I am creating my own login page in Next Auth and I have encountered a problem. After submitting the form, I check if the data is correct. If it is, I send JWT and redirect to /dashboard
– it works as I would like. However, if the login data is incorrect I would like to return an error to my login page. However, when I return return null
, the response status is 200, as if there is no error. Only the error property changes.
Currently, I base the return on the error
and display the error based on it:
Login page:
const Login = () => {
const router = useRouter();
const [loginError, setLoginError] = useState();
const handleLogin = async (e) => {
e.preventDefault();
const login = e.target[0].value;
const password = e.target[1].value;
if (login.length && password.length) {
const res = await signIn("credentials", {
login,
password,
redirect: false,
});
if (res.error) setLoginError(true);
if (!res.error) router.push("/dashboard");
}
};
return (
<div className={styles.login}>
<form onSubmit={handleLogin} className={styles.form}>
<h2 className={styles.header}>Login</h2>
<input
type="text"
placeholder="Login"
className={styles.input}
/>
<input
type="password"
placeholder="Hasło"
className={styles.input}
/>
<button className={styles.button}>Log in</button>
</form>
{loginError && <div>ERROR</div>}
</div>
);
};
export default Login;
Route:
export const authOptions = {
providers: [
CredentialsProvider({
id: "credentials",
type: "credentials",
credentials: {
login: {
label: "login",
type: "text",
},
password: { label: "Password", type: "password" },
},
async authorize(credentials) {
try {
await connect();
const user = await User.findOne({
login: credentials.login,
});
if (!user) return null;
const isPasswordValid = await bcrypt.compare(
credentials?.password,
user?.password
);
if (isPasswordValid) {
const { password, _id: id, ...userRest } = user?._doc;
const userWithoutPassword = { id, ...userRest };
const accessToken = signJwtAccessToken({
userWithoutPassword,
});
return { ...userWithoutPassword, accessToken };
} else {
return null;
}
} catch (error) {
return new NextResponse("Database Error", { status: 500 });
}
},
}),
],
callbacks: {
async jwt({ token, user }) {
return { ...token, ...user };
},
async session({ session, token }) {
session.user = token;
session.accessToken = token.accessToken;
return session;
},
},
pages: {
signIn: "/login",
},
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
However, is this a good approach? Is it possible to return {status: 401, ok: false}
?
2
Answers
You are returning null in case the data is invalid.
null !== Error
. You need to throw error if the data is invalid.Something like this:
It is a bug in NextAuth but there is a workaround.