import type { H3Event } from "h3"; import { jwtDecode } from "jwt-decode"; import type { User } from "#auth-utils"; import type { AuthUserFragment, AuthLoginMutationResult } from "#graphql/operations"; import { AuthRefreshTokenDocument } from "#graphql/operations"; import type { ResultOf } from "#graphql/registry"; // Handle login result and store user session export async function handleLogin(event: H3Event, loginResult: AuthLoginMutationResult) { if (!loginResult?.login) { return false; } const { user, authToken, refreshToken } = loginResult.login; if (!user || !authToken || !refreshToken) { return false; } await setUserSession(event, { user: getAuthUser(user), secure: { authToken, refreshToken, }, loggedInAt: new Date().toISOString(), }); return true; } // Handle user logout by clearing session export async function handleLogout(event: H3Event) { await clearUserSession(event); return true; } // Convert AuthUserFragment to nuxt-auth-utils User function getAuthUser(user: AuthUserFragment): User { return { id: Number(user.id), email: user.email!, roles: extractNodes(user.roles).map(({ name }) => name!) || [], }; } // Track in-flight refreshAuthToken calls to prevent duplicate requests const refreshTokenPromises = new Map>(); // Refresh auth token by calling remote GraphQL endpoint directly export async function refreshAuthToken(refreshToken: string): Promise { // Return existing in-flight promise if available const inFlight = refreshTokenPromises.get(refreshToken); if (inFlight) { return inFlight; } const refreshPromise = (async () => { console.log(`Refreshing auth token: ${refreshToken}`); const { public: { wpUrl } } = useRuntimeConfig(); const endpoint = `${wpUrl}/graphql`; const { data } = await executeGraphQLHTTP>({ query: AuthRefreshTokenDocument, variables: { refreshToken }, }, { endpoint }); return data?.refreshToken?.authToken || undefined; })(); refreshTokenPromises.set(refreshToken, refreshPromise); return refreshPromise.finally(() => { const current = refreshTokenPromises.get(refreshToken); if (current === refreshPromise) { refreshTokenPromises.delete(refreshToken); } }); } // Get auth token from user session (refresh if needed) export async function getAuthToken(event: H3Event): Promise { // Retrieve user session, return if none const session = await getUserSession(event); if (!session.secure) { return; } // Extract tokens and check expiration const { authToken, refreshToken } = session.secure; const decoded = jwtDecode<{ exp: number }>(authToken); const isExpired = decoded.exp * 1000 < Date.now(); if (isExpired) { try { const newAuthToken = await refreshAuthToken(refreshToken); if (!newAuthToken) { throw new Error("Impossible de rafraƮchir le jeton d'authentification."); } session.secure.authToken = newAuthToken; await setUserSession(event, session); } catch { await clearUserSession(event); return; } } return session.secure.authToken; }