@oauth42/next 0.4.7 → 0.5.0
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 +47 -2
- package/dist/{auth-BThRQMzh.d.mts → auth-CYMPe3k0.d.ts} +10 -0
- package/dist/{auth-BThRQMzh.d.ts → auth-D3tAruwx.d.mts} +10 -0
- package/dist/client/index.d.mts +19 -11
- package/dist/client/index.d.ts +19 -11
- package/dist/client/index.js +10 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +10 -1
- package/dist/client/index.mjs.map +1 -1
- package/dist/index-Cfqxl9r2.d.mts +94 -0
- package/dist/index-Cfqxl9r2.d.ts +94 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +237 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +237 -28
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/index.d.mts +2 -39
- package/dist/middleware/index.d.ts +2 -39
- package/dist/middleware/index.js +107 -10
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/index.mjs +107 -10
- package/dist/middleware/index.mjs.map +1 -1
- package/dist/server/index.d.mts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +243 -28
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +240 -28
- package/dist/server/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/server/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { C as CreateAuthOptions, a as OAuth42Provider, c as createAuth, f as createHandlers, g as getOAuth42Session, d as getServerSession, r as refreshAccessToken, w as withOAuth42ServerSideProps, e as withOAuth42Session } from '../auth-
|
|
1
|
+
export { C as CreateAuthOptions, a as OAuth42Provider, c as createAuth, f as createHandlers, g as getOAuth42Session, d as getServerSession, r as refreshAccessToken, w as withOAuth42ServerSideProps, e as withOAuth42Session } from '../auth-CYMPe3k0.js';
|
|
2
2
|
export { default as NextAuth, NextAuthOptions } from 'next-auth';
|
|
3
|
-
export { OAuth42AuthOptions, createMiddlewareConfig, withOAuth42Auth } from '../
|
|
3
|
+
export { B as BackendSessionConfig, a as BackendSessionResponse, b as BackendSessionUser, O as OAuth42AuthOptions, S as SessionStoreMode, d as createBackendSession, c as createMiddlewareConfig, r as resolveBackendSession, e as revokeBackendSession, w as withOAuth42Auth } from '../index-Cfqxl9r2.js';
|
|
4
4
|
import { NextRequest, NextResponse } from 'next/server';
|
|
5
5
|
import 'next-auth/providers/oauth';
|
|
6
6
|
import 'next';
|
package/dist/server/index.js
CHANGED
|
@@ -33,12 +33,15 @@ __export(server_exports, {
|
|
|
33
33
|
NextAuth: () => import_next_auth3.default,
|
|
34
34
|
OAuth42Provider: () => OAuth42Provider,
|
|
35
35
|
createAuth: () => createAuth,
|
|
36
|
+
createBackendSession: () => createBackendSession,
|
|
36
37
|
createHandlers: () => createHandlers,
|
|
37
38
|
createHostedAuthCallback: () => createHostedAuthCallback,
|
|
38
39
|
createMiddlewareConfig: () => createMiddlewareConfig,
|
|
39
40
|
getOAuth42Session: () => getOAuth42Session,
|
|
40
41
|
getServerSession: () => getServerSession,
|
|
41
42
|
refreshAccessToken: () => refreshAccessToken,
|
|
43
|
+
resolveBackendSession: () => resolveBackendSession,
|
|
44
|
+
revokeBackendSession: () => revokeBackendSession,
|
|
42
45
|
withOAuth42Auth: () => withOAuth42Auth,
|
|
43
46
|
withOAuth42ServerSideProps: () => withOAuth42ServerSideProps,
|
|
44
47
|
withOAuth42Session: () => withOAuth42Session
|
|
@@ -163,12 +166,72 @@ function withOAuth42ServerSideProps(getServerSideProps, authOptions) {
|
|
|
163
166
|
};
|
|
164
167
|
}
|
|
165
168
|
|
|
169
|
+
// src/server/backend-session.ts
|
|
170
|
+
function isBackendSessionMode(mode) {
|
|
171
|
+
return mode === "backend";
|
|
172
|
+
}
|
|
173
|
+
function sessionEndpoint(issuer) {
|
|
174
|
+
return `${issuer.replace(/\/$/, "")}/api/sdk/sessions`;
|
|
175
|
+
}
|
|
176
|
+
async function createBackendSession(params) {
|
|
177
|
+
const response = await fetch(sessionEndpoint(params.issuer), {
|
|
178
|
+
method: "POST",
|
|
179
|
+
headers: { "Content-Type": "application/json" },
|
|
180
|
+
body: JSON.stringify({
|
|
181
|
+
access_token: params.accessToken,
|
|
182
|
+
refresh_token: params.refreshToken,
|
|
183
|
+
expires_at: params.expiresAt ?? Math.floor(Date.now() / 1e3) + 3600,
|
|
184
|
+
id_token: params.idToken,
|
|
185
|
+
client_id: params.clientId,
|
|
186
|
+
client_secret: params.clientSecret,
|
|
187
|
+
issuer: params.issuer,
|
|
188
|
+
user: params.user
|
|
189
|
+
})
|
|
190
|
+
});
|
|
191
|
+
if (!response.ok) {
|
|
192
|
+
throw new Error(`OAuth42 backend session create failed: ${response.status}`);
|
|
193
|
+
}
|
|
194
|
+
return response.json();
|
|
195
|
+
}
|
|
196
|
+
async function resolveBackendSession(params) {
|
|
197
|
+
const response = await fetch(`${sessionEndpoint(params.issuer)}/resolve`, {
|
|
198
|
+
method: "POST",
|
|
199
|
+
headers: { "Content-Type": "application/json" },
|
|
200
|
+
body: JSON.stringify({
|
|
201
|
+
session_id: params.sessionId,
|
|
202
|
+
client_id: params.clientId,
|
|
203
|
+
client_secret: params.clientSecret,
|
|
204
|
+
issuer: params.issuer
|
|
205
|
+
})
|
|
206
|
+
});
|
|
207
|
+
if (response.status === 401 || response.status === 403 || response.status === 404) {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
if (!response.ok) {
|
|
211
|
+
throw new Error(`OAuth42 backend session resolve failed: ${response.status}`);
|
|
212
|
+
}
|
|
213
|
+
return response.json();
|
|
214
|
+
}
|
|
215
|
+
async function revokeBackendSession(params) {
|
|
216
|
+
await fetch(sessionEndpoint(params.issuer), {
|
|
217
|
+
method: "DELETE",
|
|
218
|
+
headers: { "Content-Type": "application/json" },
|
|
219
|
+
body: JSON.stringify({
|
|
220
|
+
session_id: params.sessionId,
|
|
221
|
+
client_id: params.clientId,
|
|
222
|
+
client_secret: params.clientSecret
|
|
223
|
+
})
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
166
227
|
// src/server/auth.ts
|
|
167
228
|
var NextAuth = import_next_auth2.default.default || import_next_auth2.default;
|
|
168
229
|
var activeRefresh = null;
|
|
169
230
|
function createAuth(options = {}) {
|
|
170
231
|
const clientId = options.clientId || process.env.OAUTH42_CLIENT_ID;
|
|
171
232
|
const clientSecret = options.clientSecret || process.env.OAUTH42_CLIENT_SECRET;
|
|
233
|
+
const issuer = options.issuer || process.env.NEXT_PUBLIC_OAUTH_ISSUER || process.env.OAUTH42_ISSUER || "https://localhost:8443";
|
|
234
|
+
const useBackendSessions = isBackendSessionMode(options.sessionStore);
|
|
172
235
|
if (!clientId || !clientSecret) {
|
|
173
236
|
throw new Error(
|
|
174
237
|
"OAuth42 client credentials are required. Set OAUTH42_CLIENT_ID and OAUTH42_CLIENT_SECRET environment variables or pass them in the options."
|
|
@@ -179,7 +242,7 @@ function createAuth(options = {}) {
|
|
|
179
242
|
OAuth42Provider({
|
|
180
243
|
clientId,
|
|
181
244
|
clientSecret,
|
|
182
|
-
issuer
|
|
245
|
+
issuer,
|
|
183
246
|
scopes: options.scopes,
|
|
184
247
|
pkceEnabled: options.pkceEnabled
|
|
185
248
|
})
|
|
@@ -188,14 +251,41 @@ function createAuth(options = {}) {
|
|
|
188
251
|
async jwt({ token, account, profile }) {
|
|
189
252
|
console.log("[OAuth42 SDK] JWT callback called", { hasAccount: !!account, hasProfile: !!profile });
|
|
190
253
|
if (account) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
254
|
+
if (useBackendSessions) {
|
|
255
|
+
if (!account.access_token || !account.refresh_token) {
|
|
256
|
+
throw new Error("OAuth42 backend sessions require access and refresh tokens");
|
|
257
|
+
}
|
|
258
|
+
const oauth42Profile = profile;
|
|
259
|
+
const backendSession = await createBackendSession({
|
|
260
|
+
issuer,
|
|
261
|
+
clientId,
|
|
262
|
+
clientSecret,
|
|
263
|
+
accessToken: account.access_token,
|
|
264
|
+
refreshToken: account.refresh_token,
|
|
265
|
+
expiresAt: account.expires_at,
|
|
266
|
+
idToken: account.id_token,
|
|
267
|
+
user: {
|
|
268
|
+
sub: oauth42Profile?.sub,
|
|
269
|
+
email: oauth42Profile?.email,
|
|
270
|
+
username: oauth42Profile?.username,
|
|
271
|
+
name: token.name,
|
|
272
|
+
emailVerified: oauth42Profile?.email_verified,
|
|
273
|
+
groups: oauth42Profile?.groups
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
token.oauth42SessionId = backendSession.session_id;
|
|
277
|
+
token.expiresAt = backendSession.expires_at;
|
|
278
|
+
token.issuer = issuer;
|
|
279
|
+
} else {
|
|
280
|
+
console.log("[OAuth42 SDK] Initial sign in - storing tokens in JWT");
|
|
281
|
+
token.accessToken = account.access_token;
|
|
282
|
+
token.refreshToken = account.refresh_token;
|
|
283
|
+
token.expiresAt = account.expires_at;
|
|
284
|
+
token.idToken = account.id_token;
|
|
285
|
+
token.clientId = clientId;
|
|
286
|
+
token.clientSecret = clientSecret;
|
|
287
|
+
token.issuer = issuer;
|
|
288
|
+
}
|
|
199
289
|
}
|
|
200
290
|
if (profile) {
|
|
201
291
|
const oauth42Profile = profile;
|
|
@@ -212,12 +302,40 @@ function createAuth(options = {}) {
|
|
|
212
302
|
},
|
|
213
303
|
async session({ session, token }) {
|
|
214
304
|
console.log("[OAuth42 SDK] Session callback called", { hasToken: !!token, hasSession: !!session });
|
|
215
|
-
|
|
216
|
-
|
|
305
|
+
if (useBackendSessions) {
|
|
306
|
+
const sessionId = token.oauth42SessionId;
|
|
307
|
+
if (!sessionId) {
|
|
308
|
+
session.error = "SessionRevoked";
|
|
309
|
+
return session;
|
|
310
|
+
}
|
|
311
|
+
const backendSession = await resolveBackendSession({
|
|
312
|
+
issuer,
|
|
313
|
+
clientId,
|
|
314
|
+
clientSecret,
|
|
315
|
+
sessionId
|
|
316
|
+
});
|
|
317
|
+
if (!backendSession) {
|
|
318
|
+
session.error = "SessionRevoked";
|
|
319
|
+
return session;
|
|
320
|
+
}
|
|
321
|
+
session.accessToken = backendSession.access_token;
|
|
322
|
+
session.idToken = backendSession.id_token;
|
|
323
|
+
token.expiresAt = backendSession.expires_at;
|
|
324
|
+
if (backendSession.user && session.user) {
|
|
325
|
+
session.user.email = backendSession.user.email;
|
|
326
|
+
session.user.name = backendSession.user.name;
|
|
327
|
+
session.user.username = backendSession.user.username;
|
|
328
|
+
session.user.emailVerified = backendSession.user.emailVerified;
|
|
329
|
+
session.user.groups = backendSession.user.groups;
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
session.accessToken = token.accessToken;
|
|
333
|
+
session.idToken = token.idToken;
|
|
334
|
+
}
|
|
217
335
|
if (token.error) {
|
|
218
336
|
session.error = token.error;
|
|
219
337
|
}
|
|
220
|
-
if (session.user) {
|
|
338
|
+
if (!useBackendSessions && session.user) {
|
|
221
339
|
session.user.email = token.email;
|
|
222
340
|
session.user.name = token.name;
|
|
223
341
|
session.user.username = token.username;
|
|
@@ -241,6 +359,26 @@ function createAuth(options = {}) {
|
|
|
241
359
|
strategy: "jwt",
|
|
242
360
|
...options.session
|
|
243
361
|
},
|
|
362
|
+
events: {
|
|
363
|
+
async signOut(message) {
|
|
364
|
+
if (useBackendSessions) {
|
|
365
|
+
const sessionId = message.token?.oauth42SessionId;
|
|
366
|
+
if (sessionId) {
|
|
367
|
+
await revokeBackendSession({
|
|
368
|
+
issuer,
|
|
369
|
+
clientId,
|
|
370
|
+
clientSecret,
|
|
371
|
+
sessionId
|
|
372
|
+
}).catch((error) => {
|
|
373
|
+
console.warn("[OAuth42 SDK] Failed to revoke backend session on signOut:", error);
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (options.events?.signOut) {
|
|
378
|
+
await options.events.signOut(message);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
},
|
|
244
382
|
debug: options.debug || process.env.NODE_ENV === "development",
|
|
245
383
|
secret: process.env.NEXTAUTH_SECRET,
|
|
246
384
|
// Configure unique cookie names per app to prevent session conflicts on localhost
|
|
@@ -273,7 +411,11 @@ function createAuth(options = {}) {
|
|
|
273
411
|
secure: process.env.NODE_ENV === "production"
|
|
274
412
|
}
|
|
275
413
|
},
|
|
276
|
-
// PKCE code_verifier cookie - essential for PKCE flow
|
|
414
|
+
// PKCE code_verifier cookie - essential for PKCE flow.
|
|
415
|
+
// TTL covers the full OAuth round-trip including user-in-the-loop steps
|
|
416
|
+
// like passkey ceremonies, MFA enrollment, and any debugging pauses.
|
|
417
|
+
// The previous 15-minute value was too tight for realistic ceremony-
|
|
418
|
+
// heavy flows — see #524 for the incident where state expired mid-debug.
|
|
277
419
|
pkceCodeVerifier: {
|
|
278
420
|
name: `${options.cookiePrefix}.pkce.code_verifier`,
|
|
279
421
|
options: {
|
|
@@ -281,11 +423,13 @@ function createAuth(options = {}) {
|
|
|
281
423
|
sameSite: "lax",
|
|
282
424
|
path: "/",
|
|
283
425
|
secure: process.env.NODE_ENV === "production",
|
|
284
|
-
maxAge:
|
|
285
|
-
// 15
|
|
426
|
+
maxAge: 3600
|
|
427
|
+
// 1 hour (was 900 — 15 min was too short for passkey/MFA flows)
|
|
286
428
|
}
|
|
287
429
|
},
|
|
288
|
-
// State cookie for OAuth CSRF protection
|
|
430
|
+
// State cookie for OAuth CSRF protection. Same TTL rationale as
|
|
431
|
+
// pkceCodeVerifier above. State is single-use CSRF and cannot be
|
|
432
|
+
// replayed, so a longer TTL does not weaken the security story.
|
|
289
433
|
state: {
|
|
290
434
|
name: `${options.cookiePrefix}.state`,
|
|
291
435
|
options: {
|
|
@@ -293,8 +437,8 @@ function createAuth(options = {}) {
|
|
|
293
437
|
sameSite: "lax",
|
|
294
438
|
path: "/",
|
|
295
439
|
secure: process.env.NODE_ENV === "production",
|
|
296
|
-
maxAge:
|
|
297
|
-
// 15
|
|
440
|
+
maxAge: 3600
|
|
441
|
+
// 1 hour (was 900 — 15 min was too short for passkey/MFA flows)
|
|
298
442
|
}
|
|
299
443
|
},
|
|
300
444
|
// Nonce cookie for OpenID Connect
|
|
@@ -388,7 +532,22 @@ var import_jwt = require("next-auth/jwt");
|
|
|
388
532
|
var ALLOWED_COOKIE_SIZE = 4096;
|
|
389
533
|
var ESTIMATED_EMPTY_COOKIE_SIZE = 163;
|
|
390
534
|
var CHUNK_SIZE = ALLOWED_COOKIE_SIZE - ESTIMATED_EMPTY_COOKIE_SIZE;
|
|
535
|
+
var REFRESH_RACE_GRACE_SECONDS = 60;
|
|
536
|
+
var DEFAULT_SESSION_MAX_AGE_SECONDS = 365 * 24 * 60 * 60;
|
|
391
537
|
var pendingRefreshes = /* @__PURE__ */ new Map();
|
|
538
|
+
function shouldPreserveSessionOnRefreshFailure(params) {
|
|
539
|
+
if (params.error !== "invalid_grant" || !params.expiresAt) {
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
return params.now - params.expiresAt <= REFRESH_RACE_GRACE_SECONDS;
|
|
543
|
+
}
|
|
544
|
+
function resolveRefreshConfig(options, token) {
|
|
545
|
+
return {
|
|
546
|
+
clientId: options.clientId || token.clientId || process.env.OAUTH42_CLIENT_ID,
|
|
547
|
+
clientSecret: options.clientSecret || token.clientSecret || process.env.OAUTH42_CLIENT_SECRET,
|
|
548
|
+
issuer: options.issuer || token.issuer || process.env.OAUTH42_ISSUER || "https://localhost:8443"
|
|
549
|
+
};
|
|
550
|
+
}
|
|
392
551
|
async function refreshTokens(refreshToken, clientId, clientSecret, issuer) {
|
|
393
552
|
try {
|
|
394
553
|
const tokenUrl = `${issuer}/oauth2/token`;
|
|
@@ -423,9 +582,6 @@ async function refreshTokens(refreshToken, clientId, clientSecret, issuer) {
|
|
|
423
582
|
}
|
|
424
583
|
function withOAuth42Auth(options = {}) {
|
|
425
584
|
const secret = process.env.NEXTAUTH_SECRET;
|
|
426
|
-
const clientId = process.env.OAUTH42_CLIENT_ID;
|
|
427
|
-
const clientSecret = process.env.OAUTH42_CLIENT_SECRET;
|
|
428
|
-
const issuer = process.env.OAUTH42_ISSUER || "https://localhost:8443";
|
|
429
585
|
if (!secret) {
|
|
430
586
|
console.warn("[OAuth42 Middleware] NEXTAUTH_SECRET not set");
|
|
431
587
|
}
|
|
@@ -450,6 +606,42 @@ function withOAuth42Auth(options = {}) {
|
|
|
450
606
|
url.searchParams.set("callbackUrl", pathname);
|
|
451
607
|
return import_server.NextResponse.redirect(url);
|
|
452
608
|
}
|
|
609
|
+
const refreshConfig = resolveRefreshConfig(options, token);
|
|
610
|
+
if (isBackendSessionMode(options.sessionStore)) {
|
|
611
|
+
const sessionId = token.oauth42SessionId;
|
|
612
|
+
if (!sessionId || !refreshConfig.clientId || !refreshConfig.clientSecret) {
|
|
613
|
+
const signInUrl = options.pages?.signIn || "/auth/signin";
|
|
614
|
+
const url = new URL(signInUrl, req.url);
|
|
615
|
+
url.searchParams.set("callbackUrl", pathname);
|
|
616
|
+
const response = import_server.NextResponse.redirect(url);
|
|
617
|
+
response.cookies.delete(cookieName);
|
|
618
|
+
return response;
|
|
619
|
+
}
|
|
620
|
+
const backendSession = await resolveBackendSession({
|
|
621
|
+
issuer: refreshConfig.issuer,
|
|
622
|
+
clientId: refreshConfig.clientId,
|
|
623
|
+
clientSecret: refreshConfig.clientSecret,
|
|
624
|
+
sessionId
|
|
625
|
+
}).catch((error) => {
|
|
626
|
+
console.error("[OAuth42 Middleware] Backend session resolve failed:", error);
|
|
627
|
+
return null;
|
|
628
|
+
});
|
|
629
|
+
if (!backendSession) {
|
|
630
|
+
const signInUrl = options.pages?.signIn || "/auth/signin";
|
|
631
|
+
const url = new URL(signInUrl, req.url);
|
|
632
|
+
url.searchParams.set("callbackUrl", pathname);
|
|
633
|
+
const response = import_server.NextResponse.redirect(url);
|
|
634
|
+
response.cookies.delete(cookieName);
|
|
635
|
+
return response;
|
|
636
|
+
}
|
|
637
|
+
const requestHeaders = new Headers(req.headers);
|
|
638
|
+
requestHeaders.set("x-oauth42-refreshed-token", backendSession.access_token);
|
|
639
|
+
return import_server.NextResponse.next({
|
|
640
|
+
request: {
|
|
641
|
+
headers: requestHeaders
|
|
642
|
+
}
|
|
643
|
+
});
|
|
644
|
+
}
|
|
453
645
|
const expiresAt = token.expiresAt;
|
|
454
646
|
const now = Math.floor(Date.now() / 1e3);
|
|
455
647
|
const bufferSeconds = 15;
|
|
@@ -463,7 +655,7 @@ function withOAuth42Auth(options = {}) {
|
|
|
463
655
|
path: pathname
|
|
464
656
|
});
|
|
465
657
|
}
|
|
466
|
-
if (needsRefresh && token.refreshToken && clientId && clientSecret) {
|
|
658
|
+
if (needsRefresh && token.refreshToken && refreshConfig.clientId && refreshConfig.clientSecret) {
|
|
467
659
|
const userId = token.sub;
|
|
468
660
|
let refreshPromise = pendingRefreshes.get(userId);
|
|
469
661
|
if (refreshPromise) {
|
|
@@ -472,11 +664,14 @@ function withOAuth42Auth(options = {}) {
|
|
|
472
664
|
console.log("[OAuth42 Middleware] Access token expired, refreshing...");
|
|
473
665
|
refreshPromise = refreshTokens(
|
|
474
666
|
token.refreshToken,
|
|
475
|
-
clientId,
|
|
476
|
-
clientSecret,
|
|
477
|
-
issuer
|
|
667
|
+
refreshConfig.clientId,
|
|
668
|
+
refreshConfig.clientSecret,
|
|
669
|
+
refreshConfig.issuer
|
|
478
670
|
).finally(() => {
|
|
479
|
-
setTimeout(() => pendingRefreshes.delete(userId), 3e4);
|
|
671
|
+
const cleanupTimer = setTimeout(() => pendingRefreshes.delete(userId), 3e4);
|
|
672
|
+
if (typeof cleanupTimer === "object" && "unref" in cleanupTimer) {
|
|
673
|
+
cleanupTimer.unref();
|
|
674
|
+
}
|
|
480
675
|
});
|
|
481
676
|
pendingRefreshes.set(userId, refreshPromise);
|
|
482
677
|
}
|
|
@@ -503,7 +698,8 @@ function withOAuth42Auth(options = {}) {
|
|
|
503
698
|
httpOnly: true,
|
|
504
699
|
sameSite: "lax",
|
|
505
700
|
path: "/",
|
|
506
|
-
secure: process.env.NODE_ENV === "production"
|
|
701
|
+
secure: process.env.NODE_ENV === "production",
|
|
702
|
+
maxAge: options.session?.maxAge ?? DEFAULT_SESSION_MAX_AGE_SECONDS
|
|
507
703
|
};
|
|
508
704
|
if (newJwt.length <= CHUNK_SIZE) {
|
|
509
705
|
response.cookies.set(cookieName, newJwt, cookieOptions);
|
|
@@ -551,7 +747,23 @@ function withOAuth42Auth(options = {}) {
|
|
|
551
747
|
});
|
|
552
748
|
return response;
|
|
553
749
|
} else {
|
|
554
|
-
|
|
750
|
+
if (shouldPreserveSessionOnRefreshFailure({
|
|
751
|
+
error: refreshed.error,
|
|
752
|
+
expiresAt,
|
|
753
|
+
now
|
|
754
|
+
})) {
|
|
755
|
+
console.warn(
|
|
756
|
+
"[OAuth42 Middleware] Refresh failed with invalid_grant for a recently expired token; preserving session cookie for likely parallel refresh race",
|
|
757
|
+
{
|
|
758
|
+
expiresAt,
|
|
759
|
+
now,
|
|
760
|
+
expiredAgo: now - expiresAt,
|
|
761
|
+
path: pathname
|
|
762
|
+
}
|
|
763
|
+
);
|
|
764
|
+
return import_server.NextResponse.next();
|
|
765
|
+
}
|
|
766
|
+
console.log("[OAuth42 Middleware] Refresh failed, clearing session");
|
|
555
767
|
const signInUrl = options.pages?.signIn || "/auth/signin";
|
|
556
768
|
const url = new URL(signInUrl, req.url);
|
|
557
769
|
url.searchParams.set("callbackUrl", pathname);
|
|
@@ -698,12 +910,15 @@ function createHostedAuthCallback(options = {}) {
|
|
|
698
910
|
NextAuth,
|
|
699
911
|
OAuth42Provider,
|
|
700
912
|
createAuth,
|
|
913
|
+
createBackendSession,
|
|
701
914
|
createHandlers,
|
|
702
915
|
createHostedAuthCallback,
|
|
703
916
|
createMiddlewareConfig,
|
|
704
917
|
getOAuth42Session,
|
|
705
918
|
getServerSession,
|
|
706
919
|
refreshAccessToken,
|
|
920
|
+
resolveBackendSession,
|
|
921
|
+
revokeBackendSession,
|
|
707
922
|
withOAuth42Auth,
|
|
708
923
|
withOAuth42ServerSideProps,
|
|
709
924
|
withOAuth42Session
|