cloudflare-next-intl 0.8.27 → 0.8.29
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.
|
@@ -369,23 +369,35 @@ export default async function updateSession(request, baseResponse, locale, rebui
|
|
|
369
369
|
}
|
|
370
370
|
let unverifiedEmail = false;
|
|
371
371
|
if (fa.verifyEmailPath && !isVerifyEmailPage && hasSession && decodeJwtPayload(token)?.email_verified === false) {
|
|
372
|
+
// Sending a user to `verifyEmailPath` is only safe when this claim
|
|
373
|
+
// reflects the LIVE account state, because that page resolves the
|
|
374
|
+
// same user through `getAuthUser()`/`initializeServerApp` — which
|
|
375
|
+
// reads the Auth service directly, not this frozen claim — and
|
|
376
|
+
// redirects home the moment it sees a verified user. Any disagreement
|
|
377
|
+
// between the two is therefore not a stale-data annoyance but an
|
|
378
|
+
// infinite redirect loop.
|
|
379
|
+
//
|
|
380
|
+
// The hint cookie cannot settle that: it is a client-written mirror,
|
|
381
|
+
// and after the user verifies in another tab (or the client simply
|
|
382
|
+
// never re-runs) it keeps asserting a `false` that is now wrong,
|
|
383
|
+
// while the Auth service already reports verified. Trusting a
|
|
384
|
+
// `'false'` hint as confirmation is exactly what pinned verified
|
|
385
|
+
// users in the loop. So the hint is only ever allowed to SKIP work
|
|
386
|
+
// when it agrees the user is verified — never to prove they aren't.
|
|
372
387
|
const hint = request.cookies.get(emailVerifiedHintCookieName)?.value;
|
|
373
|
-
|
|
374
|
-
if (!hintConfirms && !refreshedToken) {
|
|
388
|
+
if (!refreshedToken) {
|
|
375
389
|
const refreshToken = request.cookies.get(refreshTokenCookieName)?.value;
|
|
376
390
|
if (refreshToken) {
|
|
377
|
-
|
|
391
|
+
// `skipCache`: the cached entry is what produced the very
|
|
392
|
+
// token whose claim is in question, so a cached refresh can
|
|
393
|
+
// hand back that same token and confirm nothing.
|
|
394
|
+
const result = await refreshIdToken(fa.apiKey, refreshToken, { skipCache: true });
|
|
378
395
|
if (result.status === 'refreshed') {
|
|
379
396
|
refreshedToken = { idToken: result.idToken, refreshToken: result.refreshToken };
|
|
380
397
|
token = refreshedToken.idToken;
|
|
381
|
-
//
|
|
382
|
-
// verification live
|
|
383
|
-
//
|
|
384
|
-
// backend can lag behind the account-info read `reload()`
|
|
385
|
-
// used to set the hint. Trusting the stale claim here
|
|
386
|
-
// would redirect to verifyEmailPath, which independently
|
|
387
|
-
// resolves the user as verified via `getAuthUser()` and
|
|
388
|
-
// redirects home — an infinite loop. Hint `true` wins.
|
|
398
|
+
// A `true` hint means the client already observed
|
|
399
|
+
// verification live; never redirect against it, even if
|
|
400
|
+
// this mint's claim hasn't caught up.
|
|
389
401
|
unverifiedEmail = hint !== 'true' && decodeJwtPayload(token)?.email_verified === false;
|
|
390
402
|
}
|
|
391
403
|
else if (result.status === 'invalid') {
|
|
@@ -404,8 +416,7 @@ export default async function updateSession(request, baseResponse, locale, rebui
|
|
|
404
416
|
}
|
|
405
417
|
}
|
|
406
418
|
else {
|
|
407
|
-
|
|
408
|
-
unverifiedEmail = true;
|
|
419
|
+
unverifiedEmail = hint !== 'true' && decodeJwtPayload(token)?.email_verified === false;
|
|
409
420
|
}
|
|
410
421
|
}
|
|
411
422
|
if (refreshWasTransientFailure) {
|