I am using next-auth credentials in my next project, but It seems that the signIn()
from next-auth/react
is not working correctly. I still get redirected to admin page no matter if the login info is correct or not.
{error: null, status: 200, ok: true, url: 'https://localhost:3000/api/auth/signin?csrf=true'}
Here is some information
app/components/forms/SignInForm.tsx
'use client';
import { useRouter } from 'next/navigation';
import { redirect } from 'next/dist/server/api-utils';
import { signIn } from 'next-auth/react'; // Fixed import
const SignInForm = () => {
const router = useRouter();
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
email: '',
password: '',
},
});
const onSubmit = async (values: z.infer<typeof FormSchema>) => {
try {
// I have verified that values.email and values.password are correct!
// I think that signIn is where the problem is!
const signInData = await signIn("credentials", {
email: values.email,
password: values.password,
redirect: false,
});
if(signInData?.error) {
console.log(signInData.error)
} else{
router.push("/admin");
}
} catch (error) {
console.error("Error signing in:", error);
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='w-full'>
<div className='space-y-2'>
<FormField
control={form.control}
name='email'
render={({ field }) => (
<Input placeholder='[email protected]' {...field} />
)}
/>
<FormField
control={form.control}
name='password'
render={({ field }) => (
<Input
type='password'
placeholder='Enter your password'
{...field}
/>
)}
/>
</div>
<Button className='w-full mt-6' type='submit'>
Sign in
</Button>
</form>
</Form>
);
};
export default SignInForm;
app/api/auth/[…nextauth]/route.ts
import NextAuth from "next-auth";
import { authOptions } from "@/lib/auth";
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST}
app/lib/auth.ts
import { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { db } from "./db";
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(db),
session: {
strategy: 'jwt'
},
pages: {
signIn: '/sign-in'
},
providers: [
CredentialsProvider({
name: "credentials",
credentials: {
email: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
// removing logic to see why I am still being redirected
return null
}
})
]
}
I am unsure why I am still being redirected to /admin
even though I clearly put return null
on the auth.ts. Any help would be greatly appreciated.
2
Answers
Verify that the signIn call correctly interprets the
redirect: false
and the logic within your signIn function’s if-else block. If signInData?.error is not truthy (because authorize returns null, which might not set an error as expected), the code proceeds to redirect to /admin.Check for Undefined: Modify your if-else block:
Handle Sign-In Failure: Introduce a way to notify the user of an unsuccessful sign-in:
I had a very similar issue with a Next 13 IT Helpdesk project I was working on a couple months ago, so hopefully this helps you out.
I dont see
SessionProvider
is wrapping your app. that is whysignIn
function is not communicating withauthorize
in the
RootLayout