feat: Implement a comprehensive two-factor authentication system including setup, verification, backup codes, and integration into the login flow.
This commit is contained in:
41
src/auth.ts
41
src/auth.ts
@@ -30,8 +30,42 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
credentials: {
|
||||
email: { label: "Email", type: "email" },
|
||||
password: { label: "Password", type: "password" },
|
||||
accessToken: { label: "Access Token", type: "text" },
|
||||
refreshToken: { label: "Refresh Token", type: "text" },
|
||||
},
|
||||
async authorize(credentials) {
|
||||
// Handle 2FA completion - tokens are passed directly
|
||||
if (credentials?.accessToken && credentials?.refreshToken) {
|
||||
// Verify the tokens by fetching current user
|
||||
const verifyRes = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/auth/me`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Bearer ${credentials.accessToken}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
if (verifyRes.ok) {
|
||||
const userData = await verifyRes.json();
|
||||
if (userData.success) {
|
||||
return {
|
||||
id: userData.data.id,
|
||||
email: userData.data.email,
|
||||
name: `${userData.data.firstName || ""} ${userData.data.lastName || ""}`.trim(),
|
||||
role: userData.data.role,
|
||||
accessToken: credentials.accessToken,
|
||||
refreshToken: credentials.refreshToken,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Invalid authentication tokens");
|
||||
}
|
||||
|
||||
// Standard login flow
|
||||
const res = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_API_URL}/auth/login`,
|
||||
{
|
||||
@@ -46,6 +80,13 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
// Check if 2FA is required
|
||||
if (res.ok && data.data?.requiresTwoFactor) {
|
||||
// Return null to indicate 2FA is required
|
||||
// The frontend will handle the redirect
|
||||
throw new Error("2FA_REQUIRED");
|
||||
}
|
||||
|
||||
if (res.ok && data.success) {
|
||||
return {
|
||||
id: data.data.user.id,
|
||||
|
||||
Reference in New Issue
Block a user