Next.js Discord

Discord Forum

Sign in implementation with Server Actions

Answered
Almond stone wasp posted this in #help-forum
Open in Discord
Avatar
Almond stone waspOP
I'm trying to implement a sign in page using server actions as the <form> action.
This is what I've done so far:
async function attemptSignIn(data: FormData) {
  "use server";

  type QueryUser = { id: number; password_hash: string; }

  let db = await openDb();

  let user = await db.get<QueryUser>("SELECT id, password_hash FROM users WHERE handle = ?", [data.get("username")]);
  if (!user)
    return; /* Somehow show "Invalid username or password" in the form element ??? */

  // auth stuff...

  return; // Somehow set cookie and redirect to / ???
}

export default function SignIn() {
  return (
    <form
      action={attemptSignIn}
      className="bg-white border rounded-lg px-4 py-4 w-full max-w-96"
    >
      {/* form stuff... */}
    </form>
  );
}

Basically, I'm not sure how am I supposed to implement the functionality to tell the form that an error occurred and show a message like "Invalid username or password", or even setting the session token cookie and redirect to /
Any ideas how I can do that? Or maybe I shouldn't use server actions?
Answered by Alfonsus Ardani
try import from useFormState
View full answer

31 Replies

Avatar
Alfonsus Ardani
You can set message in search params.

On sucess, you can set token cookie and redirect to /

Its pretty straightforward...
Avatar
B33fb0n3
### Error Handling
In your case I would use: [next-safe-action](https://next-safe-action.dev/docs/safe-action-client/custom-server-error-handling). Not for the safe handling, but for the error handling part. So you call the function via the hook useAction for example, do your db stuff inside your server action and if there is no user for example you will throw an error like throw new Error("user not found"). Inside your next-safe-action you can check weither send this message to the user (so he see's it) or show a basic error like there was an unknown error.
### Setting Session Token
You can directly set cookies inside your server actions if you need to and if you know what you are doing. Else I recommend you to use [nextauth](https://next-auth.js.org/).
### Redirect
You can also directly redirect inside your server action using [the redirect function](https://nextjs.org/docs/app/building-your-application/routing/redirecting#redirect-function).
Avatar
Almond stone waspOP
If I set message in search params, a malicious user can set an arbitrary message to trick someone, like /sign-in?message=Check your e-mail to reactivate your account or something.
I just realized that I can use the redirect function, like @B33fb0n3 said. I thought I had to use the router, which is client only.
I found also about useActionState, which looks like it would help me, but it doesn't work:
TypeError: (0 , react__WEBPACK_IMPORTED_MODULE_5__.useActionState) is not a function or its return value is not iterable
    at SignIn (./app/sign-in/page.tsx:20:86)
digest: "3991891092"
   8 |
   9 | export default function SignIn() {
> 10 |   const [state, formAction] = useActionState(attemptSignIn, { errorMsg: "" });
     |                                              ^
  11 |
  12 |   return (
  13 |     <div className="flex justify-center mt-4">
 GET /sign-in 500 in 6307ms
Image
I will try next-safe-action
Avatar
Alfonsus Ardani
If I set message in search params, a malicious user can set an arbitrary message to trick someone, like /sign-in?message=Check your e-mail to reactivate your account or something.
And do what?
you can handle it in the client-side using useActionState or just any ordinary client-side handling logic to display the message
i.e using react-hook-form and use form = useForm() and form.setErrors(...) to display it
Avatar
Almond stone waspOP
He can send a fake e-mail or trick the victim into doing something, thinking it's the real website giving those messages
useActionState doesn't look to be working on last release yet 😢
Avatar
Alfonsus Ardani
all he does is signing in to your website, not their website :/
i mean
its how the message is usually set on progressive enhanced websites
Avatar
Alfonsus Ardani
try import from useFormState
Answer
Avatar
Alfonsus Ardani
its the name of the funciton before it was renamed to useActionState
Avatar
Almond stone waspOP
Ohh alright, will give it a try
Avatar
Alfonsus Ardani
if you want more / it doesnt work, most people use rhf + zod. those could work with next-safe-action too
also, did you found out with the cookies() function
Avatar
B33fb0n3
any reason, why you don't want to use this approach? https://nextjs-forum.com/post/1240321753994104862#message-1240327283332612177
Avatar
Almond stone waspOP
Yeah, it's working fine
Image
No reason, I was just looking in the stuff built-in in Next.js
But I don't have an issue using it either
And for now I won't use nextauth because my auth is very barebones, I'm just experimenting Next.js
Avatar
Alfonsus Ardani
understandable, sometimes it can be mentally demanding to learn a new lib
next-safe-action, if 0 is clsx and 5 is material UI, i would give it a 1.5 in terms of learnability
Avatar
B33fb0n3
for me I learned the library way to fast. I just copied the docs and understod it. That's crazy simple
Avatar
Alfonsus Ardani
yeah ultimately its just a wrapper, like clsx lol
Avatar
B33fb0n3
yea ong
Avatar
Almond stone waspOP
The useFormState approach is working, nice!
For fun I will try next-safe-action as well
Thanks @Alfonsus Ardani @B33fb0n3 💯
Avatar
B33fb0n3
happy to help ^^