I am developing a next.js application, I use nextauth to manage the connection. I coded my api and my sql database.
When I connect and the credentials are correct, I have my API that interacts with my mysql database and returns a status 200 to indicate that the credentials are good but I do not have a redirection to my main page. Modifying the url directly does not seem to work either
here is my options.ts file in /app/api/auth/[...nextauth] :
import type { NextAuthOptions } from 'next-auth'; // Import the 'Profile' type from 'next-auth'
import GoogleProvider from 'next-auth/providers/google';
import CredentialsProvider from 'next-auth/providers/credentials';
import axios from 'axios';
import bcrypt from 'bcrypt';
import ChangePasswordDialog from '@/components/changePasswordDialog';
export const options: NextAuthOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
}),
CredentialsProvider({
name: 'Credentials',
credentials: {},
async authorize(credentials) {
const { email, password } = credentials as { email: string, password: string };
console.log('Credentials :', credentials );
try {
const { data: users } = await axios.get(process.env.API_URL + 'utilisateurs/EmailsAndPasswords');
if (credentials) {
const user = users.find((user: any) => user.email === email);
if (user) {
const isMatch = await bcrypt.compare(password, user.password_hash);
console.log(user);
if (isMatch) {
return user;
} else {
return null;
}
} else {
return null;
}
}
console.log('Aucun credential fourni');
return null;
} catch (error) {
console.error('Erreur lors de l\'authentification:', error);
return null;
}
}
})
],
session: {
strategy: 'jwt', // Utiliser JWT pour gérer les sessions
maxAge: 30 * 60, // Durée de vie du token
},
jwt: {
secret: process.env.JWT_SECRET as string,
},
secret: process.env.JWT_SECRET as string,
callbacks: {
async signIn({ user, account, profile }) {
if (account && account.provider === 'google') {
if (!profile?.email) {
throw new Error('No email returned from Google');
}
const emailDomain = '@epfprojets.com';
if (profile.email.endsWith(emailDomain)) {
return true;
} else {
return false;
}
}
return true;
},
async jwt({ token, user }) {
if (user) {
token.id = user.id;
token.email = user.email;
token.name = user.name;
}
return token;
},
async session({ session, token }) {
session.user = {
email: token.email as string,
name: token.name as string,
};
return session;
},
async redirect({ url, baseUrl }: { url: string; baseUrl: string; }) {
return url.startsWith(baseUrl) ? url : baseUrl;
}
},
};
and here is the login page I created in /app/api/auth
"use client"
import Link from "next/link"
import { signIn } from "next-auth/react"
import {useSession} from "next-auth/react"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { SessionProvider } from 'next-auth/react';
import { Button } from "@/components/ui/button"
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Separator } from "@/components/ui/separator"
export default function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const router = useRouter();
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
const res = await signIn('credentials', {
email,
password,
redirect: false
});
if (res && res.error) {
setError("Email ou mot de passe incorrect");
}
} catch (error) {
console.log(error);
};
}
return (
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Enter your email below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit}>
<div className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="[email protected]"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="grid gap-2">
<div className="flex items-center">
<Label htmlFor="password">Password</Label>
<Link href="#" className="ml-auto inline-block text-sm underline">
Forgot your password?
</Link>
</div>
<Input id="password" type="password" required value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="By Quentin Dufour" />
</div>
{error && (
<div className="m-auto">
<Label htmlFor="error" className="bg-red-500 text-white w-fit text-sm py-1 px-3 rounded-md mt-2">
{error}
</Label>
</div>
)}
<Button type="submit" className="w-full">
Login
</Button>
<Separator className="h-[2px]"/>
<Button variant="outline" className="w-full">
Login with Google
</Button>
</div>
</form>
</CardContent>
</Card>
)
}
Here is my middleware.js:
export { default } from "next-auth/middleware";
I have several avenues that I am looking into without much conviction:
- the lines :
jwt: {
secret: process.env.JWT_SECRET as string,
},
secret: process.env.JWT_SECRET as string,
seem to be a source of the problem. When I comment out these lines, I can manually redirect to my main page by modifying the url after successful authentication.
- a redirect in the: callback{} in options.ts? (already tried without success for the moment)
- a router.replace() in my login page? (already tried without success for the moment)
- setting up ?
Thank you for any help you can give me and for the time you will devote to my problem.