@oauth42/next 0.4.8 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -2
- package/dist/build-manifest.json +59 -0
- package/dist/client/index.d.mts +15 -6
- package/dist/client/index.d.ts +15 -6
- package/dist/client/index.js +23 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +23 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/index-BuZTiUds.d.mts +144 -0
- package/dist/index-BuZTiUds.d.ts +144 -0
- package/dist/index.d.mts +20 -2
- package/dist/index.d.ts +20 -2
- package/dist/index.js +617 -104
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +613 -103
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/index.d.mts +3 -39
- package/dist/middleware/index.d.ts +3 -39
- package/dist/middleware/index.js +283 -34
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +284 -34
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/{auth-BThRQMzh.d.ts → par-Cyu6M1e6.d.mts} +36 -11
- package/dist/{auth-BThRQMzh.d.mts → par-DQNt8j-s.d.ts} +36 -11
- package/dist/server/index.d.mts +7 -3
- package/dist/server/index.d.ts +7 -3
- package/dist/server/index.js +657 -123
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +650 -122
- package/dist/server/index.mjs.map +1 -1
- package/package.json +14 -5
- package/src/types/index.ts +2 -0
- package/src/types/next-auth.d.ts +2 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.ts","../src/server/auth.ts","../src/server/session.ts","../src/server/middleware.ts"],"sourcesContent":["// Main exports\nexport { OAuth42Provider } from './provider';\nexport type { OAuth42Profile, OAuth42ProviderOptions } from './provider';\n\n// Server-side exports\nexport { createAuth, getServerSession, refreshAccessToken } from './server/auth';\nexport type { CreateAuthOptions } from './server/auth';\n\nexport { withOAuth42Auth, createMiddlewareConfig } from './server/middleware';\nexport type { OAuth42AuthOptions } from './server/middleware';\n\nexport { getOAuth42Session, withOAuth42Session, withOAuth42ServerSideProps } from './server/session';\n\n// Type exports\nexport type { OAuth42Config } from './types';\n\n// Re-export NextAuth types for convenience\nexport type { Session, User } from 'next-auth';","import type { OAuthConfig, OAuthUserConfig } from 'next-auth/providers/oauth';\n\nexport interface OAuth42Profile {\n sub: string;\n email: string;\n email_verified?: boolean;\n name?: string;\n given_name?: string;\n family_name?: string;\n picture?: string;\n username?: string;\n groups?: string[];\n id?: string;\n}\n\nexport interface OAuth42ProviderOptions {\n clientId: string;\n clientSecret: string;\n issuer?: string;\n authorizationUrl?: string;\n tokenUrl?: string;\n userinfoUrl?: string;\n scopes?: string[];\n pkceEnabled?: boolean;\n}\n\nexport function OAuth42Provider<P extends OAuth42Profile>(\n options: OAuthUserConfig<P> & Partial<OAuth42ProviderOptions>\n): OAuthConfig<P> {\n const issuer = options.issuer || process.env.OAUTH42_ISSUER || 'https://api.oauth42.com';\n const baseUrl = issuer.replace(/\\/$/, '');\n \n return {\n id: 'oauth42',\n name: 'OAuth42',\n type: 'oauth',\n version: '2.0',\n\n // Use OIDC discovery to automatically find endpoints\n wellKnown: `${baseUrl}/.well-known/openid-configuration`,\n\n // Use ID token for user profile (standard OIDC pattern)\n // This avoids an extra HTTP call to /userinfo on every auth flow\n // Apps can call /userinfo separately when they need extended claims (groups, company_id, etc.)\n idToken: true,\n\n // Also set individual endpoints for compatibility\n authorization: {\n url: `${baseUrl}/oauth2/authorize`,\n params: {\n scope: (options.scopes || ['openid', 'profile', 'email']).join(' '),\n response_type: 'code',\n },\n },\n token: `${baseUrl}/oauth2/token`,\n userinfo: `${baseUrl}/oauth2/userinfo`,\n\n client: {\n id: options.clientId,\n secret: options.clientSecret,\n token_endpoint_auth_method: 'client_secret_post',\n id_token_signed_response_alg: 'RS256', // OAuth42 uses RS256 for ID tokens\n },\n\n issuer: baseUrl,\n\n checks: options.pkceEnabled !== false ? ['pkce', 'state'] : ['state'],\n \n profile(profile: OAuth42Profile, tokens: any) {\n return {\n id: profile.sub || profile.id || profile.email,\n email: profile.email,\n emailVerified: profile.email_verified ? new Date() : null,\n name: profile.name || `${profile.given_name || ''} ${profile.family_name || ''}`.trim(),\n image: profile.picture,\n groups: profile.groups,\n };\n },\n \n style: {\n logo: '/oauth42-logo.svg',\n bg: '#1e40af',\n text: '#ffffff',\n },\n \n options,\n };\n}","import NextAuthDefault from 'next-auth';\nimport type { NextAuthOptions } from 'next-auth';\nimport { OAuth42Provider, OAuth42Profile } from '../provider';\nimport { getOAuth42Session } from './session';\n\n// Handle both CommonJS and ESM exports\nconst NextAuth = (NextAuthDefault as any).default || NextAuthDefault;\n\nexport { type NextAuthOptions };\n\n// Simple per-process lock for explicit refresh via getAccessToken()\nlet activeRefresh: Promise<any> | null = null;\n\nexport interface CreateAuthOptions {\n clientId?: string;\n clientSecret?: string;\n issuer?: string;\n scopes?: string[];\n pkceEnabled?: boolean;\n debug?: boolean;\n callbacks?: NextAuthOptions['callbacks'];\n pages?: NextAuthOptions['pages'];\n session?: NextAuthOptions['session'];\n /**\n * Unique prefix for cookie names to allow multiple apps on the same domain.\n * Each app should use a different prefix (e.g., 'portal', 'admin', 'bond').\n * This prevents session cookie conflicts when running multiple apps on localhost.\n */\n cookiePrefix?: string;\n}\n\n/**\n * Create a pre-configured NextAuth instance for OAuth42\n * This provides a simplified setup with sensible defaults\n */\nexport function createAuth(options: CreateAuthOptions = {}) {\n const clientId = options.clientId || process.env.OAUTH42_CLIENT_ID;\n const clientSecret = options.clientSecret || process.env.OAUTH42_CLIENT_SECRET;\n \n if (!clientId || !clientSecret) {\n throw new Error(\n 'OAuth42 client credentials are required. ' +\n 'Set OAUTH42_CLIENT_ID and OAUTH42_CLIENT_SECRET environment variables ' +\n 'or pass them in the options.'\n );\n }\n \n const authOptions: NextAuthOptions = {\n providers: [\n OAuth42Provider({\n clientId,\n clientSecret,\n issuer: options.issuer,\n scopes: options.scopes,\n pkceEnabled: options.pkceEnabled,\n }),\n ],\n \n callbacks: {\n async jwt({ token, account, profile }) {\n console.log('[OAuth42 SDK] JWT callback called', { hasAccount: !!account, hasProfile: !!profile });\n\n // Initial sign in - store OAuth tokens in the JWT\n if (account) {\n console.log('[OAuth42 SDK] Initial sign in - storing tokens in JWT');\n token.accessToken = account.access_token;\n token.refreshToken = account.refresh_token;\n token.expiresAt = account.expires_at;\n token.idToken = account.id_token;\n token.clientId = clientId;\n token.clientSecret = clientSecret;\n token.issuer = options.issuer || process.env.NEXT_PUBLIC_OAUTH_ISSUER || process.env.OAUTH42_ISSUER;\n }\n\n // Add user profile data\n if (profile) {\n const oauth42Profile = profile as OAuth42Profile;\n token.email = oauth42Profile.email;\n token.username = oauth42Profile.username;\n token.emailVerified = oauth42Profile.email_verified;\n token.groups = oauth42Profile.groups;\n }\n\n // NOTE: Token refresh is handled by middleware (withOAuth42Auth)\n // Middleware can properly set cookies after refresh, which JWT callback cannot\n // do in Next.js App Router Server Components.\n\n // Call custom callback if provided\n if (options.callbacks?.jwt) {\n return options.callbacks.jwt({ token, account, profile } as any);\n }\n\n console.log('[OAuth42 SDK] JWT callback complete, returning token');\n return token;\n },\n\n async session({ session, token }) {\n console.log('[OAuth42 SDK] Session callback called', { hasToken: !!token, hasSession: !!session });\n\n // Add OAuth42-specific data to session\n session.accessToken = token.accessToken as string;\n session.idToken = token.idToken as string;\n\n // Pass through any token refresh errors to the client\n if (token.error) {\n session.error = token.error as string;\n }\n\n if (session.user) {\n session.user.email = token.email as string;\n session.user.name = token.name as string;\n session.user.username = token.username as string;\n session.user.emailVerified = token.emailVerified as boolean;\n session.user.groups = token.groups as string[];\n }\n\n // Call custom callback if provided\n if (options.callbacks?.session) {\n return options.callbacks.session({ session, token } as any);\n }\n\n console.log('[OAuth42 SDK] Session callback complete, returning session');\n return session;\n },\n },\n \n pages: {\n signIn: '/auth/signin',\n signOut: '/auth/signout',\n error: '/auth/error',\n ...options.pages,\n },\n \n session: {\n strategy: 'jwt',\n ...options.session,\n },\n \n debug: options.debug || process.env.NODE_ENV === 'development',\n\n secret: process.env.NEXTAUTH_SECRET,\n\n // Configure unique cookie names per app to prevent session conflicts on localhost\n ...(options.cookiePrefix && {\n cookies: {\n sessionToken: {\n name: `${options.cookiePrefix}.session-token`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n callbackUrl: {\n name: `${options.cookiePrefix}.callback-url`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n csrfToken: {\n name: `${options.cookiePrefix}.csrf-token`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n // PKCE code_verifier cookie - essential for PKCE flow.\n // TTL covers the full OAuth round-trip including user-in-the-loop steps\n // like passkey ceremonies, MFA enrollment, and any debugging pauses.\n // The previous 15-minute value was too tight for realistic ceremony-\n // heavy flows — see #524 for the incident where state expired mid-debug.\n pkceCodeVerifier: {\n name: `${options.cookiePrefix}.pkce.code_verifier`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n maxAge: 3600, // 1 hour (was 900 — 15 min was too short for passkey/MFA flows)\n },\n },\n // State cookie for OAuth CSRF protection. Same TTL rationale as\n // pkceCodeVerifier above. State is single-use CSRF and cannot be\n // replayed, so a longer TTL does not weaken the security story.\n state: {\n name: `${options.cookiePrefix}.state`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n maxAge: 3600, // 1 hour (was 900 — 15 min was too short for passkey/MFA flows)\n },\n },\n // Nonce cookie for OpenID Connect\n nonce: {\n name: `${options.cookiePrefix}.nonce`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n },\n }),\n };\n \n // Return the configuration and handlers for API routes\n const handler = NextAuth(authOptions);\n return {\n auth: authOptions,\n handlers: { GET: handler, POST: handler },\n };\n}\n\n/**\n * Create NextAuth handlers for API routes\n */\nexport function createHandlers(authOptions: NextAuthOptions) {\n const handler = NextAuth(authOptions);\n return { GET: handler, POST: handler };\n}\n\n/**\n * Helper to get the current session server-side\n * @deprecated Use getOAuth42Session instead - this is now just an alias for backward compatibility\n * \n * This function is maintained for backward compatibility but internally\n * calls getOAuth42Session which properly handles both App Router and Pages Router\n */\nexport const getServerSession = getOAuth42Session;\n\n/**\n * Token refresh helper with simple per-process locking\n *\n * The lock prevents multiple concurrent refresh calls from the same process,\n * reducing unnecessary token churn. The backend also has a 10-second grace\n * period for blacklisted tokens, so concurrent requests across processes\n * will still succeed.\n */\nexport async function refreshAccessToken(token: any, clientId: string, clientSecret: string, issuer?: string): Promise<any> {\n // If a refresh is already in progress, wait for it\n if (activeRefresh) {\n console.log('[OAuth42] Refresh already in progress, waiting...');\n return await activeRefresh;\n }\n\n // Start the refresh and store the promise\n activeRefresh = doRefresh(token, clientId, clientSecret, issuer);\n try {\n return await activeRefresh;\n } finally {\n activeRefresh = null;\n }\n}\n\nasync function doRefresh(token: any, clientId: string, clientSecret: string, issuer?: string): Promise<any> {\n try {\n const baseUrl = issuer || process.env.OAUTH42_ISSUER || 'https://api.oauth42.com';\n const tokenUrl = `${baseUrl}/oauth2/token`;\n\n // In development, we need to handle self-signed certificates\n const fetchOptions: any = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: token.refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n };\n\n // Add agent for self-signed certificates in development\n if (process.env.NODE_ENV !== 'production' && tokenUrl.startsWith('https://')) {\n const https = await import('https');\n fetchOptions.agent = new https.Agent({\n rejectUnauthorized: false\n });\n }\n\n const response = await fetch(tokenUrl, fetchOptions);\n const refreshedTokens = await response.json();\n\n if (!response.ok) {\n throw refreshedTokens;\n }\n\n console.log('[OAuth42] Token refreshed successfully');\n return {\n ...token,\n accessToken: refreshedTokens.access_token,\n refreshToken: refreshedTokens.refresh_token ?? token.refreshToken,\n // Store expiration time in seconds (Unix timestamp)\n expiresAt: Math.floor(Date.now() / 1000) + (refreshedTokens.expires_in || 3600),\n // Explicitly remove any error property on successful refresh\n error: undefined,\n };\n } catch (error) {\n console.error('[OAuth42] Failed to refresh access token:', error);\n return {\n ...token,\n error: 'RefreshAccessTokenError',\n };\n }\n}","import { getServerSession as getNextAuthSession } from 'next-auth';\nimport { NextAuthOptions } from 'next-auth';\nimport { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from 'next';\nimport { headers } from 'next/headers';\n\n/** Header name used by middleware to pass refreshed tokens to API routes */\nconst REFRESHED_TOKEN_HEADER = 'x-oauth42-refreshed-token';\n\n/**\n * Get the OAuth42 session server-side\n *\n * This is the primary method for retrieving sessions in OAuth42 SDK.\n * Supports both Pages Router and App Router:\n *\n * App Router:\n * ```ts\n * const session = await getOAuth42Session(authOptions);\n * ```\n *\n * Pages Router:\n * ```ts\n * const session = await getOAuth42Session(req, res, authOptions);\n * ```\n *\n * **Token Refresh Support:**\n * When middleware refreshes an expired token, it passes the new token via\n * the `x-oauth42-refreshed-token` header. This function automatically detects\n * and uses that refreshed token, ensuring API routes always have a valid token.\n */\nexport async function getOAuth42Session(\n ...args:\n | [GetServerSidePropsContext['req'], GetServerSidePropsContext['res'], NextAuthOptions]\n | [NextApiRequest, NextApiResponse, NextAuthOptions]\n | [NextAuthOptions]\n) {\n const session = await getNextAuthSession(...args as any);\n\n if (!session) {\n return null;\n }\n\n // Check for refreshed token from middleware\n // This handles the race condition where middleware refreshes the token\n // but the API route still reads the old token from the session cookie\n let refreshedToken: string | null = null;\n\n try {\n // App Router: use headers() from next/headers\n if (args.length === 1) {\n const headersList = await headers();\n refreshedToken = headersList.get(REFRESHED_TOKEN_HEADER);\n }\n // Pages Router: check request headers\n else if (args.length === 3) {\n const req = args[0] as NextApiRequest | GetServerSidePropsContext['req'];\n refreshedToken = (req.headers[REFRESHED_TOKEN_HEADER] as string) || null;\n }\n } catch {\n // headers() may throw if called outside of a request context\n // This is fine - just use the session token as-is\n }\n\n if (refreshedToken) {\n const sessionToken = (session as any).accessToken as string | undefined;\n console.log('[OAuth42 Session] Using refreshed token from middleware:', {\n refreshedPrefix: refreshedToken.substring(0, 20),\n sessionPrefix: sessionToken?.substring(0, 20),\n tokensMatch: refreshedToken === sessionToken,\n });\n return {\n ...session,\n accessToken: refreshedToken,\n };\n }\n\n return session;\n}\n\n/**\n * Helper for protecting API routes\n */\nexport function withOAuth42Session(\n handler: (req: NextApiRequest, res: NextApiResponse, session: any) => Promise<void> | void,\n authOptions: NextAuthOptions\n) {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n const session = await getOAuth42Session(req, res, authOptions);\n \n if (!session) {\n return res.status(401).json({ error: 'Unauthorized' });\n }\n \n return handler(req, res, session);\n };\n}\n\n/**\n * Helper for protecting server-side props\n */\nexport function withOAuth42ServerSideProps(\n getServerSideProps: (\n context: GetServerSidePropsContext,\n session: any\n ) => Promise<any>,\n authOptions: NextAuthOptions\n) {\n return async (context: GetServerSidePropsContext) => {\n const session = await getOAuth42Session(\n context.req,\n context.res,\n authOptions\n );\n \n if (!session) {\n return {\n redirect: {\n destination: '/auth/signin',\n permanent: false,\n },\n };\n }\n \n return getServerSideProps(context, session);\n };\n}","import { NextRequest, NextResponse } from 'next/server';\nimport { getToken, encode } from 'next-auth/jwt';\n\n/**\n * Cookie chunking constants — must match NextAuth's SessionStore behavior.\n * NextAuth splits cookies at ALLOWED_COOKIE_SIZE (4096) minus overhead (163).\n * When middleware re-encodes the JWT after a token refresh, the cookie must be\n * chunked the same way, otherwise:\n * - A single cookie > ~4 KB is silently rejected by the browser\n * - Leftover chunk cookies from the original session cause SessionStore to\n * concatenate old chunks with the new base cookie, producing garbage\n */\nconst ALLOWED_COOKIE_SIZE = 4096;\nconst ESTIMATED_EMPTY_COOKIE_SIZE = 163;\nconst CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;\n\n/**\n * In-flight refresh tracking to prevent parallel refresh calls.\n * Key: user ID (from token.sub), Value: Promise that resolves with refresh result\n */\nconst pendingRefreshes = new Map<string, Promise<{\n success: boolean;\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: number;\n error?: string;\n}>>();\n\nexport interface OAuth42AuthOptions {\n pages?: {\n signIn?: string;\n error?: string;\n };\n callbacks?: {\n authorized?: (params: { token: any; req: NextRequest }) => boolean | Promise<boolean>;\n };\n protectedPaths?: string[];\n publicPaths?: string[];\n /**\n * Cookie prefix for custom cookie names. Must match the prefix used in createAuth().\n * E.g., 'oauth42-portal' will look for cookie 'oauth42-portal.session-token'\n */\n cookiePrefix?: string;\n}\n\n/**\n * Refresh tokens by calling the OAuth42 backend directly\n */\nasync function refreshTokens(\n refreshToken: string,\n clientId: string,\n clientSecret: string,\n issuer: string\n): Promise<{ success: boolean; accessToken?: string; refreshToken?: string; expiresAt?: number; error?: string }> {\n try {\n const tokenUrl = `${issuer}/oauth2/token`;\n\n const response = await fetch(tokenUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n const data = await response.json();\n\n if (!response.ok) {\n console.error('[OAuth42 Middleware] Token refresh failed:', data);\n return { success: false, error: data.error || 'refresh_failed' };\n }\n\n console.log('[OAuth42 Middleware] Token refreshed successfully');\n return {\n success: true,\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Math.floor(Date.now() / 1000) + (data.expires_in || 3600),\n };\n } catch (error) {\n console.error('[OAuth42 Middleware] Token refresh error:', error);\n return { success: false, error: 'refresh_error' };\n }\n}\n\n/**\n * Middleware helper for protecting routes with OAuth42\n *\n * This middleware handles:\n * 1. Route protection (redirect to login if no session)\n * 2. Token refresh (refresh expired tokens and update cookie)\n */\nexport function withOAuth42Auth(options: OAuth42AuthOptions = {}) {\n const secret = process.env.NEXTAUTH_SECRET;\n const clientId = process.env.OAUTH42_CLIENT_ID;\n const clientSecret = process.env.OAUTH42_CLIENT_SECRET;\n const issuer = process.env.OAUTH42_ISSUER || 'https://localhost:8443';\n\n if (!secret) {\n console.warn('[OAuth42 Middleware] NEXTAUTH_SECRET not set');\n }\n\n return async function middleware(req: NextRequest) {\n // Build cookie name - if prefix is provided, use custom name\n const cookieName = options.cookiePrefix\n ? `${options.cookiePrefix}.session-token`\n : 'next-auth.session-token';\n\n const token = await getToken({\n req: req as any,\n secret,\n cookieName,\n });\n\n const pathname = req.nextUrl.pathname;\n\n // Check if path is explicitly public\n if (options.publicPaths?.some(path => pathname.startsWith(path))) {\n return NextResponse.next();\n }\n\n // Check if path needs protection\n const needsProtection = options.protectedPaths\n ? options.protectedPaths.some(path => pathname.startsWith(path))\n : true; // Default to protecting all paths\n\n if (!needsProtection) {\n return NextResponse.next();\n }\n\n // No token at all - redirect to sign in\n if (!token) {\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n return NextResponse.redirect(url);\n }\n\n // Check if access token is expired or expiring soon (15 second buffer)\n // Buffer must be less than the token TTL to have a valid window\n const expiresAt = token.expiresAt as number | undefined;\n const now = Math.floor(Date.now() / 1000);\n const bufferSeconds = 15;\n const needsRefresh = expiresAt && now >= expiresAt - bufferSeconds;\n\n if (needsRefresh) {\n console.log('[OAuth42 Middleware] Token needs refresh:', {\n expiresAt,\n now,\n expiredAgo: expiresAt ? now - expiresAt : 'n/a',\n accessTokenPrefix: (token.accessToken as string)?.substring(0, 20),\n path: pathname,\n });\n }\n\n if (needsRefresh && token.refreshToken && clientId && clientSecret) {\n const userId = token.sub as string;\n\n // Check if there's already a refresh in progress for this user\n let refreshPromise = pendingRefreshes.get(userId);\n\n if (refreshPromise) {\n console.log('[OAuth42 Middleware] Waiting for in-flight refresh...');\n } else {\n console.log('[OAuth42 Middleware] Access token expired, refreshing...');\n\n // Create the refresh promise and store it.\n // Keep the entry for 30s after completion so late-arriving requests\n // (with stale cookies) reuse the cached result instead of triggering\n // a new refresh with the already-rotated token. See issue #470.\n refreshPromise = refreshTokens(\n token.refreshToken as string,\n clientId,\n clientSecret,\n issuer\n ).finally(() => {\n setTimeout(() => pendingRefreshes.delete(userId), 30000);\n });\n\n pendingRefreshes.set(userId, refreshPromise);\n }\n\n const refreshed = await refreshPromise;\n\n if (refreshed.success && refreshed.accessToken && refreshed.refreshToken) {\n // Update the token with new values\n const updatedToken = {\n ...token,\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken,\n expiresAt: refreshed.expiresAt,\n };\n\n // Re-encode the JWT\n const newJwt = await encode({\n token: updatedToken,\n secret: secret!,\n });\n\n // Create response with request headers that pass the new token to API routes\n // This is necessary because API routes read from the request, not the response cookie\n const requestHeaders = new Headers(req.headers);\n requestHeaders.set('x-oauth42-refreshed-token', refreshed.accessToken);\n\n const response = NextResponse.next({\n request: {\n headers: requestHeaders,\n },\n });\n\n const cookieOptions = {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n };\n\n // Set cookie with chunking matching NextAuth's SessionStore behavior.\n // Without chunking, a JWT > ~4 KB is silently rejected by the browser,\n // causing an infinite refresh loop where every request re-triggers\n // token refresh but the cookie never persists.\n if (newJwt.length <= CHUNK_SIZE) {\n // Fits in a single cookie\n response.cookies.set(cookieName, newJwt, cookieOptions);\n // Clean up any leftover chunk cookies from a previously chunked session\n for (let i = 0; ; i++) {\n const chunkName = `${cookieName}.${i}`;\n if (req.cookies.has(chunkName)) {\n response.cookies.set(chunkName, '', { ...cookieOptions, maxAge: 0 });\n } else {\n break;\n }\n }\n } else {\n // Cookie too large — chunk it like NextAuth does\n const chunkCount = Math.ceil(newJwt.length / CHUNK_SIZE);\n for (let i = 0; i < chunkCount; i++) {\n const chunkName = `${cookieName}.${i}`;\n const chunkValue = newJwt.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE);\n response.cookies.set(chunkName, chunkValue, cookieOptions);\n }\n // Delete the base cookie so SessionStore only reads chunks\n response.cookies.set(cookieName, '', { ...cookieOptions, maxAge: 0 });\n // Clean up any extra old chunks beyond the new count\n for (let i = chunkCount; ; i++) {\n const chunkName = `${cookieName}.${i}`;\n if (req.cookies.has(chunkName)) {\n response.cookies.set(chunkName, '', { ...cookieOptions, maxAge: 0 });\n } else {\n break;\n }\n }\n }\n\n // Log details to help diagnose cookie persistence issues\n const existingChunks = [];\n for (let i = 0; ; i++) {\n if (req.cookies.has(`${cookieName}.${i}`)) {\n existingChunks.push(i);\n } else {\n break;\n }\n }\n console.log(`[OAuth42 Middleware] Token refresh complete:`, {\n jwtBytes: newJwt.length,\n chunked: newJwt.length > CHUNK_SIZE,\n existingBaseCooke: req.cookies.has(cookieName),\n existingChunks: existingChunks.length > 0 ? existingChunks : 'none',\n newAccessTokenPrefix: refreshed.accessToken?.substring(0, 20),\n newExpiresAt: refreshed.expiresAt,\n cookieName,\n });\n return response;\n } else {\n // Refresh failed - clear cookie and redirect to sign in (no error, just let user log in fresh)\n console.log('[OAuth42 Middleware] Refresh failed (likely token blacklisted after deploy), clearing session');\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n // DO NOT set error parameter - just redirect silently\n\n const response = NextResponse.redirect(url);\n // Clear the base session cookie and any chunk cookies\n response.cookies.delete(cookieName);\n for (let i = 0; ; i++) {\n const chunkName = `${cookieName}.${i}`;\n if (req.cookies.has(chunkName)) {\n response.cookies.delete(chunkName);\n } else {\n break;\n }\n }\n return response;\n }\n }\n\n // Check custom authorization callback\n if (options.callbacks?.authorized) {\n const isAuthorized = await options.callbacks.authorized({ token, req });\n if (!isAuthorized) {\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n return NextResponse.redirect(url);\n }\n }\n\n return NextResponse.next();\n };\n}\n\n/**\n * Helper to create middleware configuration\n */\nexport function createMiddlewareConfig(\n protectedPaths: string[] = ['/protected'],\n publicPaths: string[] = ['/auth', '/api/auth']\n) {\n return {\n matcher: [\n /*\n * Match all request paths except for the ones starting with:\n * - _next/static (static files)\n * - _next/image (image optimization files)\n * - favicon.ico (favicon file)\n * - public folder\n */\n '/((?!_next/static|_next/image|favicon.ico|public).*)',\n ],\n protectedPaths,\n publicPaths,\n };\n}\n"],"mappings":"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","names":["import_next_auth","getNextAuthSession","NextAuthDefault"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server/client-assertion.ts","../src/provider.ts","../src/server/par.ts","../src/server/verified-userinfo.ts","../src/server/auth.ts","../src/server/session.ts","../src/server/backend-session.ts","../src/server/middleware.ts","../src/server/dpop.ts"],"sourcesContent":["// Main exports\nexport { OAuth42Provider } from './provider';\nexport type { OAuth42Profile, OAuth42ProviderOptions } from './provider';\n\n// Server-side exports\nexport { createAuth, getServerSession, refreshAccessToken } from './server/auth';\nexport type { CreateAuthOptions } from './server/auth';\n\nexport { withOAuth42Auth, createMiddlewareConfig } from './server/middleware';\nexport type { OAuth42AuthOptions } from './server/middleware';\n\nexport { getOAuth42Session, withOAuth42Session, withOAuth42ServerSideProps } from './server/session';\n\n// Type exports\nexport type { OAuth42Config } from './types';\n\n// Re-export NextAuth types for convenience\nexport type { Session, User } from 'next-auth';\nexport { OAuth42DPoP } from './server/dpop';\n\nexport { OAuth42ClientAssertion } from './server/client-assertion';\n\nexport { pushAuthorizationURL, withPushedAuthorization } from './server/par';\n","import { createHash, createPublicKey, generateKeyPairSync, KeyObject, randomBytes, sign } from 'node:crypto';\nimport type { OAuth42DPoP } from './dpop';\n\n/** Retained software signing key for a confidential backend. Never put this in a session. */\nexport class OAuth42ClientAssertion {\n readonly #key: KeyObject;\n readonly #public: Record<string, string>;\n readonly kid: string;\n readonly thumbprint: string;\n\n constructor(kid: string, key: KeyObject) {\n if (typeof kid !== 'string' || !/^[\\x21-\\x7e]{1,128}$/.test(kid)) throw new Error('Invalid client signing key ID');\n if (key.type !== 'private' || key.asymmetricKeyType !== 'ec' || key.asymmetricKeyDetails?.namedCurve !== 'prime256v1') {\n throw new Error('Client assertions require a private P-256 key');\n }\n this.#key = key;\n this.kid = kid;\n const publicKey = createPublicKey(key).export({ format: 'jwk' });\n this.#public = { crv: 'P-256', kty: 'EC', x: publicKey.x!, y: publicKey.y! };\n this.thumbprint = createHash('sha256').update(JSON.stringify(this.#public)).digest('base64url');\n }\n\n static generate(kid: string): OAuth42ClientAssertion {\n return new OAuth42ClientAssertion(kid, generateKeyPairSync('ec', { namedCurve: 'prime256v1' }).privateKey);\n }\n\n get publicJwk(): Record<string, string> { return { ...this.#public, kid: this.kid }; }\n\n /** Private keys for the server-only NextAuth/openid-client configuration, never registration. */\n get oidcJwks() {\n return { keys: [{ kty: 'EC', crv: 'P-256', x: this.#public.x, y: this.#public.y,\n d: this.#key.export({ format: 'jwk' }).d!, kid: this.kid }] };\n }\n\n static validateEndpoint(target: string): void {\n const url = new URL(target);\n if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.hash ||\n (url.protocol !== 'https:' && !['localhost', '127.0.0.1', '[::1]'].includes(url.hostname))) {\n throw new Error('Client authentication requires HTTPS outside loopback development');\n }\n }\n\n assertion(clientId: string, audience: string): string {\n OAuth42ClientAssertion.validateEndpoint(audience);\n if (!clientId || Buffer.byteLength(clientId) > 256) throw new Error('Invalid client identity');\n const now = Math.floor(Date.now() / 1000);\n const header = { alg: 'ES256', typ: 'JWT', kid: this.kid };\n const payload = { iss: clientId, sub: clientId, aud: audience, iat: now, exp: now + 60, jti: randomBytes(32).toString('base64url') };\n const data = `${Buffer.from(JSON.stringify(header)).toString('base64url')}.${Buffer.from(JSON.stringify(payload)).toString('base64url')}`;\n return `${data}.${sign('sha256', Buffer.from(data), { key: this.#key, dsaEncoding: 'ieee-p1363' }).toString('base64url')}`;\n }\n\n async fetch(clientId: string, target: string, init: RequestInit, dpop?: OAuth42DPoP): Promise<Response> {\n if (init.method?.toUpperCase() !== 'POST' || !(typeof init.body === 'string' || init.body instanceof URLSearchParams)) {\n throw new Error('Client assertions require a form POST');\n }\n const prepare = (): RequestInit => {\n const body = new URLSearchParams(init.body as string | URLSearchParams);\n body.delete('client_secret');\n body.set('client_id', clientId);\n body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer');\n body.set('client_assertion', this.assertion(clientId, target));\n const headers = new Headers(init.headers);\n headers.delete('Authorization'); headers.delete('Content-Length'); headers.delete('Transfer-Encoding');\n headers.set('Content-Type', 'application/x-www-form-urlencoded');\n return { ...init, body, headers, redirect: 'error', cache: 'no-store', signal: init.signal || AbortSignal.timeout(30_000) };\n };\n return dpop ? dpop.fetch(target, init, undefined, prepare) : fetch(target, prepare());\n }\n}\n","import { OAuth42ClientAssertion } from './server/client-assertion';\nimport type { OAuth42DPoP } from './server/dpop';\nimport type { OAuthConfig, OAuthUserConfig } from 'next-auth/providers/oauth';\n\nexport interface OAuth42Profile {\n sub: string;\n email: string;\n email_verified?: boolean;\n name?: string;\n given_name?: string;\n family_name?: string;\n picture?: string;\n username?: string;\n groups?: string[];\n id?: string;\n}\n\nexport interface OAuth42ProviderOptions {\n clientId: string;\n clientSecret?: string;\n clientAssertionKey?: OAuth42ClientAssertion;\n issuer?: string;\n authorizationUrl?: string;\n tokenUrl?: string;\n userinfoUrl?: string;\n scopes?: string[];\n pkceEnabled?: boolean;\n dpop?: OAuth42DPoP;\n}\n\nexport function OAuth42Provider<P extends OAuth42Profile>(\n options: Omit<OAuthUserConfig<P>, 'clientSecret'> & Partial<OAuth42ProviderOptions>\n): OAuthConfig<P> {\n const issuer = options.issuer || process.env.OAUTH42_ISSUER || 'https://api.oauth42.com';\n const baseUrl = issuer.replace(/\\/$/, '');\n const { dpop, clientAssertionKey, ...providerOptions } = options;\n if (clientAssertionKey) {\n OAuth42ClientAssertion.validateEndpoint(`${baseUrl}/oauth2/token`);\n providerOptions.clientSecret = undefined;\n }\n if (options.pkceEnabled === false) throw new Error('OAuth42 requires S256 PKCE');\n \n return {\n id: 'oauth42',\n name: 'OAuth42',\n type: 'oauth',\n version: '2.0',\n\n // Pin O42 metadata: NextAuth v4 discovery does not compare the returned issuer.\n // Constructing its OIDC client from these trusted endpoints preserves issuer binding.\n jwks_endpoint: `${baseUrl}/.well-known/jwks.json`,\n\n // Use ID token for user profile (standard OIDC pattern)\n // This avoids an extra HTTP call to /userinfo on every auth flow\n // Apps can call /userinfo separately when they need extended claims (groups, company_id, etc.)\n idToken: true,\n\n // Also set individual endpoints for compatibility\n authorization: {\n url: `${baseUrl}/oauth2/authorize`,\n params: {\n scope: (options.scopes || ['openid', 'profile', 'email']).join(' '),\n response_type: 'code',\n },\n },\n token: dpop ? {\n url: `${baseUrl}/oauth2/token`,\n async request({ client, provider, params, checks }) {\n const tokens = await client.callback(provider.callbackUrl, params, checks, { DPoP: dpop.oidcKey });\n dpop.assertTokenResponse(tokens);\n return { tokens };\n },\n } : `${baseUrl}/oauth2/token`,\n userinfo: `${baseUrl}/oauth2/userinfo`,\n\n ...(clientAssertionKey ? { jwks: clientAssertionKey.oidcJwks } : {}),\n client: {\n id: options.clientId,\n secret: clientAssertionKey ? undefined : options.clientSecret,\n token_endpoint_auth_method: clientAssertionKey ? 'private_key_jwt' : 'client_secret_post',\n ...(clientAssertionKey ? { token_endpoint_auth_signing_alg: 'ES256' } : {}),\n id_token_signed_response_alg: 'RS256', // OAuth42 uses RS256 for ID tokens\n },\n\n issuer,\n\n checks: ['pkce', 'state', 'nonce'],\n \n profile(profile: OAuth42Profile, tokens: any) {\n return {\n id: profile.sub || profile.id || profile.email,\n email: profile.email,\n emailVerified: profile.email_verified ? new Date() : null,\n name: profile.name || `${profile.given_name || ''} ${profile.family_name || ''}`.trim(),\n image: profile.picture,\n groups: profile.groups,\n };\n },\n \n style: {\n logo: '/oauth42-logo.svg',\n bg: '#1e40af',\n text: '#ffffff',\n },\n \n // NextAuth v4 types require a string even when private_key_jwt sends no secret.\n options: { ...providerOptions, clientSecret: providerOptions.clientSecret || '' },\n };\n}","import type { OAuth42DPoP } from './dpop';\nimport { OAuth42ClientAssertion } from './client-assertion';\n\nexport interface PARConfig {\n issuer: string; clientId: string; clientSecret?: string;\n dpop?: OAuth42DPoP; clientAssertionKey?: OAuth42ClientAssertion;\n}\n/** Transform only the authorization redirect produced by NextAuth after its\n * state/nonce/PKCE cookies are set. All pushed parameters stay server-side. */\nexport async function pushAuthorizationURL(value: string, config: PARConfig): Promise<string> {\n const base = config.issuer.replace(/\\/$/, '');\n let url: URL;\n try { url = new URL(value); } catch { return value; }\n if (`${url.origin}${url.pathname}` !== `${base}/oauth2/authorize`) return value;\n if (url.username || url.password || url.hash) throw new Error(\"Invalid authorization endpoint\");\n const body = new URLSearchParams(url.search);\n if (body.getAll('client_id').length !== 1 || body.get('client_id') !== config.clientId ||\n body.get('response_type') !== 'code' || !body.get('state') || !body.get('nonce') ||\n body.get('code_challenge_method') !== 'S256' || !/^[A-Za-z0-9_-]{43}$/.test(body.get('code_challenge') || '') ||\n ['request_uri', 'client_secret', 'client_assertion', 'client_assertion_type'].some(k => body.has(k))) {\n throw new Error('Invalid PAR authorization transaction');\n }\n const target = `${base}/oauth2/par`;\n OAuth42ClientAssertion.validateEndpoint(target);\n if (!config.clientAssertionKey) body.set('client_secret', config.clientSecret || '');\n const init: RequestInit = { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body,\n redirect: 'error', cache: 'no-store', signal: AbortSignal.timeout(30_000) };\n const response = config.clientAssertionKey ? await config.clientAssertionKey.fetch(config.clientId, target, init, config.dpop) :\n config.dpop ? await config.dpop.fetch(target, init) : await fetch(target, init);\n if (response.status !== 201) throw new Error('Pushed authorization failed');\n const pushed = await response.json();\n if (typeof pushed.request_uri !== 'string' || !/^urn:ietf:params:oauth:request_uri:[A-Za-z0-9_-]{43}$/.test(pushed.request_uri) ||\n !Number.isInteger(pushed.expires_in) || pushed.expires_in <= 0 || pushed.expires_in > 600) throw new Error('Invalid PAR response');\n url.search = new URLSearchParams({ client_id: config.clientId, request_uri: pushed.request_uri }).toString();\n return url.href;\n}\nexport function withPushedAuthorization(handler: (...args: any[]) => any, config: PARConfig) {\n return async (request: Request, context: unknown): Promise<Response> => {\n if (!(request instanceof Request)) throw new Error('PAR handlers require Next.js App Router Request/Response');\n const response: Response = await handler(request, context);\n const location = response.headers.get('Location');\n if (location) {\n const next = await pushAuthorizationURL(location, config);\n if (next === location) return response;\n const headers = new Headers(response.headers); headers.set('Location', next); headers.delete('content-length');\n return new Response(response.body, { status: response.status, headers });\n }\n if (response.headers.get('content-type')?.includes('application/json')) {\n const body = await response.clone().json();\n if (typeof body?.url === 'string') {\n const next = await pushAuthorizationURL(body.url, config);\n if (next !== body.url) {\n const headers = new Headers(response.headers); headers.delete('content-length');\n return new Response(JSON.stringify({ ...body, url: next }), { status: response.status, headers });\n }\n }\n }\n return response;\n };\n}\n","import type { OAuth42DPoP } from './dpop';\n/** Live verification binds an application session to the issuer's current user. */\nexport interface VerifiedUserInfo {\n sub: string;\n email?: string;\n name?: string;\n preferred_username?: string;\n username?: string;\n email_verified?: boolean;\n groups?: string[];\n given_name?: string;\n family_name?: string;\n company_id?: string;\n company_name?: string;\n}\n\nexport async function verifiedUserInfo(issuer: string, accessToken: unknown, subject: unknown, dpop?: OAuth42DPoP): Promise<VerifiedUserInfo | null> {\n if (typeof accessToken !== 'string' || !accessToken || typeof subject !== 'string' || !subject) return null;\n try {\n const target = `${issuer.replace(/\\/$/, '')}/oauth2/userinfo`;\n const fetcher = dpop ? (url: string, init: RequestInit) => dpop.fetch(url, init, accessToken) : fetch;\n const response = await fetcher(target, {\n headers: { Authorization: `Bearer ${accessToken}` },\n redirect: 'error', cache: 'no-store', signal: AbortSignal.timeout(30_000),\n });\n if (!response.ok) return null;\n const user = await response.json();\n return parseVerifiedUserInfo(user, subject);\n } catch {\n return null;\n }\n}\n\n\n/** Validate only live issuer response data, never cached JWT/session metadata. */\nexport function parseVerifiedUserInfo(value: unknown, subject: unknown): VerifiedUserInfo | null {\n if (typeof subject !== 'string' || !subject || !value || typeof value !== 'object' || Array.isArray(value)) return null;\n const user = value as Record<string, unknown>;\n if (user.sub !== subject) return null;\n if (user.groups !== undefined && (!Array.isArray(user.groups) || user.groups.some((group: unknown) => typeof group !== 'string'))) return null;\n // Email is required by O42's contract when present. Optional display fields\n // serialize as null for existing email-only accounts and are omitted below.\n if (user.email !== undefined && typeof user.email !== 'string') return null;\n if (user.email_verified !== undefined && typeof user.email_verified !== 'boolean') return null;\n // Return only the profile fields applications display. Never forward arbitrary\n // issuer properties into the browser session.\n const profile: VerifiedUserInfo = { sub: user.sub };\n for (const field of ['email', 'name', 'preferred_username', 'username', 'given_name', 'family_name', 'company_id', 'company_name'] as const) {\n if (user[field] != null) {\n if (typeof user[field] !== 'string') return null;\n profile[field] = user[field];\n }\n }\n if (user.email_verified !== undefined) profile.email_verified = user.email_verified;\n if (user.groups !== undefined) profile.groups = user.groups;\n return profile;\n}\n\n/** New backends verify identity within resolve; old backends retain live /userinfo. */\nexport async function verifiedBackendSessionUserInfo(\n issuer: string,\n session: { access_token: unknown; user_info?: unknown },\n subject: unknown,\n dpop?: OAuth42DPoP,\n): Promise<VerifiedUserInfo | null> {\n if (typeof session.access_token !== 'string' || !session.access_token) return null;\n if (Object.prototype.hasOwnProperty.call(session, 'user_info')) {\n // A malformed/null response fails closed. Never fall back to cached `user`\n // or let a second endpoint hide an invalid consolidated identity response.\n return parseVerifiedUserInfo(session.user_info, subject);\n }\n return verifiedUserInfo(issuer, session.access_token, subject, dpop);\n}\n","import { withPushedAuthorization } from './par';\nimport type { OAuth42ClientAssertion } from './client-assertion';\nimport type { OAuth42DPoP } from './dpop';\nimport { verifiedBackendSessionUserInfo, verifiedUserInfo, type VerifiedUserInfo } from './verified-userinfo';\nimport NextAuthDefault from 'next-auth';\nimport type { NextAuthOptions } from 'next-auth';\nimport { OAuth42Provider, OAuth42Profile } from '../provider';\nimport { getOAuth42Session } from './session';\nimport {\n createBackendSession,\n isBackendSessionMode,\n resolveBackendSession,\n revokeBackendSession,\n type SessionStoreMode,\n} from './backend-session';\n\n// Handle both CommonJS and ESM exports\nconst NextAuth = (NextAuthDefault as any).default || NextAuthDefault;\n\nexport { type NextAuthOptions };\n\n// Simple per-process lock for explicit refresh via getAccessToken()\nconst activeRefreshes = new Map<string, Promise<any>>();\n\nexport interface CreateAuthOptions {\n clientId?: string;\n clientSecret?: string;\n issuer?: string;\n scopes?: string[];\n pkceEnabled?: boolean;\n /** Require PAR through the returned App Router handlers; never falls back. */\n pushedAuthorization?: boolean;\n dpop?: OAuth42DPoP;\n clientAssertionKey?: OAuth42ClientAssertion;\n debug?: boolean;\n callbacks?: NextAuthOptions['callbacks'];\n events?: NextAuthOptions['events'];\n pages?: NextAuthOptions['pages'];\n session?: NextAuthOptions['session'];\n /**\n * Session storage mode.\n *\n * - \"jwt\" keeps OAuth token material in the encrypted NextAuth JWT cookie.\n * - \"backend\" stores token material behind a Rust-backend-owned opaque\n * session id. Next.js never talks to Redis directly.\n */\n sessionStore?: SessionStoreMode;\n /**\n * Unique prefix for cookie names to allow multiple apps on the same domain.\n * Each app should use a different prefix (e.g., 'portal', 'admin', 'bond').\n * This prevents session cookie conflicts when running multiple apps on localhost.\n */\n cookiePrefix?: string;\n}\n\n/**\n * Create a pre-configured NextAuth instance for OAuth42\n * This provides a simplified setup with sensible defaults\n */\nexport function createAuth(options: CreateAuthOptions = {}) {\n const clientId = options.clientId || process.env.OAUTH42_CLIENT_ID;\n const clientSecret = options.clientAssertionKey ? '' : options.clientSecret || process.env.OAUTH42_CLIENT_SECRET;\n const issuer =\n options.issuer ||\n process.env.NEXT_PUBLIC_OAUTH_ISSUER ||\n process.env.OAUTH42_ISSUER ||\n 'https://localhost:8443';\n const useBackendSessions = isBackendSessionMode(options.sessionStore);\n \n if (!clientId || (!clientSecret && !options.clientAssertionKey)) {\n throw new Error(\n 'OAuth42 client credentials are required. ' +\n 'Set OAUTH42_CLIENT_ID and OAUTH42_CLIENT_SECRET environment variables ' +\n 'or pass them in the options.'\n );\n }\n \n const authOptions: NextAuthOptions = {\n providers: [\n OAuth42Provider({\n clientId,\n clientSecret: clientSecret || '',\n issuer,\n scopes: options.scopes,\n pkceEnabled: options.pkceEnabled,\n dpop: options.dpop,\n clientAssertionKey: options.clientAssertionKey,\n }),\n ],\n \n callbacks: {\n async jwt({ token, account, profile }) {\n if (options.clientAssertionKey) delete token.clientSecret;\n console.log('[OAuth42 SDK] JWT callback called', { hasAccount: !!account, hasProfile: !!profile });\n\n // Initial sign in\n if (account) {\n if (useBackendSessions) {\n if (!account.access_token || !account.refresh_token) {\n throw new Error('OAuth42 backend sessions require access and refresh tokens');\n }\n\n const oauth42Profile = profile as OAuth42Profile | undefined;\n const backendSession = await createBackendSession({\n dpop: options.dpop, clientAssertionKey: options.clientAssertionKey,\n issuer,\n clientId,\n clientSecret: clientSecret || '',\n accessToken: account.access_token,\n refreshToken: account.refresh_token,\n expiresAt: account.expires_at,\n idToken: account.id_token,\n user: {\n sub: oauth42Profile?.sub,\n email: oauth42Profile?.email,\n username: oauth42Profile?.username,\n name: token.name as string | undefined,\n emailVerified: oauth42Profile?.email_verified,\n groups: oauth42Profile?.groups,\n },\n });\n\n token.oauth42SessionId = backendSession.session_id;\n token.expiresAt = backendSession.expires_at;\n token.issuer = issuer;\n } else {\n console.log('[OAuth42 SDK] Initial sign in - storing tokens in JWT');\n token.accessToken = account.access_token;\n token.refreshToken = account.refresh_token;\n token.expiresAt = account.expires_at;\n token.idToken = account.id_token;\n token.clientId = clientId;\n if (options.clientAssertionKey) delete token.clientSecret;\n else token.clientSecret = clientSecret;\n token.issuer = issuer;\n }\n }\n\n // Add user profile data\n if (profile) {\n const oauth42Profile = profile as OAuth42Profile;\n token.email = oauth42Profile.email;\n token.username = oauth42Profile.username;\n token.emailVerified = oauth42Profile.email_verified;\n token.groups = oauth42Profile.groups;\n }\n\n // NOTE: Token refresh is handled by middleware (withOAuth42Auth)\n // Middleware can properly set cookies after refresh, which JWT callback cannot\n // do in Next.js App Router Server Components.\n\n // Call custom callback if provided\n if (options.callbacks?.jwt) {\n return options.callbacks.jwt({ token, account, profile } as any);\n }\n\n console.log('[OAuth42 SDK] JWT callback complete, returning token');\n return token;\n },\n\n async session({ session, token }) {\n console.log('[OAuth42 SDK] Session callback called', { hasToken: !!token, hasSession: !!session });\n const revokedSession = () => {\n session.error = 'SessionRevoked';\n delete session.accessToken;\n delete session.idToken;\n delete session.userInfo;\n delete session.user;\n return session;\n };\n if (token.error) return revokedSession();\n let verified: VerifiedUserInfo | null;\n\n if (useBackendSessions) {\n const sessionId = token.oauth42SessionId as string | undefined;\n if (!sessionId) {\n return revokedSession();\n }\n\n const backendSession = await resolveBackendSession({\n dpop: options.dpop, clientAssertionKey: options.clientAssertionKey,\n issuer,\n clientId,\n clientSecret: clientSecret || '',\n sessionId,\n });\n\n if (!backendSession) {\n return revokedSession();\n }\n\n session.accessToken = backendSession.access_token;\n session.idToken = backendSession.id_token as string;\n token.expiresAt = backendSession.expires_at;\n verified = await verifiedBackendSessionUserInfo(issuer, backendSession, token.sub, options.dpop);\n\n if (backendSession.user && session.user) {\n session.user.email = backendSession.user.email as string;\n session.user.name = backendSession.user.name as string;\n session.user.username = backendSession.user.username as string;\n session.user.emailVerified = backendSession.user.emailVerified as boolean;\n session.user.groups = backendSession.user.groups as string[];\n }\n } else {\n // Add OAuth42-specific data to session\n session.accessToken = token.accessToken as string;\n session.idToken = token.idToken as string;\n verified = await verifiedUserInfo(issuer, session.accessToken, token.sub, options.dpop);\n }\n\n if (!verified) {\n return revokedSession();\n }\n session.userInfo = verified;\n token.email = verified.email;\n token.name = verified.name;\n token.username = verified.preferred_username ?? verified.username;\n token.emailVerified = verified.email_verified;\n token.groups = verified.groups ?? [];\n if (session.user) {\n session.user.email = verified.email;\n session.user.name = verified.name;\n session.user.username = verified.preferred_username ?? verified.username;\n session.user.emailVerified = verified.email_verified;\n session.user.groups = verified.groups ?? [];\n }\n\n // Pass through any token refresh errors to the client\n if (token.error) {\n session.error = token.error as string;\n }\n\n if (!useBackendSessions && session.user) {\n session.user.email = token.email as string;\n session.user.name = token.name as string;\n session.user.username = token.username as string;\n session.user.emailVerified = token.emailVerified as boolean;\n session.user.groups = token.groups as string[];\n }\n\n // Call custom callback if provided\n if (options.callbacks?.session) {\n return options.callbacks.session({ session, token } as any);\n }\n\n console.log('[OAuth42 SDK] Session callback complete, returning session');\n return session;\n },\n },\n \n pages: {\n signIn: '/auth/signin',\n signOut: '/auth/signout',\n error: '/auth/error',\n ...options.pages,\n },\n \n session: {\n strategy: 'jwt',\n ...options.session,\n },\n\n events: {\n async signOut(message) {\n if (useBackendSessions) {\n const sessionId = (message as any).token?.oauth42SessionId as string | undefined;\n if (sessionId) {\n await revokeBackendSession({\n dpop: options.dpop, clientAssertionKey: options.clientAssertionKey,\n issuer,\n clientId,\n clientSecret: clientSecret || '',\n sessionId,\n }).catch(error => {\n console.warn('[OAuth42 SDK] Failed to revoke backend session on signOut:', error);\n });\n }\n }\n\n if (options.events?.signOut) {\n await options.events.signOut(message as any);\n }\n },\n },\n \n debug: options.debug || process.env.NODE_ENV === 'development',\n\n secret: process.env.NEXTAUTH_SECRET,\n\n // Configure unique cookie names per app to prevent session conflicts on localhost\n ...(options.cookiePrefix && {\n cookies: {\n sessionToken: {\n name: `${options.cookiePrefix}.session-token`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n callbackUrl: {\n name: `${options.cookiePrefix}.callback-url`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n csrfToken: {\n name: `${options.cookiePrefix}.csrf-token`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n // PKCE code_verifier cookie - essential for PKCE flow.\n // TTL covers the full OAuth round-trip including user-in-the-loop steps\n // like passkey ceremonies, MFA enrollment, and any debugging pauses.\n // The previous 15-minute value was too tight for realistic ceremony-\n // heavy flows — see #524 for the incident where state expired mid-debug.\n pkceCodeVerifier: {\n name: `${options.cookiePrefix}.pkce.code_verifier`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n maxAge: 3600, // 1 hour (was 900 — 15 min was too short for passkey/MFA flows)\n },\n },\n // State cookie for OAuth CSRF protection. Same TTL rationale as\n // pkceCodeVerifier above. State is single-use CSRF and cannot be\n // replayed, so a longer TTL does not weaken the security story.\n state: {\n name: `${options.cookiePrefix}.state`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n maxAge: 3600, // 1 hour (was 900 — 15 min was too short for passkey/MFA flows)\n },\n },\n // Nonce cookie for OpenID Connect\n nonce: {\n name: `${options.cookiePrefix}.nonce`,\n options: {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n },\n },\n },\n }),\n };\n \n // Return the configuration and handlers for API routes\n const nextAuthHandler = NextAuth(authOptions);\n const handler = options.pushedAuthorization ? withPushedAuthorization(nextAuthHandler, { issuer, clientId, clientSecret, dpop: options.dpop, clientAssertionKey: options.clientAssertionKey }) : nextAuthHandler;\n return {\n auth: authOptions,\n handlers: { GET: handler, POST: handler },\n };\n}\n\n/**\n * Create NextAuth handlers for API routes\n */\nexport function createHandlers(authOptions: NextAuthOptions) {\n const handler = NextAuth(authOptions);\n return { GET: handler, POST: handler };\n}\n\n/**\n * Helper to get the current session server-side\n * @deprecated Use getOAuth42Session instead - this is now just an alias for backward compatibility\n * \n * This function is maintained for backward compatibility but internally\n * calls getOAuth42Session which properly handles both App Router and Pages Router\n */\nexport const getServerSession = getOAuth42Session;\n\n/**\n * Token refresh helper with simple per-process locking\n *\n * The lock prevents multiple concurrent refresh calls from the same process,\n * reducing unnecessary token churn. Coordinate refresh across backend instances;\n * the server rejects reuse of an already rotated refresh token.\n */\nexport async function refreshAccessToken(token: any, clientId: string, clientSecret: string, issuer?: string, dpop?: OAuth42DPoP, clientAssertionKey?: OAuth42ClientAssertion): Promise<any> {\n if (typeof token.refreshToken !== 'string' || !token.refreshToken) {\n return { ...token, error: 'RefreshAccessTokenError' };\n }\n // Deduplicate only the same grant under the same issuer and client credentials.\n const key = JSON.stringify([issuer || process.env.OAUTH42_ISSUER || 'https://api.oauth42.com', clientId, clientSecret, token.sub, token.refreshToken, dpop?.thumbprint, clientAssertionKey?.thumbprint, clientAssertionKey?.kid]);\n let refresh = activeRefreshes.get(key);\n if (!refresh) {\n refresh = doRefresh(token, clientId, clientSecret, issuer, dpop, clientAssertionKey);\n activeRefreshes.set(key, refresh);\n }\n try {\n const result = await refresh;\n // Keep the calling session's claims, even when it shares a refresh grant.\n const updated = { ...token, accessToken: result.accessToken, refreshToken: result.refreshToken,\n expiresAt: result.expiresAt, error: result.error };\n if (clientAssertionKey) delete updated.clientSecret;\n return updated;\n } finally {\n if (activeRefreshes.get(key) === refresh) activeRefreshes.delete(key);\n }\n}\n\nasync function doRefresh(token: any, clientId: string, clientSecret: string, issuer?: string, dpop?: OAuth42DPoP, clientAssertionKey?: OAuth42ClientAssertion): Promise<any> {\n try {\n const baseUrl = issuer || process.env.OAUTH42_ISSUER || 'https://api.oauth42.com';\n const tokenUrl = `${baseUrl}/oauth2/token`;\n\n // In development, we need to handle self-signed certificates\n const fetchOptions: RequestInit = {\n method: 'POST',\n redirect: 'error',\n cache: 'no-store',\n signal: AbortSignal.timeout(30_000),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: token.refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n };\n\n const response = clientAssertionKey ? await clientAssertionKey.fetch(clientId, tokenUrl, fetchOptions, dpop) :\n dpop ? await dpop.fetch(tokenUrl, fetchOptions) : await fetch(tokenUrl, fetchOptions);\n const refreshedTokens = await response.json();\n\n if (!response.ok) {\n throw refreshedTokens;\n }\n\n dpop?.assertTokenResponse(refreshedTokens);\n console.log('[OAuth42] Token refreshed successfully');\n return {\n ...token,\n accessToken: refreshedTokens.access_token,\n refreshToken: refreshedTokens.refresh_token ?? token.refreshToken,\n // Store expiration time in seconds (Unix timestamp)\n expiresAt: Math.floor(Date.now() / 1000) + (refreshedTokens.expires_in || 3600),\n // Explicitly remove any error property on successful refresh\n error: undefined,\n };\n } catch (error) {\n console.error('[OAuth42] Failed to refresh access token');\n return {\n ...token,\n error: 'RefreshAccessTokenError',\n };\n }\n}\n","import { getServerSession as getNextAuthSession } from 'next-auth';\nimport { NextAuthOptions } from 'next-auth';\nimport { GetServerSidePropsContext, NextApiRequest, NextApiResponse } from 'next';\n\n/**\n * Get the OAuth42 session server-side\n *\n * This is the primary method for retrieving sessions in OAuth42 SDK.\n * Supports both Pages Router and App Router:\n *\n * App Router:\n * ```ts\n * const session = await getOAuth42Session(authOptions);\n * ```\n *\n * Pages Router:\n * ```ts\n * const session = await getOAuth42Session(req, res, authOptions);\n * ```\n *\n * Middleware forwards refreshed encrypted session cookies to the current request.\n * Caller-supplied access-token headers are never an authentication source.\n */\nexport async function getOAuth42Session(\n ...args:\n | [GetServerSidePropsContext['req'], GetServerSidePropsContext['res'], NextAuthOptions]\n | [NextApiRequest, NextApiResponse, NextAuthOptions]\n | [NextAuthOptions]\n) {\n const session = await getNextAuthSession(...args as any);\n\n if (!session || (session as any).error) {\n return null;\n }\n\n return session;\n}\n\n/**\n * Helper for protecting API routes\n */\nexport function withOAuth42Session(\n handler: (req: NextApiRequest, res: NextApiResponse, session: any) => Promise<void> | void,\n authOptions: NextAuthOptions\n) {\n return async (req: NextApiRequest, res: NextApiResponse) => {\n const session = await getOAuth42Session(req, res, authOptions);\n \n if (!session) {\n return res.status(401).json({ error: 'Unauthorized' });\n }\n \n return handler(req, res, session);\n };\n}\n\n/**\n * Helper for protecting server-side props\n */\nexport function withOAuth42ServerSideProps(\n getServerSideProps: (\n context: GetServerSidePropsContext,\n session: any\n ) => Promise<any>,\n authOptions: NextAuthOptions\n) {\n return async (context: GetServerSidePropsContext) => {\n const session = await getOAuth42Session(\n context.req,\n context.res,\n authOptions\n );\n \n if (!session) {\n return {\n redirect: {\n destination: '/auth/signin',\n permanent: false,\n },\n };\n }\n \n return getServerSideProps(context, session);\n };\n}","import type { OAuth42DPoP } from './dpop';\nimport { OAuth42ClientAssertion } from './client-assertion';\nexport type SessionStoreMode = 'jwt' | 'backend';\n\nexport interface BackendSessionUser {\n sub?: string;\n email?: string;\n username?: string;\n name?: string;\n emailVerified?: boolean;\n groups?: string[];\n}\n\nexport interface BackendSessionResponse {\n token_type?: string;\n session_id: string;\n access_token: string;\n expires_at: number;\n id_token?: string;\n user?: BackendSessionUser;\n /** Wire data must pass subject/shape validation before becoming a session. */\n user_info?: unknown;\n}\n\nexport interface BackendSessionConfig {\n issuer: string;\n clientId: string;\n clientSecret: string;\n dpop?: OAuth42DPoP;\n clientAssertionKey?: OAuth42ClientAssertion;\n}\n\nexport function isBackendSessionMode(mode?: SessionStoreMode): boolean {\n return mode === 'backend';\n}\n\nfunction sessionEndpoint(issuer: string): string {\n return `${issuer.replace(/\\/$/, '')}/api/sdk/sessions`;\n}\n\nasync function sessionFetch(params: BackendSessionConfig, target: string, body: Record<string, unknown>, credential: string, method = 'POST'): Promise<Response> {\n OAuth42ClientAssertion.validateEndpoint(target);\n const prepare = (): RequestInit => ({\n method, redirect: 'error', cache: 'no-store', signal: AbortSignal.timeout(30_000),\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...body, client_id: params.clientId,\n ...(params.clientAssertionKey ? {\n client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n client_assertion: params.clientAssertionKey.assertion(params.clientId, target),\n } : { client_secret: params.clientSecret }),\n }),\n });\n return params.dpop ? params.dpop.fetch(target, {}, credential, prepare) : fetch(target, prepare());\n}\n\nasync function sessionResponse(response: Response, params: BackendSessionConfig): Promise<BackendSessionResponse> {\n if (!response.ok) throw new Error(`OAuth42 backend session request failed: ${response.status}`);\n const session: BackendSessionResponse = await response.json();\n if (params.dpop) params.dpop.assertTokenResponse(session);\n else if (session.token_type?.toLowerCase() === 'dpop') throw new Error('Backend session requires its retained proof key');\n return session;\n}\n\nexport async function createBackendSession(params: BackendSessionConfig & {\n accessToken: string; refreshToken: string; expiresAt?: number; idToken?: string; user?: BackendSessionUser;\n}): Promise<BackendSessionResponse> {\n return sessionResponse(await sessionFetch(params, sessionEndpoint(params.issuer), {\n access_token: params.accessToken, refresh_token: params.refreshToken,\n id_token: params.idToken, user: params.user,\n }, params.accessToken), params);\n}\n\nexport async function resolveBackendSession(params: BackendSessionConfig & { sessionId: string }): Promise<BackendSessionResponse | null> {\n const response = await sessionFetch(params, `${sessionEndpoint(params.issuer)}/resolve`, { session_id: params.sessionId }, params.sessionId);\n if ([401, 403, 404].includes(response.status)) return null;\n return sessionResponse(response, params);\n}\n\nexport async function revokeBackendSession(params: BackendSessionConfig & { sessionId: string }): Promise<void> {\n const response = await sessionFetch(params, sessionEndpoint(params.issuer), { session_id: params.sessionId }, params.sessionId, 'DELETE');\n if (!response.ok) throw new Error(`OAuth42 backend session revoke failed: ${response.status}`);\n}\n","import type { OAuth42ClientAssertion } from './client-assertion';\nimport type { OAuth42DPoP } from './dpop';\nimport { verifiedBackendSessionUserInfo, verifiedUserInfo, type VerifiedUserInfo } from './verified-userinfo';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { getToken, encode } from 'next-auth/jwt';\nimport {\n isBackendSessionMode,\n resolveBackendSession,\n type SessionStoreMode,\n} from './backend-session';\n\n/**\n * Cookie chunking constants — must match NextAuth's SessionStore behavior.\n * NextAuth splits cookies at ALLOWED_COOKIE_SIZE (4096) minus overhead (163).\n * When middleware re-encodes the JWT after a token refresh, the cookie must be\n * chunked the same way, otherwise:\n * - A single cookie > ~4 KB is silently rejected by the browser\n * - Leftover chunk cookies from the original session cause SessionStore to\n * concatenate old chunks with the new base cookie, producing garbage\n */\nconst ALLOWED_COOKIE_SIZE = 4096;\nconst ESTIMATED_EMPTY_COOKIE_SIZE = 163;\nconst CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;\nconst DEFAULT_SESSION_MAX_AGE_SECONDS = 365 * 24 * 60 * 60;\n\n/**\n * In-flight refresh tracking to prevent parallel refresh calls.\n * Key: user ID (from token.sub), Value: Promise that resolves with refresh result\n */\nconst pendingRefreshes = new Map<string, Promise<{\n success: boolean;\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: number;\n error?: string;\n}>>();\n\nexport interface OAuth42AuthOptions {\n pages?: {\n signIn?: string;\n error?: string;\n };\n callbacks?: {\n authorized?: (params: { token: any; req: NextRequest }) => boolean | Promise<boolean>;\n };\n protectedPaths?: string[];\n publicPaths?: string[];\n /**\n * Cookie prefix for custom cookie names. Must match the prefix used in createAuth().\n * E.g., 'oauth42-portal' will look for cookie 'oauth42-portal.session-token'\n */\n cookiePrefix?: string;\n /**\n * OAuth client credentials for middleware refresh. When omitted, the middleware\n * prefers credentials embedded in the NextAuth token by createAuth(), then\n * falls back to OAUTH42_CLIENT_ID / OAUTH42_CLIENT_SECRET.\n */\n clientId?: string;\n clientSecret?: string;\n issuer?: string;\n dpop?: OAuth42DPoP;\n clientAssertionKey?: OAuth42ClientAssertion;\n /**\n * \"backend\" keeps OAuth token material in the Rust backend and stores only\n * an opaque backend session id in the NextAuth JWT cookie.\n */\n sessionStore?: SessionStoreMode;\n /**\n * Session cookie lifetime. Should match createAuth({ session.maxAge }).\n * Defaults to OAuth42's persistent-session policy of 365 days.\n */\n session?: {\n maxAge?: number;\n };\n}\n\n/** @deprecated Invalid refresh grants must fail closed, including concurrent requests. */\nexport function shouldPreserveSessionOnRefreshFailure(_params: {\n error?: string; expiresAt?: number; now: number;\n}): boolean {\n return false;\n}\n\nfunction forwardedHeaders(req: NextRequest, cookieName?: string, jwt?: string): Headers {\n const headers = new Headers(req.headers);\n headers.delete('x-oauth42-refreshed-token');\n if (cookieName && jwt) {\n const cookies = req.cookies.getAll().filter(cookie => cookie.name !== cookieName && !cookie.name.startsWith(`${cookieName}.`));\n if (jwt.length <= CHUNK_SIZE) cookies.push({ name: cookieName, value: jwt });\n else for (let i = 0; i * CHUNK_SIZE < jwt.length; i++) {\n cookies.push({ name: `${cookieName}.${i}`, value: jwt.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE) });\n }\n headers.set('cookie', cookies.map(cookie => `${encodeURIComponent(cookie.name)}=${encodeURIComponent(cookie.value)}`).join('; '));\n }\n return headers;\n}\n\nexport function resolveRefreshConfig(\n options: OAuth42AuthOptions,\n token: any\n): { clientId?: string; clientSecret?: string; issuer: string } {\n return {\n clientId:\n options.clientId ||\n (token.clientId as string | undefined) ||\n process.env.OAUTH42_CLIENT_ID,\n clientSecret:\n options.clientSecret ||\n (token.clientSecret as string | undefined) ||\n process.env.OAUTH42_CLIENT_SECRET,\n issuer:\n options.issuer ||\n (token.issuer as string | undefined) ||\n process.env.OAUTH42_ISSUER ||\n 'https://localhost:8443',\n };\n}\n\n/**\n * Refresh tokens by calling the OAuth42 backend directly\n */\nasync function refreshTokens(\n refreshToken: string,\n clientId: string,\n clientSecret: string,\n issuer: string,\n dpop?: OAuth42DPoP,\n clientAssertionKey?: OAuth42ClientAssertion\n): Promise<{ success: boolean; accessToken?: string; refreshToken?: string; expiresAt?: number; error?: string }> {\n try {\n const tokenUrl = `${issuer}/oauth2/token`;\n\n const fetcher = clientAssertionKey ? (url: string, init: RequestInit) => clientAssertionKey.fetch(clientId, url, init, dpop) : dpop ? dpop.fetch.bind(dpop) : fetch;\n const response = await fetcher(tokenUrl, {\n method: 'POST',\n redirect: 'error',\n cache: 'no-store',\n signal: AbortSignal.timeout(30_000),\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: clientId,\n client_secret: clientSecret,\n }),\n });\n\n const data = await response.json();\n\n if (!response.ok) {\n console.error('[OAuth42 Middleware] Token refresh failed:', response.status);\n return { success: false, error: data.error || 'refresh_failed' };\n }\n\n dpop?.assertTokenResponse(data);\n console.log('[OAuth42 Middleware] Token refreshed successfully');\n return {\n success: true,\n accessToken: data.access_token,\n refreshToken: data.refresh_token,\n expiresAt: Math.floor(Date.now() / 1000) + (data.expires_in || 3600),\n };\n } catch (error) {\n console.error('[OAuth42 Middleware] Token refresh request failed');\n return { success: false, error: 'refresh_error' };\n }\n}\n\n/**\n * Middleware helper for protecting routes with OAuth42\n *\n * This middleware handles:\n * 1. Route protection (redirect to login if no session)\n * 2. Token refresh (refresh expired tokens and update cookie)\n */\nexport function withOAuth42Auth(options: OAuth42AuthOptions = {}) {\n const secret = process.env.NEXTAUTH_SECRET;\n\n if (!secret) {\n throw new Error('NEXTAUTH_SECRET is required for OAuth42 middleware');\n }\n\n return async function middleware(req: NextRequest) {\n // Build cookie name - if prefix is provided, use custom name\n const cookieName = options.cookiePrefix\n ? `${options.cookiePrefix}.session-token`\n : 'next-auth.session-token';\n\n const token = await getToken({\n req: req as any,\n secret,\n cookieName,\n });\n\n const pathname = req.nextUrl.pathname;\n\n // Check if path is explicitly public\n if (options.publicPaths?.some(path => pathname.startsWith(path))) {\n return NextResponse.next({ request: { headers: forwardedHeaders(req) } });\n }\n\n // Check if path needs protection\n const needsProtection = options.protectedPaths\n ? options.protectedPaths.some(path => pathname.startsWith(path))\n : true; // Default to protecting all paths\n\n if (!needsProtection) {\n return NextResponse.next({ request: { headers: forwardedHeaders(req) } });\n }\n\n // No token at all - redirect to sign in\n if (!token || token.error) {\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n return NextResponse.redirect(url);\n }\n\n const refreshConfig = resolveRefreshConfig(options, token);\n\n const denied = () => {\n const url = new URL(options.pages?.signIn || '/auth/signin', req.url);\n url.searchParams.set('callbackUrl', pathname);\n const response = NextResponse.redirect(url);\n for (const cookie of req.cookies.getAll()) {\n if (cookie.name === cookieName || cookie.name.startsWith(`${cookieName}.`)) response.cookies.delete(cookie.name);\n }\n return response;\n };\n const verifyAndAuthorize = async (current: typeof token, resolved?: VerifiedUserInfo | null) => {\n const user = resolved === undefined\n ? await verifiedUserInfo(refreshConfig.issuer, current.accessToken, token.sub, options.dpop)\n : resolved;\n if (!user) return false;\n current.groups = user.groups ?? [];\n current.email = user.email;\n current.name = user.name;\n current.username = user.preferred_username ?? user.username;\n current.emailVerified = user.email_verified;\n return options.callbacks?.authorized ? options.callbacks.authorized({ token: current, req }) : true;\n };\n\n if (isBackendSessionMode(options.sessionStore)) {\n const sessionId = token.oauth42SessionId as string | undefined;\n if (!sessionId || !refreshConfig.clientId || (!refreshConfig.clientSecret && !options.clientAssertionKey)) {\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n const response = NextResponse.redirect(url);\n response.cookies.delete(cookieName);\n return response;\n }\n\n const backendSession = await resolveBackendSession({\n dpop: options.dpop, clientAssertionKey: options.clientAssertionKey,\n issuer: refreshConfig.issuer,\n clientId: refreshConfig.clientId,\n clientSecret: refreshConfig.clientSecret || '',\n sessionId,\n }).catch(error => {\n console.error('[OAuth42 Middleware] Backend session resolve failed:', error);\n return null;\n });\n\n if (!backendSession) {\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n const response = NextResponse.redirect(url);\n response.cookies.delete(cookieName);\n return response;\n }\n\n const verified = await verifiedBackendSessionUserInfo(refreshConfig.issuer, backendSession, token.sub, options.dpop);\n if (!(await verifyAndAuthorize({ ...token, accessToken: backendSession.access_token }, verified))) return denied();\n const requestHeaders = forwardedHeaders(req);\n return NextResponse.next({\n request: {\n headers: requestHeaders,\n },\n });\n }\n\n // Check if access token is expired or expiring soon (15 second buffer)\n // Buffer must be less than the token TTL to have a valid window\n const expiresAt = token.expiresAt as number | undefined;\n const now = Math.floor(Date.now() / 1000);\n const bufferSeconds = 15;\n const needsRefresh = expiresAt && now >= expiresAt - bufferSeconds;\n\n if (needsRefresh) {\n console.log('[OAuth42 Middleware] Token needs refresh:', {\n expiresAt,\n now,\n expiredAgo: expiresAt ? now - expiresAt : 'n/a',\n path: pathname,\n });\n }\n\n if (needsRefresh && token.refreshToken && refreshConfig.clientId && (refreshConfig.clientSecret || options.clientAssertionKey)) {\n const grantKey = JSON.stringify([refreshConfig.issuer, refreshConfig.clientId, refreshConfig.clientSecret, token.sub, token.refreshToken, options.dpop?.thumbprint, options.clientAssertionKey?.thumbprint, options.clientAssertionKey?.kid]);\n\n // Check if there's already a refresh in progress for this user\n let refreshPromise = pendingRefreshes.get(grantKey);\n\n if (refreshPromise) {\n console.log('[OAuth42 Middleware] Waiting for in-flight refresh...');\n } else {\n console.log('[OAuth42 Middleware] Access token expired, refreshing...');\n\n // Create the refresh promise and store it.\n // Keep the entry for 30s after completion so late-arriving requests\n // (with stale cookies) reuse the cached result instead of triggering\n // a new refresh with the already-rotated token. See issue #470.\n refreshPromise = refreshTokens(\n token.refreshToken as string,\n refreshConfig.clientId,\n refreshConfig.clientSecret || '',\n refreshConfig.issuer,\n options.dpop,\n options.clientAssertionKey\n ).finally(() => {\n const cleanupTimer = setTimeout(() => pendingRefreshes.delete(grantKey), 30000);\n if (typeof cleanupTimer === 'object' && 'unref' in cleanupTimer) {\n cleanupTimer.unref();\n }\n });\n\n pendingRefreshes.set(grantKey, refreshPromise);\n }\n\n const refreshed = await refreshPromise;\n\n if (refreshed.success && refreshed.accessToken && refreshed.refreshToken) {\n // Update the token with new values\n const updatedToken: typeof token = {\n ...token,\n accessToken: refreshed.accessToken,\n refreshToken: refreshed.refreshToken,\n expiresAt: refreshed.expiresAt,\n };\n\n if (options.clientAssertionKey) delete updatedToken.clientSecret;\n if (!(await verifyAndAuthorize(updatedToken))) return denied();\n // Re-encode the JWT\n const newJwt = await encode({\n token: updatedToken,\n secret: secret!,\n });\n\n // Create response with request headers that pass the new token to API routes\n // This is necessary because API routes read from the request, not the response cookie\n const requestHeaders = forwardedHeaders(req, cookieName, newJwt);\n\n const response = NextResponse.next({\n request: {\n headers: requestHeaders,\n },\n });\n\n const cookieOptions = {\n httpOnly: true,\n sameSite: 'lax' as const,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n maxAge: options.session?.maxAge ?? DEFAULT_SESSION_MAX_AGE_SECONDS,\n };\n\n // Set cookie with chunking matching NextAuth's SessionStore behavior.\n // Without chunking, a JWT > ~4 KB is silently rejected by the browser,\n // causing an infinite refresh loop where every request re-triggers\n // token refresh but the cookie never persists.\n if (newJwt.length <= CHUNK_SIZE) {\n // Fits in a single cookie\n response.cookies.set(cookieName, newJwt, cookieOptions);\n // Clean up any leftover chunk cookies from a previously chunked session\n for (let i = 0; ; i++) {\n const chunkName = `${cookieName}.${i}`;\n if (req.cookies.has(chunkName)) {\n response.cookies.set(chunkName, '', { ...cookieOptions, maxAge: 0 });\n } else {\n break;\n }\n }\n } else {\n // Cookie too large — chunk it like NextAuth does\n const chunkCount = Math.ceil(newJwt.length / CHUNK_SIZE);\n for (let i = 0; i < chunkCount; i++) {\n const chunkName = `${cookieName}.${i}`;\n const chunkValue = newJwt.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE);\n response.cookies.set(chunkName, chunkValue, cookieOptions);\n }\n // Delete the base cookie so SessionStore only reads chunks\n response.cookies.set(cookieName, '', { ...cookieOptions, maxAge: 0 });\n // Clean up any extra old chunks beyond the new count\n for (let i = chunkCount; ; i++) {\n const chunkName = `${cookieName}.${i}`;\n if (req.cookies.has(chunkName)) {\n response.cookies.set(chunkName, '', { ...cookieOptions, maxAge: 0 });\n } else {\n break;\n }\n }\n }\n\n // Log details to help diagnose cookie persistence issues\n const existingChunks = [];\n for (let i = 0; ; i++) {\n if (req.cookies.has(`${cookieName}.${i}`)) {\n existingChunks.push(i);\n } else {\n break;\n }\n }\n console.log(`[OAuth42 Middleware] Token refresh complete:`, {\n jwtBytes: newJwt.length,\n chunked: newJwt.length > CHUNK_SIZE,\n existingBaseCooke: req.cookies.has(cookieName),\n existingChunks: existingChunks.length > 0 ? existingChunks : 'none',\n newExpiresAt: refreshed.expiresAt,\n cookieName,\n });\n return response;\n } else {\n // Refresh failed - clear cookie and redirect to sign in (no error, just let user log in fresh)\n console.log('[OAuth42 Middleware] Refresh failed, clearing session');\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n // DO NOT set error parameter - just redirect silently\n\n const response = NextResponse.redirect(url);\n // Clear the base session cookie and any chunk cookies\n response.cookies.delete(cookieName);\n for (let i = 0; ; i++) {\n const chunkName = `${cookieName}.${i}`;\n if (req.cookies.has(chunkName)) {\n response.cookies.delete(chunkName);\n } else {\n break;\n }\n }\n return response;\n }\n }\n\n\n if (!Number.isFinite(expiresAt) || now >= (expiresAt as number) || !token.accessToken) {\n const url = new URL(options.pages?.signIn || '/auth/signin', req.url);\n url.searchParams.set('callbackUrl', pathname);\n return NextResponse.redirect(url);\n }\n if (!(await verifyAndAuthorize(token))) return denied();\n return NextResponse.next({ request: { headers: forwardedHeaders(req) } });\n };\n}\n\n/**\n * Helper to create middleware configuration\n */\nexport function createMiddlewareConfig(\n protectedPaths: string[] = ['/protected'],\n publicPaths: string[] = ['/auth', '/api/auth']\n) {\n return {\n matcher: [\n /*\n * Match all request paths except for the ones starting with:\n * - _next/static (static files)\n * - _next/image (image optimization files)\n * - favicon.ico (favicon file)\n * - public folder\n */\n '/((?!_next/static|_next/image|favicon.ico|public).*)',\n ],\n protectedPaths,\n publicPaths,\n };\n}\n","import { createHash, createPublicKey, generateKeyPairSync, KeyObject, randomBytes, sign } from 'node:crypto';\n\n/** A retained server-side proof key. It represents this backend, not a user's device. */\nexport class OAuth42DPoP {\n private readonly key: KeyObject;\n private readonly jwk: Record<string, string>;\n private readonly nonces = new Map<string, string>();\n readonly thumbprint: string;\n\n constructor(key: KeyObject) {\n if (key.type !== 'private' || key.asymmetricKeyType !== 'ec' || key.asymmetricKeyDetails?.namedCurve !== 'prime256v1') {\n throw new Error('DPoP requires a private P-256 key');\n }\n this.key = key;\n const publicKey = createPublicKey(key).export({ format: 'jwk' });\n this.jwk = { crv: 'P-256', kty: 'EC', x: publicKey.x!, y: publicKey.y! };\n this.thumbprint = createHash('sha256').update(JSON.stringify(this.jwk)).digest('base64url');\n }\n\n /** Persist keys in protected server storage; regeneration cannot recover a public refresh grant. */\n static generate(): OAuth42DPoP {\n return new OAuth42DPoP(generateKeyPairSync('ec', { namedCurve: 'prime256v1' }).privateKey);\n }\n\n /** Passed directly to openid-client so its callback keeps OIDC issuer/nonce/signature validation. */\n get oidcKey(): KeyObject { return this.key; }\n\n proof(method: string, target: string, nonce?: string, accessToken?: string): string {\n const url = new URL(target);\n if (!['http:', 'https:'].includes(url.protocol) || (url.protocol !== 'https:' && !['localhost', '127.0.0.1', '[::1]'].includes(url.hostname))) {\n throw new Error('DPoP requires HTTPS outside loopback development');\n }\n if (url.username || url.password) throw new Error('DPoP endpoint must not contain credentials');\n url.search = ''; url.hash = '';\n const header = { typ: 'dpop+jwt', alg: 'ES256', jwk: this.jwk };\n const claims = { htm: method.toUpperCase(), htu: url.href, iat: Math.floor(Date.now() / 1000),\n jti: randomBytes(32).toString('base64url'), ...(nonce ? { nonce } : {}),\n ...(accessToken !== undefined ? { ath: createHash('sha256').update(accessToken).digest('base64url') } : {}) };\n const input = `${Buffer.from(JSON.stringify(header)).toString('base64url')}.${Buffer.from(JSON.stringify(claims)).toString('base64url')}`;\n return `${input}.${sign('sha256', Buffer.from(input), { key: this.key, dsaEncoding: 'ieee-p1363' }).toString('base64url')}`;\n }\n\n assertTokenResponse(tokens: { token_type?: unknown }): void {\n if (typeof tokens.token_type !== 'string' || tokens.token_type.toLowerCase() !== 'dpop') {\n throw new Error('Server did not issue the requested DPoP-bound token');\n }\n }\n\n async fetch(target: string, init: RequestInit = {}, accessToken?: string, prepare?: () => RequestInit): Promise<Response> {\n if (init.body instanceof ReadableStream) throw new Error('DPoP nonce retries require a replayable request body');\n const cacheKey = `${new URL(target).origin}:${accessToken !== undefined ? 'resource' : 'token'}`;\n for (let attempt = 0; attempt < 2; attempt++) {\n const request = prepare ? prepare() : init;\n const headers = new Headers(request.headers);\n headers.set('DPoP', this.proof(request.method || 'GET', target, this.nonces.get(cacheKey), accessToken));\n if (accessToken !== undefined) headers.set('Authorization', `DPoP ${accessToken}`);\n const response = await fetch(target, { ...request, headers, redirect: 'error', cache: 'no-store', signal: request.signal || AbortSignal.timeout(30_000) });\n const nonce = response.headers.get('DPoP-Nonce');\n if (nonce && /^[\\x21-\\x7e]{1,128}$/.test(nonce)) {\n if (this.nonces.size >= 256) this.nonces.clear();\n this.nonces.set(cacheKey, nonce);\n } else return response;\n if (attempt || ![400, 401].includes(response.status)) return response;\n const error = await response.clone().json().catch(() => null);\n if (error?.error !== 'use_dpop_nonce') return response;\n }\n throw new Error('DPoP nonce negotiation failed');\n }\n}\n"],"mappings":"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","names":["import_next_auth","getNextAuthSession","NextAuthDefault","import_node_crypto"]}
|