cloudflare-next-intl 0.6.19 → 0.6.21

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.
@@ -9,6 +9,7 @@ import { getFirebaseAuthClient, getFirebaseAuthModule } from './firebase_client'
9
9
  import { setAuthUserCache } from './auth_user_cache';
10
10
  import { defaultEmailVerifiedHintCookieName, defaultRefreshTokenCookieName, defaultSessionCookieName } from '../middleware/update_session';
11
11
  import decodeJwtPayload from '../decode_jwt_payload';
12
+ import isWhitelisted from '../is_whitelisted';
12
13
  import setCookie from '../../client/functions/set_cookie';
13
14
  import getCookie from '../../client/functions/get_cookie';
14
15
  import clearSessionAction from '../server/clear_session_action';
@@ -87,7 +88,7 @@ export default function AuthUserProvider({ initialUser = null, children }) {
87
88
  const router = useRouter();
88
89
  const pathname = usePathname();
89
90
  const isAuthPage = fa.isAuthPath(pathname);
90
- const isWhiteListed = fa.whiteListPaths?.includes(pathname) ?? false;
91
+ const isWhiteListed = isWhitelisted(pathname, fa.whiteListPaths);
91
92
  const maxAge = fa.sessionCookieMaxAge ?? 60 * 60 * 24 * 5;
92
93
  const sessionCookieName = fa.sessionCookieName ?? defaultSessionCookieName;
93
94
  const refreshTokenMaxAge = fa.refreshTokenCookieMaxAge ?? 60 * 60 * 24 * 365;
@@ -1,6 +1,19 @@
1
1
  'use client';
2
2
  import config from '@intl-config';
3
3
  import requireFirebaseAuthConfig from '../require_config';
4
+ async function initializeFirebaseAppCheck(app, appCheckConfig) {
5
+ const { initializeAppCheck, ReCaptchaV3Provider, ReCaptchaEnterpriseProvider } = await import('firebase/app-check');
6
+ if (appCheckConfig.debugToken) {
7
+ globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
8
+ }
9
+ const provider = appCheckConfig.recaptchaEnterpriseSiteKey
10
+ ? new ReCaptchaEnterpriseProvider(appCheckConfig.recaptchaEnterpriseSiteKey)
11
+ : new ReCaptchaV3Provider(appCheckConfig.recaptchaV3SiteKey);
12
+ initializeAppCheck(app, {
13
+ provider,
14
+ isTokenAutoRefreshEnabled: appCheckConfig.isTokenAutoRefreshEnabled ?? true,
15
+ });
16
+ }
4
17
  let cached;
5
18
  let cachedPromise;
6
19
  /**
@@ -16,7 +29,7 @@ export async function getFirebaseAuthClient() {
16
29
  return cached;
17
30
  if (!cachedPromise) {
18
31
  const fa = config.firebaseAuth;
19
- cachedPromise = Promise.all([import('firebase/app'), import('firebase/auth')]).then(([{ getApp, getApps, initializeApp }, { getAuth }]) => {
32
+ cachedPromise = Promise.all([import('firebase/app'), import('firebase/auth')]).then(async ([{ getApp, getApps, initializeApp }, { getAuth }]) => {
20
33
  const firebaseConfig = {
21
34
  apiKey: fa.apiKey,
22
35
  authDomain: fa.authDomain,
@@ -27,6 +40,9 @@ export async function getFirebaseAuthClient() {
27
40
  measurementId: fa.measurementId,
28
41
  };
29
42
  const app = getApps().length ? getApp() : initializeApp(firebaseConfig);
43
+ if (fa.appCheck) {
44
+ await initializeFirebaseAppCheck(app, fa.appCheck);
45
+ }
30
46
  const auth = getAuth(app);
31
47
  cached = { app, auth };
32
48
  return cached;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Whether `path` is exempt from auth redirects under `whiteListPaths`.
3
+ * Matches an entry exactly, OR as a path-segment prefix (`/bonds` also
4
+ * covers `/bonds/some-slug`, but NOT `/bonds-extra`) — a plain
5
+ * `startsWith` would let a differently-named sibling route slip through
6
+ * whenever one route's name happens to prefix another's.
7
+ */
8
+ export default function isWhitelisted(path: string, whiteListPaths: readonly string[] | undefined): boolean;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Whether `path` is exempt from auth redirects under `whiteListPaths`.
3
+ * Matches an entry exactly, OR as a path-segment prefix (`/bonds` also
4
+ * covers `/bonds/some-slug`, but NOT `/bonds-extra`) — a plain
5
+ * `startsWith` would let a differently-named sibling route slip through
6
+ * whenever one route's name happens to prefix another's.
7
+ */
8
+ export default function isWhitelisted(path, whiteListPaths) {
9
+ if (!whiteListPaths)
10
+ return false;
11
+ return whiteListPaths.some((entry) => path === entry || path.startsWith(`${entry}/`));
12
+ }
@@ -1,6 +1,7 @@
1
1
  import { NextResponse } from 'next/server';
2
2
  import config from '@intl-config';
3
3
  import decodeJwtPayload from '../decode_jwt_payload';
4
+ import isWhitelisted from '../is_whitelisted';
4
5
  export const defaultSessionCookieName = '__fa_session__';
5
6
  export const defaultRefreshTokenCookieName = '__fa_refresh_token__';
6
7
  // Non-httpOnly: written by AuthUserProvider (client) every time it observes
@@ -219,7 +220,7 @@ export default async function updateSession(request, baseResponse, locale) {
219
220
  }
220
221
  }
