cloudflare-next-intl 0.6.11 → 0.6.13

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.
@@ -110,15 +110,32 @@ export default function AuthUserProvider({ initialUser = null, children }) {
110
110
  const [confirmedSignedOut, setConfirmedSignedOut] = useState(initialUser === null);
111
111
  useEffect(() => {
112
112
  const { user, loading } = state;
113
- if (loading || isAuthPage || isWhiteListed)
113
+ if (loading || isWhiteListed)
114
114
  return;
115
115
  if (!user) {
116
- if (confirmedSignedOut)
116
+ // Signed-out on an auth page is where they're supposed to be —
117
+ // only bounce a signed-out user away from a NON-auth page.
118
+ if (!isAuthPage && confirmedSignedOut)
117
119
  router.replace(fa.redirectAuthPath);
118
120
  }
119
121
  else if (fa.verifyEmailPath && !user.emailVerified && pathname !== fa.verifyEmailPath) {
122
+ // Checked before the auth-page redirect below (mirrors
123
+ // `update_session.ts`'s same ordering): an unverified signed-in
124
+ // user must land on verifyEmailPath even if they navigated to
125
+ // an auth page like /login — homePath isn't reachable yet either.
120
126
  router.replace(fa.verifyEmailPath);
121
127
  }
128
+ else if (isAuthPage || (fa.verifyEmailPath && user.emailVerified && pathname === fa.verifyEmailPath)) {
129
+ // Mirrors the middleware's own signed-in-on-auth-page redirect
130
+ // (`update_session.ts`'s `isAuthPage` branch) — needed here too
131
+ // because a client-side navigation (e.g. a `<Link>`) to an auth
132
+ // page never re-runs the middleware, so without this the user
133
+ // would land on e.g. `/login` while already signed in and stay
134
+ // there until a hard refresh. A verified user reaching
135
+ // verifyEmailPath itself gets the same "go home" treatment —
136
+ // they're done here, same as the auth-page case.
137
+ router.replace(fa.homePath);
138
+ }
122
139
  // eslint-disable-next-line react-hooks/exhaustive-deps
123
140
  }, [state, pathname, isAuthPage, isWhiteListed, confirmedSignedOut]);
124
141
  useEffect(() => {
@@ -270,12 +270,30 @@ export default async function updateSession(request, baseResponse, locale) {
270
270
  else if (!hasSession || clearInvalidSession) {
271
271
  response = isAuthPage ? baseResponse : buildRedirect(baseResponse, localeUrl(fa.redirectAuthPath));
272
272
  }
273
- else if (isAuthPage) {
274
- response = buildRedirect(baseResponse, localeUrl(fa.homePath));
275
- }
276
273
  else if (unverifiedEmail) {
274
+ // Checked before the auth-page redirect: an unverified signed-in
275
+ // user must land on verifyEmailPath even if they navigated to an
276
+ // auth page like /login — homePath is not a state they're allowed
277
+ // to reach yet either.
277
278
  response = buildRedirect(baseResponse, localeUrl(fa.verifyEmailPath));
278
279
  }
280
+ else if (isAuthPage || (isVerifyEmailPage && decodeJwtPayload(token)?.email_verified === true)) {
281
+ // A verified user has no reason to be on verifyEmailPath either —
282
+ // same "you're done here, go home" treatment as an auth page.
283
+ // `unverifiedEmail` can't be reused here: its own computation
284
+ // deliberately skips verifyEmailPath (so it never redirects AWAY
285
+ // from that page for an unverified user), so it's always `false`
286
+ // while already on it regardless of actual verification status —
287
+ // checking the claim again directly is what tells verified and
288
+ // unverified apart on this specific page. Requires an EXPLICIT
289
+ // `true` (not just "not false") — a missing/undefined claim must
290
+ // NOT redirect home here, since `AuthUserProvider`'s client-side
291
+ // effect treats that same user as unverified via the live SDK's
292
+ // boolean `user.emailVerified`. The two disagreeing caused an
293
+ // infinite client<->server redirect loop on this exact page when a
294
+ // token's claim was merely absent rather than `false`.
295
+ response = buildRedirect(baseResponse, localeUrl(fa.homePath));
296
+ }
279
297
  else {
280
298
  response = baseResponse;
281
299
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.6.11",
3
+ "version": "0.6.13",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",