import axios from "axios"; import moment from "moment"; import { AuthOptions, Session } from "next-auth"; import { JWT } from "next-auth/jwt"; moment.locale("fr"); export const authOptions: AuthOptions = { providers: [ { id: "oauth", name: process.env.OAUTH_PROVIDER_NAME, type: "oauth", clientId: process.env.OAUTH_CLIENT_ID, clientSecret: process.env.OAUTH_CLIENT_SECRET, authorization: { url: process.env.OAUTH_AUTHORIZATION_URL, params: { scope: "openid profile offline_access", response_type: "code", }, }, checks: ["pkce", "state"], idToken: true, token: process.env.OAUTH_TOKEN_URL, userinfo: process.env.OAUTH_USERINFO_URL, issuer: process.env.OAUTH_ISSUER, jwks_endpoint: process.env.OAUTH_JWKS_ENDPOINT, profile(profile: Session["user"]) { return { id: profile.sub || profile.id, name: profile.name || profile.preferred_username || `${profile.given_name} ${profile.family_name}`, }; }, }, ], callbacks: { async jwt({ token, account, user }) { if (account && user) { token.accessToken = account.access_token; token.accessTokenExpires = moment(account.expires_at * 1000).subtract(5, "s"); token.refreshToken = account.refresh_token; token.user = user; return token; } if (moment().isBefore(moment(token.accessTokenExpires))) { return token; } return refreshAccessToken(token); }, async session({ session, token }) { if (token) { session.user = token.user; session.accessToken = token.accessToken; session.accessTokenExpires = token.accessTokenExpires; session.error = token.error; } return session; }, }, pages: { signIn: "/auth/login", signOut: "/auth/logout", } }; const refreshAccessToken = async (token: JWT): Promise => { const response = await axios.post<{ access_token: string; expires_in: number; refresh_token: string; error_description?: string; }>( process.env.OAUTH_TOKEN_URL, { grant_type: "refresh_token", refresh_token: token.refreshToken, client_id: process.env.OAUTH_CLIENT_ID, client_secret: process.env.OAUTH_CLIENT_SECRET, }, { headers: { "Content-Type": "application/x-www-form-urlencoded", }, } ); if (response.status != 200) { throw new Error( response.data.error_description || "Failed to refresh access token" ); } return { ...token, accessToken: response.data.access_token, accessTokenExpires: moment().add(response.data.expires_in, "seconds").subtract(5, "s"), refreshToken: response.data.refresh_token, }; };