// file: ~/server/api/auth/[...].ts import { NuxtAuthHandler } from '#auth' import CredentialsProvider from 'next-auth/providers/credentials'; import GithubProvider from 'next-auth/providers/github' import GoogleProvider from 'next-auth/providers/google'; import type { JWT } from 'next-auth/jwt'; const config = useRuntimeConfig(); const API_BASE_URL = config.public.BASE_API_URL || (config.public as { NUXT_PUBLIC_API_BASE?: string }).NUXT_PUBLIC_API_BASE || 'http://127.0.0.1:8080'; // Helper to refresh the access token async function refreshAccessToken(token: JWT): Promise { try { if (!token.refreshToken) { throw new Error("No refresh token available"); } const response = await fetch(`${API_BASE_URL}/api/v1/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify({ refresh_token: token.refreshToken }), }); const refreshedProperies = await response.json(); if (!response.ok) { throw refreshedProperies; } return { ...token, accessToken: refreshedProperies.access_token, refreshToken: refreshedProperies.refresh_token ?? token.refreshToken, // Fallback to old refresh token accessTokenExpires: Date.now() + 15 * 60 * 1000, // Varsayılan 15 dk, backend yanıtına göre ayarlanabilir }; } catch (error) { console.error('RefreshAccessTokenError', error); return { ...token, error: 'RefreshAccessTokenError', }; } } export default NuxtAuthHandler({ secret: config.authSecret, //debug: false, providers: [ // @ts-expect-error next-auth provider default export typing GithubProvider.default({ clientId: config.githubClientId, clientSecret: config.githubClientSecret }), // @ts-expect-error next-auth provider default export typing GoogleProvider.default({ clientId: config.googleClientId, clientSecret: config.googleClientSecret }), // @ts-expect-error next-auth provider default export typing CredentialsProvider.default({ name: 'Credentials', credentials: { email: { label: 'Email', type: 'email' }, password: { label: 'Password', type: 'password' }, turnstile_token: { label: 'Turnstile', type: 'text' } }, async authorize(credentials) { if (!credentials?.email || !credentials?.password) return null; const turnstileToken = credentials.turnstile_token as string | undefined; if (!turnstileToken) return null; try { const validation = await verifyTurnstileToken(turnstileToken); if (!validation.success) return null; } catch { return null; } try { const res = await fetch(`${API_BASE_URL}/api/v1/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: credentials.email, password: credentials.password }) }); const user = await res.json(); // Backend dönüş formatı: { access_token, refresh_token, user: { ... } } if (res.ok && user.access_token && user.user) { return { ...user.user, // id, email, username, is_admin vb. access_token: user.access_token, refresh_token: user.refresh_token, }; } return null; } catch (error) { console.error('Login error:', error); return null; } } }) ], callbacks: { async jwt({ token, user, account }) { // Initial sign in if (account && user) { // Social login case handled here if needed, consistent with Credentials // Eğer social login backend değişimi yapılacaksa burası da güncellenmeli. // Şimdilik Credentials akışına odaklanıyoruz. return { ...token, accessToken: user.access_token, refreshToken: user.refresh_token, accessTokenExpires: Date.now() + 15 * 60 * 1000, // 15 dakika id: user.id as number, email: user.email as string, username: user.username as string, first_name: user.first_name as string, last_name: user.last_name as string, is_admin: user.is_admin as boolean, // Diğer alanlar }; } // Return previous token if the access token has not expired yet if (Date.now() < (token.accessTokenExpires as number)) { return token; } // Access token has expired, try to update it return refreshAccessToken(token); }, async session({ session, token }) { if (token) { session.user.id = token.id; session.user.email = token.email; session.user.username = token.username; session.user.first_name = token.first_name; session.user.last_name = token.last_name; session.user.is_admin = token.is_admin; session.accessToken = token.accessToken; session.refreshToken = token.refreshToken; session.error = token.error; } return session; } }, pages: { signIn: '/auth/login', newUser: '/auth/register' // Opsiyonel }, session: { strategy: 'jwt' }, // Debug only in development debug: process.env.NODE_ENV === 'development', })