@oauth42/next 0.2.5 → 0.2.7

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.
@@ -51,8 +51,32 @@ function OAuth42Provider(options) {
51
51
 
52
52
  // src/server/session.ts
53
53
  import { getServerSession as getNextAuthSession } from "next-auth";
54
+ import { headers } from "next/headers";
55
+ var REFRESHED_TOKEN_HEADER = "x-oauth42-refreshed-token";
54
56
  async function getOAuth42Session(...args) {
55
- return getNextAuthSession(...args);
57
+ const session = await getNextAuthSession(...args);
58
+ if (!session) {
59
+ return null;
60
+ }
61
+ let refreshedToken = null;
62
+ try {
63
+ if (args.length === 1) {
64
+ const headersList = await headers();
65
+ refreshedToken = headersList.get(REFRESHED_TOKEN_HEADER);
66
+ } else if (args.length === 3) {
67
+ const req = args[0];
68
+ refreshedToken = req.headers[REFRESHED_TOKEN_HEADER] || null;
69
+ }
70
+ } catch {
71
+ }
72
+ if (refreshedToken) {
73
+ console.log("[OAuth42 Session] Using refreshed token from middleware");
74
+ return {
75
+ ...session,
76
+ accessToken: refreshedToken
77
+ };
78
+ }
79
+ return session;
56
80
  }
57
81
  function withOAuth42Session(handler, authOptions) {
58
82
  return async (req, res) => {
@@ -84,6 +108,7 @@ function withOAuth42ServerSideProps(getServerSideProps, authOptions) {
84
108
 
85
109
  // src/server/auth.ts
86
110
  var NextAuth = NextAuthDefault.default || NextAuthDefault;
111
+ var activeRefresh = null;
87
112
  function createAuth(options = {}) {
88
113
  const clientId = options.clientId || process.env.OAUTH42_CLIENT_ID;
89
114
  const clientSecret = options.clientSecret || process.env.OAUTH42_CLIENT_SECRET;
@@ -104,11 +129,16 @@ function createAuth(options = {}) {
104
129
  ],
105
130
  callbacks: {
106
131
  async jwt({ token, account, profile }) {
132
+ console.log("[OAuth42 SDK] JWT callback called", { hasAccount: !!account, hasProfile: !!profile });
107
133
  if (account) {
134
+ console.log("[OAuth42 SDK] Initial sign in - storing tokens in JWT");
108
135
  token.accessToken = account.access_token;
109
136
  token.refreshToken = account.refresh_token;
110
137
  token.expiresAt = account.expires_at;
111
138
  token.idToken = account.id_token;
139
+ token.clientId = clientId;
140
+ token.clientSecret = clientSecret;
141
+ token.issuer = options.issuer || process.env.NEXT_PUBLIC_OAUTH_ISSUER || process.env.OAUTH42_ISSUER;
112
142
  }
113
143
  if (profile) {
114
144
  const oauth42Profile = profile;
@@ -119,11 +149,16 @@ function createAuth(options = {}) {
119
149
  if (options.callbacks?.jwt) {
120
150
  return options.callbacks.jwt({ token, account, profile });
121
151
  }
152
+ console.log("[OAuth42 SDK] JWT callback complete, returning token");
122
153
  return token;
123
154
  },
124
155
  async session({ session, token }) {
156
+ console.log("[OAuth42 SDK] Session callback called", { hasToken: !!token, hasSession: !!session });
125
157
  session.accessToken = token.accessToken;
126
158
  session.idToken = token.idToken;
159
+ if (token.error) {
160
+ session.error = token.error;
161
+ }
127
162
  if (session.user) {
128
163
  session.user.email = token.email;
129
164
  session.user.name = token.name;
@@ -133,9 +168,9 @@ function createAuth(options = {}) {
133
168
  if (options.callbacks?.session) {
134
169
  return options.callbacks.session({ session, token });
135
170
  }
171
+ console.log("[OAuth42 SDK] Session callback complete, returning session");
136
172
  return session;
137
- },
138
- ...options.callbacks
173
+ }
139
174
  },
140
175
  pages: {
141
176
  signIn: "/auth/signin",
@@ -148,11 +183,78 @@ function createAuth(options = {}) {
148
183
  ...options.session
149
184
  },
150
185
  debug: options.debug || process.env.NODE_ENV === "development",
151
- secret: process.env.NEXTAUTH_SECRET
186
+ secret: process.env.NEXTAUTH_SECRET,
187
+ // Configure unique cookie names per app to prevent session conflicts on localhost
188
+ ...options.cookiePrefix && {
189
+ cookies: {
190
+ sessionToken: {
191
+ name: `${options.cookiePrefix}.session-token`,
192
+ options: {
193
+ httpOnly: true,
194
+ sameSite: "lax",
195
+ path: "/",
196
+ secure: process.env.NODE_ENV === "production"
197
+ }
198
+ },
199
+ callbackUrl: {
200
+ name: `${options.cookiePrefix}.callback-url`,
201
+ options: {
202
+ httpOnly: true,
203
+ sameSite: "lax",
204
+ path: "/",
205
+ secure: process.env.NODE_ENV === "production"
206
+ }
207
+ },
208
+ csrfToken: {
209
+ name: `${options.cookiePrefix}.csrf-token`,
210
+ options: {
211
+ httpOnly: true,
212
+ sameSite: "lax",
213
+ path: "/",
214
+ secure: process.env.NODE_ENV === "production"
215
+ }
216
+ },
217
+ // PKCE code_verifier cookie - essential for PKCE flow
218
+ pkceCodeVerifier: {
219
+ name: `${options.cookiePrefix}.pkce.code_verifier`,
220
+ options: {
221
+ httpOnly: true,
222
+ sameSite: "lax",
223
+ path: "/",
224
+ secure: process.env.NODE_ENV === "production",
225
+ maxAge: 900
226
+ // 15 minutes
227
+ }
228
+ },
229
+ // State cookie for OAuth CSRF protection
230
+ state: {
231
+ name: `${options.cookiePrefix}.state`,
232
+ options: {
233
+ httpOnly: true,
234
+ sameSite: "lax",
235
+ path: "/",
236
+ secure: process.env.NODE_ENV === "production",
237
+ maxAge: 900
238
+ // 15 minutes
239
+ }
240
+ },
241
+ // Nonce cookie for OpenID Connect
242
+ nonce: {
243
+ name: `${options.cookiePrefix}.nonce`,
244
+ options: {
245
+ httpOnly: true,
246
+ sameSite: "lax",
247
+ path: "/",
248
+ secure: process.env.NODE_ENV === "production"
249
+ }
250
+ }
251
+ }
252
+ }
152
253
  };
254
+ const handler = NextAuth(authOptions);
153
255
  return {
154
256
  auth: authOptions,
155
- handlers: NextAuth(authOptions)
257
+ handlers: { GET: handler, POST: handler }
156
258
  };
157
259
  }
158
260
  function createHandlers(authOptions) {
@@ -161,6 +263,18 @@ function createHandlers(authOptions) {
161
263
  }
162
264
  var getServerSession = getOAuth42Session;
163
265
  async function refreshAccessToken(token, clientId, clientSecret, issuer) {
266
+ if (activeRefresh) {
267
+ console.log("[OAuth42] Refresh already in progress, waiting...");
268
+ return await activeRefresh;
269
+ }
270
+ activeRefresh = doRefresh(token, clientId, clientSecret, issuer);
271
+ try {
272
+ return await activeRefresh;
273
+ } finally {
274
+ activeRefresh = null;
275
+ }
276
+ }
277
+ async function doRefresh(token, clientId, clientSecret, issuer) {
164
278
  try {
165
279
  const baseUrl = issuer || process.env.OAUTH42_ISSUER || "https://oauth42.com";
166
280
  const tokenUrl = `${baseUrl}/oauth2/token`;
@@ -187,6 +301,7 @@ async function refreshAccessToken(token, clientId, clientSecret, issuer) {
187
301
  if (!response.ok) {
188
302
  throw refreshedTokens;
189
303
  }
304
+ console.log("[OAuth42] Token refreshed successfully");
190
305
  return {
191
306
  ...token,
192
307
  accessToken: refreshedTokens.access_token,
@@ -197,7 +312,7 @@ async function refreshAccessToken(token, clientId, clientSecret, issuer) {
197
312
  error: void 0
198
313
  };
199
314
  } catch (error) {
200
- console.error("Failed to refresh access token:", error);
315
+ console.error("[OAuth42] Failed to refresh access token:", error);
201
316
  return {
202
317
  ...token,
203
318
  error: "RefreshAccessTokenError"
@@ -210,12 +325,53 @@ import { default as default2 } from "next-auth";
210
325
 
211
326
  // src/server/middleware.ts
212
327
  import { NextResponse } from "next/server";
213
- import { getToken } from "next-auth/jwt";
328
+ import { getToken, encode } from "next-auth/jwt";
329
+ async function refreshTokens(refreshToken, clientId, clientSecret, issuer) {
330
+ try {
331
+ const tokenUrl = `${issuer}/oauth2/token`;
332
+ const response = await fetch(tokenUrl, {
333
+ method: "POST",
334
+ headers: {
335
+ "Content-Type": "application/x-www-form-urlencoded"
336
+ },
337
+ body: new URLSearchParams({
338
+ grant_type: "refresh_token",
339
+ refresh_token: refreshToken,
340
+ client_id: clientId,
341
+ client_secret: clientSecret
342
+ })
343
+ });
344
+ const data = await response.json();
345
+ if (!response.ok) {
346
+ console.error("[OAuth42 Middleware] Token refresh failed:", data);
347
+ return { success: false, error: data.error || "refresh_failed" };
348
+ }
349
+ console.log("[OAuth42 Middleware] Token refreshed successfully");
350
+ return {
351
+ success: true,
352
+ accessToken: data.access_token,
353
+ refreshToken: data.refresh_token,
354
+ expiresAt: Math.floor(Date.now() / 1e3) + (data.expires_in || 3600)
355
+ };
356
+ } catch (error) {
357
+ console.error("[OAuth42 Middleware] Token refresh error:", error);
358
+ return { success: false, error: "refresh_error" };
359
+ }
360
+ }
214
361
  function withOAuth42Auth(options = {}) {
362
+ const secret = process.env.NEXTAUTH_SECRET;
363
+ const clientId = process.env.OAUTH42_CLIENT_ID;
364
+ const clientSecret = process.env.OAUTH42_CLIENT_SECRET;
365
+ const issuer = process.env.OAUTH42_ISSUER || "https://localhost:8443";
366
+ if (!secret) {
367
+ console.warn("[OAuth42 Middleware] NEXTAUTH_SECRET not set");
368
+ }
215
369
  return async function middleware(req) {
370
+ const cookieName = options.cookiePrefix ? `${options.cookiePrefix}.session-token` : "next-auth.session-token";
216
371
  const token = await getToken({
217
372
  req,
218
- secret: process.env.NEXTAUTH_SECRET
373
+ secret,
374
+ cookieName
219
375
  });
220
376
  const pathname = req.nextUrl.pathname;
221
377
  if (options.publicPaths?.some((path) => pathname.startsWith(path))) {
@@ -225,16 +381,68 @@ function withOAuth42Auth(options = {}) {
225
381
  if (!needsProtection) {
226
382
  return NextResponse.next();
227
383
  }
228
- let isAuthorized = !!token;
229
- if (options.callbacks?.authorized) {
230
- isAuthorized = await options.callbacks.authorized({ token, req });
231
- }
232
- if (!isAuthorized) {
384
+ if (!token) {
233
385
  const signInUrl = options.pages?.signIn || "/auth/signin";
234
386
  const url = new URL(signInUrl, req.url);
235
387
  url.searchParams.set("callbackUrl", pathname);
236
388
  return NextResponse.redirect(url);
237
389
  }
390
+ const expiresAt = token.expiresAt;
391
+ const now = Math.floor(Date.now() / 1e3);
392
+ const bufferSeconds = 60;
393
+ const needsRefresh = expiresAt && now >= expiresAt - bufferSeconds;
394
+ if (needsRefresh && token.refreshToken && clientId && clientSecret) {
395
+ console.log("[OAuth42 Middleware] Access token expired, refreshing...");
396
+ const refreshed = await refreshTokens(
397
+ token.refreshToken,
398
+ clientId,
399
+ clientSecret,
400
+ issuer
401
+ );
402
+ if (refreshed.success && refreshed.accessToken && refreshed.refreshToken) {
403
+ const updatedToken = {
404
+ ...token,
405
+ accessToken: refreshed.accessToken,
406
+ refreshToken: refreshed.refreshToken,
407
+ expiresAt: refreshed.expiresAt
408
+ };
409
+ const newJwt = await encode({
410
+ token: updatedToken,
411
+ secret
412
+ });
413
+ const requestHeaders = new Headers(req.headers);
414
+ requestHeaders.set("x-oauth42-refreshed-token", refreshed.accessToken);
415
+ const response = NextResponse.next({
416
+ request: {
417
+ headers: requestHeaders
418
+ }
419
+ });
420
+ response.cookies.set(cookieName, newJwt, {
421
+ httpOnly: true,
422
+ sameSite: "lax",
423
+ path: "/",
424
+ secure: process.env.NODE_ENV === "production"
425
+ });
426
+ console.log("[OAuth42 Middleware] Cookie updated with refreshed tokens, header set for current request");
427
+ return response;
428
+ } else {
429
+ console.error("[OAuth42 Middleware] Refresh failed, redirecting to sign in");
430
+ const signInUrl = options.pages?.signIn || "/auth/signin";
431
+ const url = new URL(signInUrl, req.url);
432
+ url.searchParams.set("callbackUrl", pathname);
433
+ url.searchParams.set("error", "RefreshAccessTokenError");
434
+ return NextResponse.redirect(url);
435
+ }
436
+ }
437
+ if (options.callbacks?.authorized) {
438
+ const isAuthorized = await options.callbacks.authorized({ token, req });
439
+ if (!isAuthorized) {
440
+ const signInUrl = options.pages?.signIn || "/auth/signin";
441
+ const url = new URL(signInUrl, req.url);
442
+ url.searchParams.set("callbackUrl", pathname);
443
+ return NextResponse.redirect(url);
444
+ }
445
+ }
238
446
  return NextResponse.next();
239
447
  };
240
448
  }
@@ -258,7 +466,7 @@ function createMiddlewareConfig(protectedPaths = ["/protected"], publicPaths = [
258
466
  // src/server/hosted-auth-callback.ts
259
467
  import { NextResponse as NextResponse2 } from "next/server";
260
468
  import https from "https";
261
- import { encode } from "next-auth/jwt";
469
+ import { encode as encode2 } from "next-auth/jwt";
262
470
  function createHostedAuthCallback(options = {}) {
263
471
  return async function GET(request) {
264
472
  const {
@@ -321,7 +529,7 @@ function createHostedAuthCallback(options = {}) {
321
529
  } : {}
322
530
  });
323
531
  const userInfo = await userInfoResponse.json();
324
- const sessionToken = await encode({
532
+ const sessionToken = await encode2({
325
533
  token: {
326
534
  accessToken: tokens.access_token,
327
535
  refreshToken: tokens.refresh_token,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/auth.ts","../../src/provider.ts","../../src/server/session.ts","../../src/server/index.ts","../../src/server/middleware.ts","../../src/server/hosted-auth-callback.ts"],"sourcesContent":["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\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\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 // Store OAuth tokens in the JWT\n if (account) {\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 }\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 }\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 return token;\n },\n \n async session({ session, token }) {\n // Add OAuth42-specific data to session\n session.accessToken = token.accessToken as string;\n session.idToken = token.idToken as string;\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 }\n\n // Call custom callback if provided\n if (options.callbacks?.session) {\n return options.callbacks.session({ session, token } as any);\n }\n\n return session;\n },\n \n ...options.callbacks,\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 \n // Return the configuration and a function to create handlers\n return {\n auth: authOptions,\n handlers: NextAuth(authOptions),\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\n */\nexport async function refreshAccessToken(token: any, clientId: string, clientSecret: string, issuer?: string) {\n try {\n const baseUrl = issuer || process.env.OAUTH42_ISSUER || 'https://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 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('Failed to refresh access token:', error);\n return {\n ...token,\n error: 'RefreshAccessTokenError',\n };\n }\n}","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 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://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 // 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: 'HS256', // OAuth42 uses HS256 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 };\n },\n \n style: {\n logo: '/oauth42-logo.svg',\n bg: '#1e40af',\n text: '#ffffff',\n },\n \n options,\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 */\nexport async function getOAuth42Session(\n ...args: \n | [GetServerSidePropsContext['req'], GetServerSidePropsContext['res'], NextAuthOptions]\n | [NextApiRequest, NextApiResponse, NextAuthOptions]\n | [NextAuthOptions]\n) {\n return getNextAuthSession(...args as any);\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}","// Server-side exports\nexport { createAuth, createHandlers, getServerSession, refreshAccessToken } from './auth';\nexport type { CreateAuthOptions, NextAuthOptions } from './auth';\n\n// Re-export NextAuth from next-auth\nexport { default as NextAuth } from 'next-auth';\n\n// Re-export OAuth42Provider\nexport { OAuth42Provider } from '../provider';\n\nexport { withOAuth42Auth, createMiddlewareConfig } from './middleware';\nexport type { OAuth42AuthOptions } from './middleware';\n\nexport { getOAuth42Session, withOAuth42Session, withOAuth42ServerSideProps } from './session';\n\n// Hosted auth callback handler\nexport { createHostedAuthCallback } from './hosted-auth-callback';\nexport type { HostedAuthCallbackOptions } from './hosted-auth-callback';","import { NextRequest, NextResponse } from 'next/server';\nimport { getToken } from 'next-auth/jwt';\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\n/**\n * Middleware helper for protecting routes with OAuth42\n */\nexport function withOAuth42Auth(options: OAuth42AuthOptions = {}) {\n return async function middleware(req: NextRequest) {\n const token = await getToken({ \n req: req as any, \n secret: process.env.NEXTAUTH_SECRET \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 // Check authorization\n let isAuthorized = !!token;\n \n if (options.callbacks?.authorized) {\n isAuthorized = await options.callbacks.authorized({ token, req });\n }\n \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 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}","import { NextRequest, NextResponse } from 'next/server';\nimport https from 'https';\nimport { encode } from 'next-auth/jwt';\n\nexport interface HostedAuthCallbackOptions {\n /**\n * OAuth42 issuer URL (e.g., 'https://api.oauth42.com' or 'https://localhost:8443')\n */\n issuer?: string;\n\n /**\n * OAuth2 client ID\n */\n clientId?: string;\n\n /**\n * OAuth2 client secret\n */\n clientSecret?: string;\n\n /**\n * Application base URL (e.g., 'http://localhost:3000')\n */\n baseUrl?: string;\n\n /**\n * NextAuth secret for JWT encoding\n */\n nextAuthSecret?: string;\n\n /**\n * URL to redirect to after successful authentication\n * @default '/dashboard'\n */\n redirectUrl?: string;\n\n /**\n * URL to redirect to on error\n * @default '/'\n */\n errorUrl?: string;\n}\n\n/**\n * Creates a handler for OAuth42 hosted auth callback that integrates with NextAuth.\n *\n * This function handles the OAuth callback, exchanges the authorization code for tokens,\n * fetches user info, and creates a NextAuth-compatible session cookie.\n *\n * @example\n * ```typescript\n * // app/api/oauth/callback/route.ts\n * import { createHostedAuthCallback } from '@oauth42/next/server';\n *\n * export const GET = createHostedAuthCallback({\n * redirectUrl: '/dashboard',\n * });\n * ```\n */\nexport function createHostedAuthCallback(options: HostedAuthCallbackOptions = {}) {\n return async function GET(request: NextRequest) {\n const {\n issuer = process.env.OAUTH42_ISSUER || 'https://api.oauth42.com',\n clientId = process.env.OAUTH42_CLIENT_ID,\n clientSecret = process.env.OAUTH42_CLIENT_SECRET,\n baseUrl = process.env.NEXTAUTH_URL,\n nextAuthSecret = process.env.NEXTAUTH_SECRET,\n redirectUrl = '/dashboard',\n errorUrl = '/',\n } = options;\n\n if (!clientId || !clientSecret) {\n console.error('OAuth42 client credentials are required');\n return NextResponse.redirect(new URL(`${errorUrl}?error=missing_credentials`, request.url));\n }\n\n if (!nextAuthSecret) {\n console.error('NEXTAUTH_SECRET is required');\n return NextResponse.redirect(new URL(`${errorUrl}?error=missing_secret`, request.url));\n }\n\n const searchParams = request.nextUrl.searchParams;\n const code = searchParams.get('code');\n\n if (!code) {\n return NextResponse.redirect(new URL(`${errorUrl}?error=missing_code`, request.url));\n }\n\n try {\n // Exchange authorization code for tokens\n const tokenEndpoint = `${issuer}/oauth2/token`;\n\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: `${baseUrl}/api/oauth/callback`,\n client_id: clientId,\n client_secret: clientSecret,\n });\n\n // For development, use custom agent to disable SSL verification\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n };\n\n if (process.env.NODE_ENV !== 'production') {\n const agent = new https.Agent({\n rejectUnauthorized: false,\n });\n (fetchOptions as any).agent = agent;\n }\n\n const tokenResponse = await fetch(tokenEndpoint, fetchOptions);\n const tokens = await tokenResponse.json();\n\n if (!tokenResponse.ok) {\n console.error('Token exchange failed:', tokens);\n return NextResponse.redirect(new URL(`${errorUrl}?error=token_exchange_failed`, request.url));\n }\n\n // Fetch user info\n const userInfoEndpoint = `${issuer}/oauth2/userinfo`;\n const userInfoResponse = await fetch(userInfoEndpoint, {\n headers: {\n 'Authorization': `Bearer ${tokens.access_token}`,\n },\n ...(process.env.NODE_ENV !== 'production' ? {\n agent: new https.Agent({ rejectUnauthorized: false })\n } as any : {})\n });\n\n const userInfo = await userInfoResponse.json();\n\n // Create NextAuth-compatible session token\n const sessionToken = await encode({\n token: {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: Math.floor(Date.now() / 1000) + (tokens.expires_in || 3600),\n idToken: tokens.id_token,\n email: userInfo.email,\n username: userInfo.username,\n name: userInfo.name,\n sub: userInfo.sub,\n },\n secret: nextAuthSecret,\n });\n\n const redirectResponse = NextResponse.redirect(new URL(redirectUrl, request.url));\n\n // Set NextAuth session cookie\n const cookieName = process.env.NODE_ENV === 'production'\n ? '__Secure-next-auth.session-token'\n : 'next-auth.session-token';\n\n redirectResponse.cookies.set(cookieName, sessionToken, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 60 * 60 * 24 * 30, // 30 days\n path: '/',\n });\n\n return redirectResponse;\n } catch (error) {\n console.error('OAuth callback error:', error);\n return NextResponse.redirect(new URL(`${errorUrl}?error=callback_failed`, request.url));\n }\n };\n}\n"],"mappings":"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","names":["https","default","NextResponse"]}
1
+ {"version":3,"sources":["../../src/server/auth.ts","../../src/provider.ts","../../src/server/session.ts","../../src/server/index.ts","../../src/server/middleware.ts","../../src/server/hosted-auth-callback.ts"],"sourcesContent":["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 }\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 }\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 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: 900, // 15 minutes\n },\n },\n // State cookie for OAuth CSRF protection\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: 900, // 15 minutes\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://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 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 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://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 // 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: 'HS256', // OAuth42 uses HS256 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 };\n },\n \n style: {\n logo: '/oauth42-logo.svg',\n bg: '#1e40af',\n text: '#ffffff',\n },\n \n options,\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 console.log('[OAuth42 Session] Using refreshed token from middleware');\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}","// Server-side exports\nexport { createAuth, createHandlers, getServerSession, refreshAccessToken } from './auth';\nexport type { CreateAuthOptions, NextAuthOptions } from './auth';\n\n// Re-export NextAuth from next-auth\nexport { default as NextAuth } from 'next-auth';\n\n// Re-export OAuth42Provider\nexport { OAuth42Provider } from '../provider';\n\nexport { withOAuth42Auth, createMiddlewareConfig } from './middleware';\nexport type { OAuth42AuthOptions } from './middleware';\n\nexport { getOAuth42Session, withOAuth42Session, withOAuth42ServerSideProps } from './session';\n\n// Hosted auth callback handler\nexport { createHostedAuthCallback } from './hosted-auth-callback';\nexport type { HostedAuthCallbackOptions } from './hosted-auth-callback';","import { NextRequest, NextResponse } from 'next/server';\nimport { getToken, encode } from 'next-auth/jwt';\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 (60 second buffer)\n const expiresAt = token.expiresAt as number | undefined;\n const now = Math.floor(Date.now() / 1000);\n const bufferSeconds = 60;\n const needsRefresh = expiresAt && now >= expiresAt - bufferSeconds;\n\n if (needsRefresh && token.refreshToken && clientId && clientSecret) {\n console.log('[OAuth42 Middleware] Access token expired, refreshing...');\n\n const refreshed = await refreshTokens(\n token.refreshToken as string,\n clientId,\n clientSecret,\n issuer\n );\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 // Set cookie with same settings NextAuth uses (for future requests)\n response.cookies.set(cookieName, newJwt, {\n httpOnly: true,\n sameSite: 'lax',\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n });\n\n console.log('[OAuth42 Middleware] Cookie updated with refreshed tokens, header set for current request');\n return response;\n } else {\n // Refresh failed - redirect to sign in\n console.error('[OAuth42 Middleware] Refresh failed, redirecting to sign in');\n const signInUrl = options.pages?.signIn || '/auth/signin';\n const url = new URL(signInUrl, req.url);\n url.searchParams.set('callbackUrl', pathname);\n url.searchParams.set('error', 'RefreshAccessTokenError');\n return NextResponse.redirect(url);\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","import { NextRequest, NextResponse } from 'next/server';\nimport https from 'https';\nimport { encode } from 'next-auth/jwt';\n\nexport interface HostedAuthCallbackOptions {\n /**\n * OAuth42 issuer URL (e.g., 'https://api.oauth42.com' or 'https://localhost:8443')\n */\n issuer?: string;\n\n /**\n * OAuth2 client ID\n */\n clientId?: string;\n\n /**\n * OAuth2 client secret\n */\n clientSecret?: string;\n\n /**\n * Application base URL (e.g., 'http://localhost:3000')\n */\n baseUrl?: string;\n\n /**\n * NextAuth secret for JWT encoding\n */\n nextAuthSecret?: string;\n\n /**\n * URL to redirect to after successful authentication\n * @default '/dashboard'\n */\n redirectUrl?: string;\n\n /**\n * URL to redirect to on error\n * @default '/'\n */\n errorUrl?: string;\n}\n\n/**\n * Creates a handler for OAuth42 hosted auth callback that integrates with NextAuth.\n *\n * This function handles the OAuth callback, exchanges the authorization code for tokens,\n * fetches user info, and creates a NextAuth-compatible session cookie.\n *\n * @example\n * ```typescript\n * // app/api/oauth/callback/route.ts\n * import { createHostedAuthCallback } from '@oauth42/next/server';\n *\n * export const GET = createHostedAuthCallback({\n * redirectUrl: '/dashboard',\n * });\n * ```\n */\nexport function createHostedAuthCallback(options: HostedAuthCallbackOptions = {}) {\n return async function GET(request: NextRequest) {\n const {\n issuer = process.env.OAUTH42_ISSUER || 'https://api.oauth42.com',\n clientId = process.env.OAUTH42_CLIENT_ID,\n clientSecret = process.env.OAUTH42_CLIENT_SECRET,\n baseUrl = process.env.NEXTAUTH_URL,\n nextAuthSecret = process.env.NEXTAUTH_SECRET,\n redirectUrl = '/dashboard',\n errorUrl = '/',\n } = options;\n\n if (!clientId || !clientSecret) {\n console.error('OAuth42 client credentials are required');\n return NextResponse.redirect(new URL(`${errorUrl}?error=missing_credentials`, request.url));\n }\n\n if (!nextAuthSecret) {\n console.error('NEXTAUTH_SECRET is required');\n return NextResponse.redirect(new URL(`${errorUrl}?error=missing_secret`, request.url));\n }\n\n const searchParams = request.nextUrl.searchParams;\n const code = searchParams.get('code');\n\n if (!code) {\n return NextResponse.redirect(new URL(`${errorUrl}?error=missing_code`, request.url));\n }\n\n try {\n // Exchange authorization code for tokens\n const tokenEndpoint = `${issuer}/oauth2/token`;\n\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: `${baseUrl}/api/oauth/callback`,\n client_id: clientId,\n client_secret: clientSecret,\n });\n\n // For development, use custom agent to disable SSL verification\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body.toString(),\n };\n\n if (process.env.NODE_ENV !== 'production') {\n const agent = new https.Agent({\n rejectUnauthorized: false,\n });\n (fetchOptions as any).agent = agent;\n }\n\n const tokenResponse = await fetch(tokenEndpoint, fetchOptions);\n const tokens = await tokenResponse.json();\n\n if (!tokenResponse.ok) {\n console.error('Token exchange failed:', tokens);\n return NextResponse.redirect(new URL(`${errorUrl}?error=token_exchange_failed`, request.url));\n }\n\n // Fetch user info\n const userInfoEndpoint = `${issuer}/oauth2/userinfo`;\n const userInfoResponse = await fetch(userInfoEndpoint, {\n headers: {\n 'Authorization': `Bearer ${tokens.access_token}`,\n },\n ...(process.env.NODE_ENV !== 'production' ? {\n agent: new https.Agent({ rejectUnauthorized: false })\n } as any : {})\n });\n\n const userInfo = await userInfoResponse.json();\n\n // Create NextAuth-compatible session token\n const sessionToken = await encode({\n token: {\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token,\n expiresAt: Math.floor(Date.now() / 1000) + (tokens.expires_in || 3600),\n idToken: tokens.id_token,\n email: userInfo.email,\n username: userInfo.username,\n name: userInfo.name,\n sub: userInfo.sub,\n },\n secret: nextAuthSecret,\n });\n\n const redirectResponse = NextResponse.redirect(new URL(redirectUrl, request.url));\n\n // Set NextAuth session cookie\n const cookieName = process.env.NODE_ENV === 'production'\n ? '__Secure-next-auth.session-token'\n : 'next-auth.session-token';\n\n redirectResponse.cookies.set(cookieName, sessionToken, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 60 * 60 * 24 * 30, // 30 days\n path: '/',\n });\n\n return redirectResponse;\n } catch (error) {\n console.error('OAuth callback error:', error);\n return NextResponse.redirect(new URL(`${errorUrl}?error=callback_failed`, request.url));\n }\n };\n}\n"],"mappings":";AAAA,OAAO,qBAAqB;;;ACyBrB,SAAS,gBACd,SACgB;AAChB,QAAM,SAAS,QAAQ,UAAU,QAAQ,IAAI,kBAAkB;AAC/D,QAAM,UAAU,OAAO,QAAQ,OAAO,EAAE;AAExC,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA;AAAA,IAGT,WAAW,GAAG,OAAO;AAAA;AAAA,IAGrB,eAAe;AAAA,MACb,KAAK,GAAG,OAAO;AAAA,MACf,QAAQ;AAAA,QACN,QAAQ,QAAQ,UAAU,CAAC,UAAU,WAAW,OAAO,GAAG,KAAK,GAAG;AAAA,QAClE,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,GAAG,OAAO;AAAA,IACjB,UAAU,GAAG,OAAO;AAAA,IAEpB,QAAQ;AAAA,MACN,IAAI,QAAQ;AAAA,MACZ,QAAQ,QAAQ;AAAA,MAChB,4BAA4B;AAAA,MAC5B,8BAA8B;AAAA;AAAA,IAChC;AAAA,IAEA,QAAQ;AAAA,IAER,QAAQ,QAAQ,gBAAgB,QAAQ,CAAC,QAAQ,OAAO,IAAI,CAAC,OAAO;AAAA,IAEpE,QAAQ,SAAyB,QAAa;AAC5C,aAAO;AAAA,QACL,IAAI,QAAQ,OAAO,QAAQ,MAAM,QAAQ;AAAA,QACzC,OAAO,QAAQ;AAAA,QACf,eAAe,QAAQ,iBAAiB,oBAAI,KAAK,IAAI;AAAA,QACrD,MAAM,QAAQ,QAAQ,GAAG,QAAQ,cAAc,EAAE,IAAI,QAAQ,eAAe,EAAE,GAAG,KAAK;AAAA,QACtF,OAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,IAEA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,MAAM;AAAA,IACR;AAAA,IAEA;AAAA,EACF;AACF;;;AChFA,SAAS,oBAAoB,0BAA0B;AAGvD,SAAS,eAAe;AAGxB,IAAM,yBAAyB;AAuB/B,eAAsB,qBACjB,MAIH;AACA,QAAM,UAAU,MAAM,mBAAmB,GAAG,IAAW;AAEvD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAKA,MAAI,iBAAgC;AAEpC,MAAI;AAEF,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,cAAc,MAAM,QAAQ;AAClC,uBAAiB,YAAY,IAAI,sBAAsB;AAAA,IACzD,WAES,KAAK,WAAW,GAAG;AAC1B,YAAM,MAAM,KAAK,CAAC;AAClB,uBAAkB,IAAI,QAAQ,sBAAsB,KAAgB;AAAA,IACtE;AAAA,EACF,QAAQ;AAAA,EAGR;AAEA,MAAI,gBAAgB;AAClB,YAAQ,IAAI,yDAAyD;AACrE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,aAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,mBACd,SACA,aACA;AACA,SAAO,OAAO,KAAqB,QAAyB;AAC1D,UAAM,UAAU,MAAM,kBAAkB,KAAK,KAAK,WAAW;AAE7D,QAAI,CAAC,SAAS;AACZ,aAAO,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,IACvD;AAEA,WAAO,QAAQ,KAAK,KAAK,OAAO;AAAA,EAClC;AACF;AAKO,SAAS,2BACd,oBAIA,aACA;AACA,SAAO,OAAO,YAAuC;AACnD,UAAM,UAAU,MAAM;AAAA,MACpB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,IACF;AAEA,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,UAAU;AAAA,UACR,aAAa;AAAA,UACb,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,WAAO,mBAAmB,SAAS,OAAO;AAAA,EAC5C;AACF;;;AFjHA,IAAM,WAAY,gBAAwB,WAAW;AAKrD,IAAI,gBAAqC;AAwBlC,SAAS,WAAW,UAA6B,CAAC,GAAG;AAC1D,QAAM,WAAW,QAAQ,YAAY,QAAQ,IAAI;AACjD,QAAM,eAAe,QAAQ,gBAAgB,QAAQ,IAAI;AAEzD,MAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AAEA,QAAM,cAA+B;AAAA,IACnC,WAAW;AAAA,MACT,gBAAgB;AAAA,QACd;AAAA,QACA;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,QAChB,aAAa,QAAQ;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,IAEA,WAAW;AAAA,MACT,MAAM,IAAI,EAAE,OAAO,SAAS,QAAQ,GAAG;AACrC,gBAAQ,IAAI,qCAAqC,EAAE,YAAY,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,QAAQ,CAAC;AAGjG,YAAI,SAAS;AACX,kBAAQ,IAAI,uDAAuD;AACnE,gBAAM,cAAc,QAAQ;AAC5B,gBAAM,eAAe,QAAQ;AAC7B,gBAAM,YAAY,QAAQ;AAC1B,gBAAM,UAAU,QAAQ;AACxB,gBAAM,WAAW;AACjB,gBAAM,eAAe;AACrB,gBAAM,SAAS,QAAQ,UAAU,QAAQ,IAAI,4BAA4B,QAAQ,IAAI;AAAA,QACvF;AAGA,YAAI,SAAS;AACX,gBAAM,iBAAiB;AACvB,gBAAM,QAAQ,eAAe;AAC7B,gBAAM,WAAW,eAAe;AAChC,gBAAM,gBAAgB,eAAe;AAAA,QACvC;AAOA,YAAI,QAAQ,WAAW,KAAK;AAC1B,iBAAO,QAAQ,UAAU,IAAI,EAAE,OAAO,SAAS,QAAQ,CAAQ;AAAA,QACjE;AAEA,gBAAQ,IAAI,sDAAsD;AAClE,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,QAAQ,EAAE,SAAS,MAAM,GAAG;AAChC,gBAAQ,IAAI,yCAAyC,EAAE,UAAU,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,QAAQ,CAAC;AAGjG,gBAAQ,cAAc,MAAM;AAC5B,gBAAQ,UAAU,MAAM;AAGxB,YAAI,MAAM,OAAO;AACf,kBAAQ,QAAQ,MAAM;AAAA,QACxB;AAEA,YAAI,QAAQ,MAAM;AAChB,kBAAQ,KAAK,QAAQ,MAAM;AAC3B,kBAAQ,KAAK,OAAO,MAAM;AAC1B,kBAAQ,KAAK,WAAW,MAAM;AAC9B,kBAAQ,KAAK,gBAAgB,MAAM;AAAA,QACrC;AAGA,YAAI,QAAQ,WAAW,SAAS;AAC9B,iBAAO,QAAQ,UAAU,QAAQ,EAAE,SAAS,MAAM,CAAQ;AAAA,QAC5D;AAEA,gBAAQ,IAAI,4DAA4D;AACxE,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO;AAAA,MACP,GAAG,QAAQ;AAAA,IACb;AAAA,IAEA,SAAS;AAAA,MACP,UAAU;AAAA,MACV,GAAG,QAAQ;AAAA,IACb;AAAA,IAEA,OAAO,QAAQ,SAAS,QAAQ,IAAI,aAAa;AAAA,IAEjD,QAAQ,QAAQ,IAAI;AAAA;AAAA,IAGpB,GAAI,QAAQ,gBAAgB;AAAA,MAC1B,SAAS;AAAA,QACP,cAAc;AAAA,UACZ,MAAM,GAAG,QAAQ,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,UACnC;AAAA,QACF;AAAA,QACA,aAAa;AAAA,UACX,MAAM,GAAG,QAAQ,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,UACnC;AAAA,QACF;AAAA,QACA,WAAW;AAAA,UACT,MAAM,GAAG,QAAQ,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,UACnC;AAAA,QACF;AAAA;AAAA,QAEA,kBAAkB;AAAA,UAChB,MAAM,GAAG,QAAQ,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,YACjC,QAAQ;AAAA;AAAA,UACV;AAAA,QACF;AAAA;AAAA,QAEA,OAAO;AAAA,UACL,MAAM,GAAG,QAAQ,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,YACjC,QAAQ;AAAA;AAAA,UACV;AAAA,QACF;AAAA;AAAA,QAEA,OAAO;AAAA,UACL,MAAM,GAAG,QAAQ,YAAY;AAAA,UAC7B,SAAS;AAAA,YACP,UAAU;AAAA,YACV,UAAU;AAAA,YACV,MAAM;AAAA,YACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,UAAU,SAAS,WAAW;AACpC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,EAAE,KAAK,SAAS,MAAM,QAAQ;AAAA,EAC1C;AACF;AAKO,SAAS,eAAe,aAA8B;AAC3D,QAAM,UAAU,SAAS,WAAW;AACpC,SAAO,EAAE,KAAK,SAAS,MAAM,QAAQ;AACvC;AASO,IAAM,mBAAmB;AAUhC,eAAsB,mBAAmB,OAAY,UAAkB,cAAsB,QAA+B;AAE1H,MAAI,eAAe;AACjB,YAAQ,IAAI,mDAAmD;AAC/D,WAAO,MAAM;AAAA,EACf;AAGA,kBAAgB,UAAU,OAAO,UAAU,cAAc,MAAM;AAC/D,MAAI;AACF,WAAO,MAAM;AAAA,EACf,UAAE;AACA,oBAAgB;AAAA,EAClB;AACF;AAEA,eAAe,UAAU,OAAY,UAAkB,cAAsB,QAA+B;AAC1G,MAAI;AACF,UAAM,UAAU,UAAU,QAAQ,IAAI,kBAAkB;AACxD,UAAM,WAAW,GAAG,OAAO;AAG3B,UAAM,eAAoB;AAAA,MACxB,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,eAAe,MAAM;AAAA,QACrB,WAAW;AAAA,QACX,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AAGA,QAAI,QAAQ,IAAI,aAAa,gBAAgB,SAAS,WAAW,UAAU,GAAG;AAC5E,YAAMA,SAAQ,MAAM,OAAO,OAAO;AAClC,mBAAa,QAAQ,IAAIA,OAAM,MAAM;AAAA,QACnC,oBAAoB;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,UAAM,WAAW,MAAM,MAAM,UAAU,YAAY;AACnD,UAAM,kBAAkB,MAAM,SAAS,KAAK;AAE5C,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM;AAAA,IACR;AAEA,YAAQ,IAAI,wCAAwC;AACpD,WAAO;AAAA,MACL,GAAG;AAAA,MACH,aAAa,gBAAgB;AAAA,MAC7B,cAAc,gBAAgB,iBAAiB,MAAM;AAAA;AAAA,MAErD,WAAW,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,KAAK,gBAAgB,cAAc;AAAA;AAAA,MAE1E,OAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,6CAA6C,KAAK;AAChE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,OAAO;AAAA,IACT;AAAA,EACF;AACF;;;AG7SA,SAAoB,WAAXC,gBAA2B;;;ACLpC,SAAsB,oBAAoB;AAC1C,SAAS,UAAU,cAAc;AAsBjC,eAAe,cACb,cACA,UACA,cACA,QACgH;AAChH,MAAI;AACF,UAAM,WAAW,GAAG,MAAM;AAE1B,UAAM,WAAW,MAAM,MAAM,UAAU;AAAA,MACrC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,IAAI,gBAAgB;AAAA,QACxB,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,WAAW;AAAA,QACX,eAAe;AAAA,MACjB,CAAC;AAAA,IACH,CAAC;AAED,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,MAAM,8CAA8C,IAAI;AAChE,aAAO,EAAE,SAAS,OAAO,OAAO,KAAK,SAAS,iBAAiB;AAAA,IACjE;AAEA,YAAQ,IAAI,mDAAmD;AAC/D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB,WAAW,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,KAAK,KAAK,cAAc;AAAA,IACjE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,6CAA6C,KAAK;AAChE,WAAO,EAAE,SAAS,OAAO,OAAO,gBAAgB;AAAA,EAClD;AACF;AASO,SAAS,gBAAgB,UAA8B,CAAC,GAAG;AAChE,QAAM,SAAS,QAAQ,IAAI;AAC3B,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,eAAe,QAAQ,IAAI;AACjC,QAAM,SAAS,QAAQ,IAAI,kBAAkB;AAE7C,MAAI,CAAC,QAAQ;AACX,YAAQ,KAAK,8CAA8C;AAAA,EAC7D;AAEA,SAAO,eAAe,WAAW,KAAkB;AAEjD,UAAM,aAAa,QAAQ,eACvB,GAAG,QAAQ,YAAY,mBACvB;AAEJ,UAAM,QAAQ,MAAM,SAAS;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,WAAW,IAAI,QAAQ;AAG7B,QAAI,QAAQ,aAAa,KAAK,UAAQ,SAAS,WAAW,IAAI,CAAC,GAAG;AAChE,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,kBAAkB,QAAQ,iBAC5B,QAAQ,eAAe,KAAK,UAAQ,SAAS,WAAW,IAAI,CAAC,IAC7D;AAEJ,QAAI,CAAC,iBAAiB;AACpB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,QAAI,CAAC,OAAO;AACV,YAAM,YAAY,QAAQ,OAAO,UAAU;AAC3C,YAAM,MAAM,IAAI,IAAI,WAAW,IAAI,GAAG;AACtC,UAAI,aAAa,IAAI,eAAe,QAAQ;AAC5C,aAAO,aAAa,SAAS,GAAG;AAAA,IAClC;AAGA,UAAM,YAAY,MAAM;AACxB,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,UAAM,gBAAgB;AACtB,UAAM,eAAe,aAAa,OAAO,YAAY;AAErD,QAAI,gBAAgB,MAAM,gBAAgB,YAAY,cAAc;AAClE,cAAQ,IAAI,0DAA0D;AAEtE,YAAM,YAAY,MAAM;AAAA,QACtB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,UAAU,WAAW,UAAU,eAAe,UAAU,cAAc;AAExE,cAAM,eAAe;AAAA,UACnB,GAAG;AAAA,UACH,aAAa,UAAU;AAAA,UACvB,cAAc,UAAU;AAAA,UACxB,WAAW,UAAU;AAAA,QACvB;AAGA,cAAM,SAAS,MAAM,OAAO;AAAA,UAC1B,OAAO;AAAA,UACP;AAAA,QACF,CAAC;AAID,cAAM,iBAAiB,IAAI,QAAQ,IAAI,OAAO;AAC9C,uBAAe,IAAI,6BAA6B,UAAU,WAAW;AAErE,cAAM,WAAW,aAAa,KAAK;AAAA,UACjC,SAAS;AAAA,YACP,SAAS;AAAA,UACX;AAAA,QACF,CAAC;AAGD,iBAAS,QAAQ,IAAI,YAAY,QAAQ;AAAA,UACvC,UAAU;AAAA,UACV,UAAU;AAAA,UACV,MAAM;AAAA,UACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACnC,CAAC;AAED,gBAAQ,IAAI,2FAA2F;AACvG,eAAO;AAAA,MACT,OAAO;AAEL,gBAAQ,MAAM,6DAA6D;AAC3E,cAAM,YAAY,QAAQ,OAAO,UAAU;AAC3C,cAAM,MAAM,IAAI,IAAI,WAAW,IAAI,GAAG;AACtC,YAAI,aAAa,IAAI,eAAe,QAAQ;AAC5C,YAAI,aAAa,IAAI,SAAS,yBAAyB;AACvD,eAAO,aAAa,SAAS,GAAG;AAAA,MAClC;AAAA,IACF;AAGA,QAAI,QAAQ,WAAW,YAAY;AACjC,YAAM,eAAe,MAAM,QAAQ,UAAU,WAAW,EAAE,OAAO,IAAI,CAAC;AACtE,UAAI,CAAC,cAAc;AACjB,cAAM,YAAY,QAAQ,OAAO,UAAU;AAC3C,cAAM,MAAM,IAAI,IAAI,WAAW,IAAI,GAAG;AACtC,YAAI,aAAa,IAAI,eAAe,QAAQ;AAC5C,eAAO,aAAa,SAAS,GAAG;AAAA,MAClC;AAAA,IACF;AAEA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;AAKO,SAAS,uBACd,iBAA2B,CAAC,YAAY,GACxC,cAAwB,CAAC,SAAS,WAAW,GAC7C;AACA,SAAO;AAAA,IACL,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQP;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzNA,SAAsB,gBAAAC,qBAAoB;AAC1C,OAAO,WAAW;AAClB,SAAS,UAAAC,eAAc;AAyDhB,SAAS,yBAAyB,UAAqC,CAAC,GAAG;AAChF,SAAO,eAAe,IAAI,SAAsB;AAC9C,UAAM;AAAA,MACJ,SAAS,QAAQ,IAAI,kBAAkB;AAAA,MACvC,WAAW,QAAQ,IAAI;AAAA,MACvB,eAAe,QAAQ,IAAI;AAAA,MAC3B,UAAU,QAAQ,IAAI;AAAA,MACtB,iBAAiB,QAAQ,IAAI;AAAA,MAC7B,cAAc;AAAA,MACd,WAAW;AAAA,IACb,IAAI;AAEJ,QAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,cAAQ,MAAM,yCAAyC;AACvD,aAAOD,cAAa,SAAS,IAAI,IAAI,GAAG,QAAQ,8BAA8B,QAAQ,GAAG,CAAC;AAAA,IAC5F;AAEA,QAAI,CAAC,gBAAgB;AACnB,cAAQ,MAAM,6BAA6B;AAC3C,aAAOA,cAAa,SAAS,IAAI,IAAI,GAAG,QAAQ,yBAAyB,QAAQ,GAAG,CAAC;AAAA,IACvF;AAEA,UAAM,eAAe,QAAQ,QAAQ;AACrC,UAAM,OAAO,aAAa,IAAI,MAAM;AAEpC,QAAI,CAAC,MAAM;AACT,aAAOA,cAAa,SAAS,IAAI,IAAI,GAAG,QAAQ,uBAAuB,QAAQ,GAAG,CAAC;AAAA,IACrF;AAEA,QAAI;AAEF,YAAM,gBAAgB,GAAG,MAAM;AAE/B,YAAM,OAAO,IAAI,gBAAgB;AAAA,QAC/B,YAAY;AAAA,QACZ;AAAA,QACA,cAAc,GAAG,OAAO;AAAA,QACxB,WAAW;AAAA,QACX,eAAe;AAAA,MACjB,CAAC;AAGD,YAAM,eAA4B;AAAA,QAChC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,SAAS;AAAA,MACtB;AAEA,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAM,QAAQ,IAAI,MAAM,MAAM;AAAA,UAC5B,oBAAoB;AAAA,QACtB,CAAC;AACD,QAAC,aAAqB,QAAQ;AAAA,MAChC;AAEA,YAAM,gBAAgB,MAAM,MAAM,eAAe,YAAY;AAC7D,YAAM,SAAS,MAAM,cAAc,KAAK;AAExC,UAAI,CAAC,cAAc,IAAI;AACrB,gBAAQ,MAAM,0BAA0B,MAAM;AAC9C,eAAOA,cAAa,SAAS,IAAI,IAAI,GAAG,QAAQ,gCAAgC,QAAQ,GAAG,CAAC;AAAA,MAC9F;AAGA,YAAM,mBAAmB,GAAG,MAAM;AAClC,YAAM,mBAAmB,MAAM,MAAM,kBAAkB;AAAA,QACrD,SAAS;AAAA,UACP,iBAAiB,UAAU,OAAO,YAAY;AAAA,QAChD;AAAA,QACA,GAAI,QAAQ,IAAI,aAAa,eAAe;AAAA,UAC1C,OAAO,IAAI,MAAM,MAAM,EAAE,oBAAoB,MAAM,CAAC;AAAA,QACtD,IAAW,CAAC;AAAA,MACd,CAAC;AAED,YAAM,WAAW,MAAM,iBAAiB,KAAK;AAG7C,YAAM,eAAe,MAAMC,QAAO;AAAA,QAChC,OAAO;AAAA,UACL,aAAa,OAAO;AAAA,UACpB,cAAc,OAAO;AAAA,UACrB,WAAW,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,KAAK,OAAO,cAAc;AAAA,UACjE,SAAS,OAAO;AAAA,UAChB,OAAO,SAAS;AAAA,UAChB,UAAU,SAAS;AAAA,UACnB,MAAM,SAAS;AAAA,UACf,KAAK,SAAS;AAAA,QAChB;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,YAAM,mBAAmBD,cAAa,SAAS,IAAI,IAAI,aAAa,QAAQ,GAAG,CAAC;AAGhF,YAAM,aAAa,QAAQ,IAAI,aAAa,eACxC,qCACA;AAEJ,uBAAiB,QAAQ,IAAI,YAAY,cAAc;AAAA,QACrD,UAAU;AAAA,QACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACjC,UAAU;AAAA,QACV,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,QACvB,MAAM;AAAA,MACR,CAAC;AAED,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,aAAOA,cAAa,SAAS,IAAI,IAAI,GAAG,QAAQ,0BAA0B,QAAQ,GAAG,CAAC;AAAA,IACxF;AAAA,EACF;AACF;","names":["https","default","NextResponse","encode"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oauth42/next",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "Official OAuth42 SDK for Next.js applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,6 +20,11 @@
20
20
  "types": "./dist/server/index.d.ts",
21
21
  "import": "./dist/server/index.mjs",
22
22
  "require": "./dist/server/index.js"
23
+ },
24
+ "./middleware": {
25
+ "types": "./dist/middleware/index.d.ts",
26
+ "import": "./dist/middleware/index.mjs",
27
+ "require": "./dist/middleware/index.js"
23
28
  }
24
29
  },
25
30
  "scripts": {
@@ -70,11 +75,11 @@
70
75
  "license": "SEE LICENSE IN LICENSE",
71
76
  "repository": {
72
77
  "type": "git",
73
- "url": "https://github.com/devxpod/oauth42.git",
78
+ "url": "https://github.com/oauth42/oauth42.git",
74
79
  "directory": "src/ts/sdk/o42next"
75
80
  },
76
81
  "bugs": {
77
- "url": "https://github.com/devxpod/oauth42/issues"
82
+ "url": "https://github.com/oauth42/oauth42/issues"
78
83
  },
79
84
  "homepage": "https://oauth42.com"
80
85
  }
@@ -5,6 +5,7 @@ declare module "next-auth" {
5
5
  interface Session {
6
6
  accessToken?: string
7
7
  idToken?: string
8
+ error?: string // Token refresh error (e.g., "RefreshAccessTokenError")
8
9
  user?: {
9
10
  email?: string | null
10
11
  name?: string | null
@@ -24,5 +25,6 @@ declare module "next-auth/jwt" {
24
25
  email?: string
25
26
  username?: string
26
27
  emailVerified?: boolean
28
+ error?: string // Token refresh error
27
29
  }
28
30
  }