Files
nextgo/lib/auth.ts
Beyhan Oğur 9eb7aea821 first commit
2026-04-26 22:15:25 +03:00

147 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { NextAuthOptions } from 'next-auth'
import type { JWT } from 'next-auth/jwt'
import CredentialsProvider from 'next-auth/providers/credentials'
import GitHubProvider from 'next-auth/providers/github'
import GoogleProvider from 'next-auth/providers/google'
import {
fetchRefreshedBackendJwt,
getJwtExpMs,
shouldRefreshBackendToken,
} from '@/lib/backend-jwt-refresh'
const API_BASE = process.env.API_BASE_URL ?? 'http://localhost:8080'
type AuthUser = {
id: string
email: string
username: string
accessToken: string
refreshToken: string
accessTokenExpires: number
}
async function refreshAccessToken(token: JWT): Promise<JWT> {
const next = await fetchRefreshedBackendJwt(token)
if (!next) {
return {
...token,
error: 'RefreshAccessTokenError',
}
}
return next
}
export const authOptions: NextAuthOptions = {
session: {
strategy: 'jwt',
/** NextAuth oturum çerezi ömrü (saniye) — backend refresh ile uyumlu uzun süre */
maxAge: 60 * 60 * 24 * 7,
},
secret: process.env.NEXTAUTH_SECRET ?? process.env.AUTH_SECRET,
providers: [
...(process.env.GOOGLE_CLIENT_ID && process.env.GOOGLE_CLIENT_SECRET
? [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
]
: []),
...(process.env.GITHUB_CLIENT_ID && process.env.GITHUB_CLIENT_SECRET
? [
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
}),
]
: []),
CredentialsProvider({
name: 'Credentials',
credentials: {
email: { label: 'Email', type: 'email' },
password: { label: 'Password', type: 'password' },
},
async authorize(credentials) {
const email = credentials?.email
const password = credentials?.password
if (!email || !password) return null
const res = await fetch(`${API_BASE}/api/v1/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password }),
})
if (!res.ok) return null
const data = (await res.json()) as { access: string; refresh: string }
const accessToken = data.access
const refreshToken = data.refresh
return {
id: email,
email,
username: email,
accessToken,
refreshToken,
accessTokenExpires: getJwtExpMs(accessToken),
} satisfies AuthUser
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
const authUser = user as AuthUser
// OAuth login akışında backend access/refresh token'ı yoksa refresh denemeyelim.
if (!authUser.accessToken || !authUser.refreshToken) {
return {
...token,
user: {
id: authUser.id,
email: authUser.email,
username: authUser.username ?? authUser.email,
},
}
}
return {
...token,
accessToken: authUser.accessToken,
refreshToken: authUser.refreshToken,
accessTokenExpires: authUser.accessTokenExpires,
user: {
id: authUser.id,
email: authUser.email,
username: authUser.username,
},
}
}
if (token.error === 'RefreshAccessTokenError') {
return token
}
if (!shouldRefreshBackendToken(token)) {
return token
}
return refreshAccessToken(token)
},
async session({ session, token }) {
session.user = {
...(session.user ?? {}),
...(token.user ?? {}),
}
session.accessToken = token.accessToken
session.refreshToken = token.refreshToken
session.error = token.error
return session
},
},
pages: {
signIn: '/auth/login',
},
}