221
222
  }
222
- const isWhiteListed = fa.whiteListPaths?.includes(path) ?? false;
223
+ const isWhiteListed = isWhitelisted(path, fa.whiteListPaths);
223
224
  if (isWhiteListed)
224
225
  return baseResponse;
225
226
  const isAuthPage = fa.isAuthPath(path);
@@ -440,6 +440,13 @@ export interface FirebaseAuthRoutingConfig {
440
440
  appId: string;
441
441
  /** Firebase Analytics measurement ID. */
442
442
  measurementId?: string;
443
+ /**
444
+ * Enables Firebase App Check on the client. Omit to leave App Check
445
+ * uninitialized — required if App Check enforcement is turned on for
446
+ * Auth/Firestore/etc. in the Firebase console, or every request gets
447
+ * rejected with 401.
448
+ */
449
+ appCheck?: FirebaseAppCheckConfig;
443
450
  /** Path to redirect signed-out users to, e.g. "/login". Must start with "/" — `setIntlConfig` auto-corrects a missing leading slash with a warning. */
444
451
  redirectAuthPath: string;
445
452
  /** Path to redirect signed-in users away from auth pages to, e.g. "/". Must start with "/" — `setIntlConfig` auto-corrects a missing leading slash with a warning. */
@@ -531,6 +538,21 @@ export interface FirebaseAuthRoutingConfig {
531
538
  */
532
539
  onSignOut?: () => void | Promise<void>;
533
540
  }
541
+ export interface FirebaseAppCheckConfig {
542
+ /** reCAPTCHA v3 site key. Mutually exclusive with `recaptchaEnterpriseSiteKey`. */
543
+ recaptchaV3SiteKey?: string;
544
+ /** reCAPTCHA Enterprise site key. Mutually exclusive with `recaptchaV3SiteKey`. */
545
+ recaptchaEnterpriseSiteKey?: string;
546
+ /**
547
+ * Enables App Check's debug token on this client (sets
548
+ * `self.FIREBASE_APPCHECK_DEBUG_TOKEN = true` before init, which logs a
549
+ * token to the console to register in the Firebase console). Use only
550
+ * for local development — never set `true` in production.
551
+ */
552
+ debugToken?: boolean;
553
+ /** Forwarded to `initializeAppCheck`'s `isTokenAutoRefreshEnabled`. Defaults to `true`. */
554
+ isTokenAutoRefreshEnabled?: boolean;
555
+ }
534
556
  export interface CookieAttributes {
535
557
  /**
536
558
  * Specifies the value for the {@link https://tools.ietf.org/html/rfc6265#section-5.2.3|Domain Set-Cookie attribute}. By default, no
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.6.19",
3
+ "version": "0.6.21",
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",