Sign in implementation with Server Actions
Answered
Almond stone wasp posted this in #help-forum
Almond stone waspOP
I'm trying to implement a sign in page using server actions as the
This is what I've done so far:
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?
<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?
31 Replies
Alfonsus Ardani
You can set message in search params.
On sucess, you can set token cookie and redirect to
Its pretty straightforward...
On sucess, you can set token cookie and redirect to
/
Its pretty straightforward...
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
### 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).
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).
Almond stone waspOP
If I set message in search params, a malicious user can set an arbitrary message to trick someone, like
I just realized that I can use the
/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
I will try
next-safe-action
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 itAlmond 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 😢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
Alfonsus Ardani
try
import from useFormState
Answer
Alfonsus Ardani
its the name of the funciton before it was renamed to useActionState
Almond stone waspOP
Ohh alright, will give it a try
Alfonsus Ardani
if you want more / it doesnt work, most people use rhf + zod. those could work with
next-safe-action
tooalso, did you found out with the cookies() function
B33fb0n3
any reason, why you don't want to use this approach? https://nextjs-forum.com/post/1240321753994104862#message-1240327283332612177
Almond stone waspOP
Yeah, it's working fine
No reason, I was just looking in the stuff built-in in Next.js
But I don't have an issue using it either
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.jsAlfonsus 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 learnabilityB33fb0n3
for me I learned the library way to fast. I just copied the docs and understod it. That's crazy simple
Alfonsus Ardani
yeah ultimately its just a wrapper, like clsx lol
B33fb0n3
yea ong
Almond stone waspOP
The
useFormState
approach is working, nice!For fun I will try
next-safe-action
as wellThanks @Alfonsus Ardani @B33fb0n3 💯
B33fb0n3
happy to help ^^