Server action for signIn function
Unanswered
TK2 posted this in #help-forum
TK2OP
I was finally able to get more meaningful error message returned when credentials are incorrect during sign in. I'm just wondering if this could be simplified any further or if I'm missing something
And here is where I'm calling the function in my login page
authenticate server action'use server'
import { signIn } from '@/auth'
import { AuthError } from 'next-auth';
export async function authenticate(email: string, password: string, values: Object) {
try {
console.log("values inside authenticate()", email, password)
await signIn("credentials", {
email: email,
password: password,
redirect: false
})
} catch (error) {
if (error instanceof AuthError) {
switch (error.type) {
case 'CredentialsSignin':
return 'Invalid credentials.';
default:
return 'Something went wrong.';
}
}
throw error;
}
}And here is where I'm calling the function in my login page
const handleServerSignIn = async (
values: z.infer<typeof signInSchema>,
e,
) => {
e.preventDefault();
try {
console.log("values in handleServerSignIn", values);
const data = await authenticate(values.email, values.password);
console.log("data", data);
if (data) {
toast({
title: "Error",
description: data,
variant: "destructive",
});
} else {
router.refresh();
router.push("/dashboard/admin");
}
} catch (error) {
console.log("error catch handleServerSignIn()", error);
}
};6 Replies
TK2OP
For reference my
auth.config I have extending CredentialsSignIn and throwing error strings but have no successfully been able to return those errors to client after failed signinclass InvalidEmailError extends CredentialsSignin {
code = "Email is not associated with any existing user."
}
class InvalidPasswordError extends CredentialsSignin {
code = "Password does not match our records."
}
class InvalidLoginError extends CredentialsSignin {
code = "Invalid credentials."
}
export default {
providers:
[
GitHub,
Google,
CredentialsProvider({
id: "credentials",
name: "Credentials",
credentials: {
email: {
label: "Email",
type: "text",
placeholder: "example@gmail.com"
},
password: {
label: "password",
type: "password",
placeholder: "************"
},
},
authorize: async (credentials) => {
try {
console.log("Credentials inside authorize function", credentials);
const { email, password } = await signInSchema.parseAsync(credentials);
console.log("parseAsync credentials ", email, password)
const user = await prisma.user.findUnique({
where: { email: email.toLowerCase() },
})
console.log("user look up", user);
// throw error that email is not found
if (!user) {
throw new InvalidEmailError();
};
// compare passwords and throw password doesn't match records error
if (!bcryptjs.compareSync(password, user.password)) {
throw new InvalidPasswordError();
}
const { password: _, ...rest } = user;
return user;
} catch(error) {
console.log("error inside catch block authorize()")
throw new InvalidLoginError();
}
}
}),
],
} satisfies NextAuthConfigTK2OP
hmm
You can’t throw in a server action. Just return a object with an error message in it
{error:error.message}
You can’t throw specific data from a server action this is an intended function as it stops leakage of server side secrets
There’s also a nice doc on throwing in server actions someone from the discord made but I gotta find it later I’m mobile