import { createMiddleware } from "@tanstack/react-start" import { type AuthUser, REFRESH_TOKEN_MUTATION, resolveSessionAction, } from "@wp-reactor/auth" import { createServerGraphQLClient } from "@wp-reactor/headless-core" import { runtimeEnv } from "../env" import { useAppSession } from "./session" export interface AuthContext { isAuthenticated: boolean user: AuthUser | null authToken: string } /** * Coque (Option B) : lit la session scellée, décide via `resolveSessionAction` * (helper PUR du package), rafraîchit/purge le JWT, et expose `{ isAuthenticated, * user, authToken }` aux serverFns. Aucun token ne transite vers le client. */ export const authMiddleware = createMiddleware().server(async ({ next }) => { const session = await useAppSession() const data = session.data const tokens = { authToken: data.authToken ?? "", refreshToken: data.refreshToken ?? "", authTokenExpiration: data.authTokenExpiration ?? 0, refreshTokenExpiration: data.refreshTokenExpiration ?? 0, } let authToken = tokens.authToken let user: AuthUser | null = data.user ?? null let isAuthenticated = false switch (resolveSessionAction(tokens)) { case "authenticated": isAuthenticated = true break case "refresh": { // Même X-Forwarded-Host que login/panier (claim `iss` du JWT). const client = createServerGraphQLClient(runtimeEnv) try { const res = await client.request(REFRESH_TOKEN_MUTATION, { token: tokens.refreshToken, }) if (res?.refreshToken?.success) { authToken = res.refreshToken.authToken await session.update({ authToken, authTokenExpiration: res.refreshToken.authTokenExpiration, }) isAuthenticated = true } else { await session.clear() user = null } } catch { await session.clear() user = null } break } case "clear": await session.clear() user = null break case "anonymous": break } return next({ context: { isAuthenticated, user: isAuthenticated ? user : null, authToken: isAuthenticated ? authToken : "", } satisfies AuthContext, }) })