Files
konstitisyon.nu/app/api/auth/[...nextauth]/options.js
T

116 lines
3.4 KiB
JavaScript
Raw Normal View History

/* eslint-disable new-cap */
2024-05-20 04:14:16 +04:00
import CredentialsProvider from 'next-auth/providers/credentials'
import {readMe, withToken} from '@directus/sdk'
import {directusClient} from '@/lib/directus.js'
const apiUrl = process.env.DIRECTUS_API_URL
const nextauthSecret = process.env.NEXTAUTH_SECRET
// On rafraîchit 60s avant l'échéance réelle pour éviter les races
const REFRESH_MARGIN_MS = 60 * 1000
/**
* Appelle l'endpoint Directus /auth/refresh et retourne les nouveaux tokens.
* Lève une erreur si le refresh échoue (refresh_token expiré ou révoqué).
*
* @param {string} refreshToken
* @returns {Promise<{accessToken: string, refreshToken: string, accessTokenExpires: number}>}
*/
async function refreshDirectusToken(refreshToken) {
const res = await fetch(`${apiUrl}/auth/refresh`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({refresh_token: refreshToken, mode: 'json'}),
})
if (!res.ok) {
throw new Error(`Directus refresh failed with status ${res.status}`)
}
const {data} = await res.json()
return {
accessToken: data.access_token,
refreshToken: data.refresh_token,
accessTokenExpires: Date.now() + (data.expires ?? 900_000) - REFRESH_MARGIN_MS,
}
}
2024-05-20 04:14:16 +04:00
export const options = {
providers: [
CredentialsProvider({
2024-05-20 04:14:16 +04:00
name: 'Credentials',
credentials: {
email: {},
password: {}
},
async authorize(credentials) {
const res = await fetch(`${apiUrl}/auth/login`, {
method: 'POST',
body: JSON.stringify(credentials),
headers: {'Content-Type': 'application/json'}
})
const user = await res.json()
if (res.ok && user) {
return user
}
return null
}
})
],
2024-06-21 09:57:05 +04:00
trustHost: true,
2024-05-20 04:14:16 +04:00
secret: nextauthSecret,
pages: {
signIn: '/login'
},
callbacks: {
async jwt({token, user, account}) {
// Connexion initiale : enrichissement du token avec les données Directus
2024-05-20 04:14:16 +04:00
if (account && user) {
const userData = await directusClient.request(
withToken(
user.data.access_token,
readMe({fields: ['*']})
2024-05-20 04:14:16 +04:00
)
)
2024-05-23 18:43:53 +04:00
2024-05-20 04:14:16 +04:00
return {
...token,
accessToken: user.data.access_token,
refreshToken: user.data.refresh_token,
accessTokenExpires: Date.now() + (user.data.expires ?? 900_000) - REFRESH_MARGIN_MS,
user: userData,
2024-05-20 04:14:16 +04:00
}
}
// Token encore valide : on le retourne sans modification
if (Date.now() < token.accessTokenExpires) {
return token
}
// Token expiré : tentative de rafraîchissement silencieux
try {
const refreshed = await refreshDirectusToken(token.refreshToken)
return {...token, ...refreshed}
} catch (refreshError) {
console.error('Refresh token Directus échoué :', refreshError.message)
return {...token, error: 'RefreshAccessTokenError'}
}
2024-05-20 04:14:16 +04:00
},
async session({session, token}) {
2024-05-23 18:43:53 +04:00
session.user.userId = token.user.id
session.user.username = token.user.first_name
session.user.accessToken = token.accessToken
session.user.refreshToken = token.refreshToken
session.user.token = token.user.token
session.user.email = token.user.email
session.user.password = token.user.password
session.error = token.error
2024-05-20 04:14:16 +04:00
return session
}
}
}