@tern-secure/nextjs 5.1.7 → 5.1.9
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/dist/cjs/__tests__/gemini_fnTernSecureNextHandler.bench.js +31 -0
- package/dist/cjs/__tests__/gemini_fnTernSecureNextHandler.bench.js.map +1 -0
- package/dist/cjs/app-router/admin/actions.js +62 -0
- package/dist/cjs/app-router/admin/actions.js.map +1 -0
- package/dist/cjs/app-router/admin/constants.js +29 -0
- package/dist/cjs/app-router/admin/constants.js.map +1 -0
- package/dist/cjs/app-router/admin/fnValidators.js +295 -0
- package/dist/cjs/app-router/admin/fnValidators.js.map +1 -0
- package/dist/cjs/app-router/admin/index.js +16 -3
- package/dist/cjs/app-router/admin/index.js.map +1 -1
- package/dist/cjs/app-router/admin/responses.js +120 -0
- package/dist/cjs/app-router/admin/responses.js.map +1 -0
- package/dist/cjs/app-router/admin/sessionHandlers.js +167 -0
- package/dist/cjs/app-router/admin/sessionHandlers.js.map +1 -0
- package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js +84 -0
- package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js.map +1 -0
- package/dist/cjs/app-router/admin/types.js +127 -0
- package/dist/cjs/app-router/admin/types.js.map +1 -0
- package/dist/cjs/app-router/admin/utils.js +107 -0
- package/dist/cjs/app-router/admin/utils.js.map +1 -0
- package/dist/cjs/app-router/admin/validators.js +217 -0
- package/dist/cjs/app-router/admin/validators.js.map +1 -0
- package/dist/cjs/app-router/client/TernSecureProvider.js +2 -6
- package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -1
- package/dist/cjs/app-router/server/auth.js +100 -0
- package/dist/cjs/app-router/server/auth.js.map +1 -0
- package/dist/cjs/app-router/server/utils.js +87 -0
- package/dist/cjs/app-router/server/utils.js.map +1 -0
- package/dist/cjs/boundary/components.js +4 -7
- package/dist/cjs/boundary/components.js.map +1 -1
- package/dist/cjs/{components/uiComponents.js → constants.js} +17 -18
- package/dist/cjs/constants.js.map +1 -0
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/index.js +4 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/constant.js +38 -0
- package/dist/cjs/server/constant.js.map +1 -0
- package/dist/cjs/server/edge-session.js +118 -24
- package/dist/cjs/server/edge-session.js.map +1 -1
- package/dist/cjs/server/headers-utils.js +70 -0
- package/dist/cjs/server/headers-utils.js.map +1 -0
- package/dist/cjs/server/index.js +8 -6
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/server/jwt-edge.js +47 -19
- package/dist/cjs/server/jwt-edge.js.map +1 -1
- package/dist/cjs/server/jwt.js +11 -4
- package/dist/cjs/server/jwt.js.map +1 -1
- package/dist/cjs/server/nextErrors.js +131 -0
- package/dist/cjs/server/nextErrors.js.map +1 -0
- package/dist/cjs/server/nextFetcher.js +31 -0
- package/dist/cjs/server/nextFetcher.js.map +1 -0
- package/dist/cjs/server/node/SessionTernSecure.js +55 -0
- package/dist/cjs/server/node/SessionTernSecure.js.map +1 -0
- package/dist/cjs/server/{auth.js → node/auth.js} +11 -20
- package/dist/cjs/server/node/auth.js.map +1 -0
- package/dist/cjs/server/node/index.js +40 -0
- package/dist/cjs/server/node/index.js.map +1 -0
- package/dist/cjs/server/node/node-session.js +60 -0
- package/dist/cjs/server/node/node-session.js.map +1 -0
- package/dist/cjs/server/node/ternSecureNodeMiddleware.js +182 -0
- package/dist/cjs/server/node/ternSecureNodeMiddleware.js.map +1 -0
- package/dist/cjs/server/protect.js +90 -0
- package/dist/cjs/server/protect.js.map +1 -0
- package/dist/cjs/server/redirect.js +84 -0
- package/dist/cjs/server/redirect.js.map +1 -0
- package/dist/cjs/server/routeMatcher.js +36 -0
- package/dist/cjs/server/routeMatcher.js.map +1 -0
- package/dist/cjs/server/sdk-versions.js +43 -0
- package/dist/cjs/server/sdk-versions.js.map +1 -0
- package/dist/cjs/server/session-store.js.map +1 -1
- package/dist/cjs/server/ternSecureEdgeMiddleware.js +298 -0
- package/dist/cjs/server/ternSecureEdgeMiddleware.js.map +1 -0
- package/dist/cjs/server/ternSecureFireMiddleware.js +192 -0
- package/dist/cjs/server/ternSecureFireMiddleware.js.map +1 -0
- package/dist/cjs/server/types.js.map +1 -1
- package/dist/cjs/server/utils.js +115 -2
- package/dist/cjs/server/utils.js.map +1 -1
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/NextCookieAdapter.js +44 -0
- package/dist/cjs/utils/NextCookieAdapter.js.map +1 -0
- package/dist/cjs/utils/allNextProviderProps.js +10 -24
- package/dist/cjs/utils/allNextProviderProps.js.map +1 -1
- package/dist/cjs/utils/config.js +38 -2
- package/dist/cjs/utils/config.js.map +1 -1
- package/dist/cjs/utils/construct.js.map +1 -1
- package/dist/cjs/utils/fireconfig.js +38 -0
- package/dist/cjs/utils/fireconfig.js.map +1 -0
- package/dist/cjs/utils/logger.js +101 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/cjs/utils/redis.js +33 -0
- package/dist/cjs/utils/redis.js.map +1 -0
- package/dist/cjs/utils/response.js +38 -0
- package/dist/cjs/utils/response.js.map +1 -0
- package/dist/cjs/utils/serverRedirectAuth.js +39 -0
- package/dist/cjs/utils/serverRedirectAuth.js.map +1 -0
- package/dist/cjs/utils/ternsecure-sw.js +1 -1
- package/dist/cjs/utils/ternsecure-sw.js.map +1 -1
- package/dist/cjs/utils/withLogger.js +82 -0
- package/dist/cjs/utils/withLogger.js.map +1 -0
- package/dist/esm/__tests__/gemini_fnTernSecureNextHandler.bench.js +30 -0
- package/dist/esm/__tests__/gemini_fnTernSecureNextHandler.bench.js.map +1 -0
- package/dist/esm/app-router/admin/actions.js +40 -0
- package/dist/esm/app-router/admin/actions.js.map +1 -0
- package/dist/esm/app-router/admin/constants.js +5 -0
- package/dist/esm/app-router/admin/constants.js.map +1 -0
- package/dist/esm/app-router/admin/fnValidators.js +270 -0
- package/dist/esm/app-router/admin/fnValidators.js.map +1 -0
- package/dist/esm/app-router/admin/index.js +16 -2
- package/dist/esm/app-router/admin/index.js.map +1 -1
- package/dist/esm/app-router/admin/responses.js +93 -0
- package/dist/esm/app-router/admin/responses.js.map +1 -0
- package/dist/esm/app-router/admin/sessionHandlers.js +131 -0
- package/dist/esm/app-router/admin/sessionHandlers.js.map +1 -0
- package/dist/esm/app-router/admin/ternsecureNextjsHandler.js +62 -0
- package/dist/esm/app-router/admin/ternsecureNextjsHandler.js.map +1 -0
- package/dist/esm/app-router/admin/types.js +98 -0
- package/dist/esm/app-router/admin/types.js.map +1 -0
- package/dist/esm/app-router/admin/utils.js +80 -0
- package/dist/esm/app-router/admin/utils.js.map +1 -0
- package/dist/esm/app-router/admin/validators.js +189 -0
- package/dist/esm/app-router/admin/validators.js.map +1 -0
- package/dist/esm/app-router/client/TernSecureProvider.js +2 -6
- package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -1
- package/dist/esm/app-router/server/auth.js +81 -0
- package/dist/esm/app-router/server/auth.js.map +1 -0
- package/dist/esm/app-router/server/utils.js +51 -0
- package/dist/esm/app-router/server/utils.js.map +1 -0
- package/dist/esm/boundary/components.js +4 -7
- package/dist/esm/boundary/components.js.map +1 -1
- package/dist/esm/constants.js +17 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.js +5 -11
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/constant.js +11 -0
- package/dist/esm/server/constant.js.map +1 -0
- package/dist/esm/server/edge-session.js +113 -22
- package/dist/esm/server/edge-session.js.map +1 -1
- package/dist/esm/server/headers-utils.js +41 -0
- package/dist/esm/server/headers-utils.js.map +1 -0
- package/dist/esm/server/index.js +9 -3
- package/dist/esm/server/index.js.map +1 -1
- package/dist/esm/server/jwt-edge.js +48 -20
- package/dist/esm/server/jwt-edge.js.map +1 -1
- package/dist/esm/server/jwt.js +12 -5
- package/dist/esm/server/jwt.js.map +1 -1
- package/dist/esm/server/nextErrors.js +97 -0
- package/dist/esm/server/nextErrors.js.map +1 -0
- package/dist/esm/server/nextFetcher.js +7 -0
- package/dist/esm/server/nextFetcher.js.map +1 -0
- package/dist/esm/server/node/SessionTernSecure.js +31 -0
- package/dist/esm/server/node/SessionTernSecure.js.map +1 -0
- package/dist/esm/server/{auth.js → node/auth.js} +11 -20
- package/dist/esm/server/node/auth.js.map +1 -0
- package/dist/esm/server/node/index.js +19 -0
- package/dist/esm/server/node/index.js.map +1 -0
- package/dist/esm/server/node/node-session.js +36 -0
- package/dist/esm/server/node/node-session.js.map +1 -0
- package/dist/esm/server/node/ternSecureNodeMiddleware.js +165 -0
- package/dist/esm/server/node/ternSecureNodeMiddleware.js.map +1 -0
- package/dist/esm/server/protect.js +66 -0
- package/dist/esm/server/protect.js.map +1 -0
- package/dist/esm/server/redirect.js +60 -0
- package/dist/esm/server/redirect.js.map +1 -0
- package/dist/esm/server/routeMatcher.js +12 -0
- package/dist/esm/server/routeMatcher.js.map +1 -0
- package/dist/esm/server/sdk-versions.js +8 -0
- package/dist/esm/server/sdk-versions.js.map +1 -0
- package/dist/esm/server/session-store.js.map +1 -1
- package/dist/esm/server/ternSecureEdgeMiddleware.js +286 -0
- package/dist/esm/server/ternSecureEdgeMiddleware.js.map +1 -0
- package/dist/esm/server/ternSecureFireMiddleware.js +179 -0
- package/dist/esm/server/ternSecureFireMiddleware.js.map +1 -0
- package/dist/esm/server/utils.js +99 -1
- package/dist/esm/server/utils.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/NextCookieAdapter.js +20 -0
- package/dist/esm/utils/NextCookieAdapter.js.map +1 -0
- package/dist/esm/utils/allNextProviderProps.js +10 -24
- package/dist/esm/utils/allNextProviderProps.js.map +1 -1
- package/dist/esm/utils/config.js +34 -1
- package/dist/esm/utils/config.js.map +1 -1
- package/dist/esm/utils/construct.js +1 -1
- package/dist/esm/utils/construct.js.map +1 -1
- package/dist/esm/utils/fireconfig.js +14 -0
- package/dist/esm/utils/fireconfig.js.map +1 -0
- package/dist/esm/utils/logger.js +74 -0
- package/dist/esm/utils/logger.js.map +1 -0
- package/dist/esm/utils/redis.js +9 -0
- package/dist/esm/utils/redis.js.map +1 -0
- package/dist/esm/utils/response.js +13 -0
- package/dist/esm/utils/response.js.map +1 -0
- package/dist/esm/utils/serverRedirectAuth.js +17 -0
- package/dist/esm/utils/serverRedirectAuth.js.map +1 -0
- package/dist/esm/utils/ternsecure-sw.js +1 -1
- package/dist/esm/utils/ternsecure-sw.js.map +1 -1
- package/dist/esm/utils/withLogger.js +57 -0
- package/dist/esm/utils/withLogger.js.map +1 -0
- package/dist/types/app-router/admin/actions.d.ts +19 -0
- package/dist/types/app-router/admin/actions.d.ts.map +1 -0
- package/dist/types/app-router/admin/constants.d.ts +2 -0
- package/dist/types/app-router/admin/constants.d.ts.map +1 -0
- package/dist/types/app-router/admin/fnValidators.d.ts +35 -0
- package/dist/types/app-router/admin/fnValidators.d.ts.map +1 -0
- package/dist/types/app-router/admin/index.d.ts +3 -1
- package/dist/types/app-router/admin/index.d.ts.map +1 -1
- package/dist/types/app-router/admin/responses.d.ts +28 -0
- package/dist/types/app-router/admin/responses.d.ts.map +1 -0
- package/dist/types/app-router/admin/sessionHandlers.d.ts +26 -0
- package/dist/types/app-router/admin/sessionHandlers.d.ts.map +1 -0
- package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts +7 -0
- package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts.map +1 -0
- package/dist/types/app-router/admin/types.d.ts +105 -0
- package/dist/types/app-router/admin/types.d.ts.map +1 -0
- package/dist/types/app-router/admin/utils.d.ts +53 -0
- package/dist/types/app-router/admin/utils.d.ts.map +1 -0
- package/dist/types/app-router/admin/validators.d.ts +46 -0
- package/dist/types/app-router/admin/validators.d.ts.map +1 -0
- package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -1
- package/dist/types/app-router/server/auth.d.ts +26 -0
- package/dist/types/app-router/server/auth.d.ts.map +1 -0
- package/dist/types/app-router/server/utils.d.ts +5 -0
- package/dist/types/app-router/server/utils.d.ts.map +1 -0
- package/dist/types/boundary/components.d.ts +1 -1
- package/dist/types/boundary/components.d.ts.map +1 -1
- package/dist/types/constants.d.ts +11 -0
- package/dist/types/constants.d.ts.map +1 -0
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/server/constant.d.ts +5 -0
- package/dist/types/server/constant.d.ts.map +1 -0
- package/dist/types/server/edge-session.d.ts +13 -1
- package/dist/types/server/edge-session.d.ts.map +1 -1
- package/dist/types/server/headers-utils.d.ts +10 -0
- package/dist/types/server/headers-utils.d.ts.map +1 -0
- package/dist/types/server/index.d.ts +6 -3
- package/dist/types/server/index.d.ts.map +1 -1
- package/dist/types/server/jwt-edge.d.ts +12 -18
- package/dist/types/server/jwt-edge.d.ts.map +1 -1
- package/dist/types/server/jwt.d.ts +12 -18
- package/dist/types/server/jwt.d.ts.map +1 -1
- package/dist/types/server/nextErrors.d.ts +54 -0
- package/dist/types/server/nextErrors.d.ts.map +1 -0
- package/dist/types/server/nextFetcher.d.ts +26 -0
- package/dist/types/server/nextFetcher.d.ts.map +1 -0
- package/dist/types/server/node/SessionTernSecure.d.ts +3 -0
- package/dist/types/server/node/SessionTernSecure.d.ts.map +1 -0
- package/dist/types/server/{auth.d.ts → node/auth.d.ts} +5 -5
- package/dist/types/server/node/auth.d.ts.map +1 -0
- package/dist/types/server/node/index.d.ts +3 -0
- package/dist/types/server/node/index.d.ts.map +1 -0
- package/dist/types/server/node/node-session.d.ts +4 -0
- package/dist/types/server/node/node-session.d.ts.map +1 -0
- package/dist/types/server/node/ternSecureNodeMiddleware.d.ts +54 -0
- package/dist/types/server/node/ternSecureNodeMiddleware.d.ts.map +1 -0
- package/dist/types/server/protect.d.ts +26 -0
- package/dist/types/server/protect.d.ts.map +1 -0
- package/dist/types/server/redirect.d.ts +20 -0
- package/dist/types/server/redirect.d.ts.map +1 -0
- package/dist/types/server/routeMatcher.d.ts +13 -0
- package/dist/types/server/routeMatcher.d.ts.map +1 -0
- package/dist/types/server/sdk-versions.d.ts +8 -0
- package/dist/types/server/sdk-versions.d.ts.map +1 -0
- package/dist/types/server/session-store.d.ts.map +1 -1
- package/dist/types/server/ternSecureEdgeMiddleware.d.ts +47 -0
- package/dist/types/server/ternSecureEdgeMiddleware.d.ts.map +1 -0
- package/dist/types/server/ternSecureFireMiddleware.d.ts +47 -0
- package/dist/types/server/ternSecureFireMiddleware.d.ts.map +1 -0
- package/dist/types/server/types.d.ts +16 -2
- package/dist/types/server/types.d.ts.map +1 -1
- package/dist/types/server/utils.d.ts +7 -0
- package/dist/types/server/utils.d.ts.map +1 -1
- package/dist/types/types.d.ts +33 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/NextCookieAdapter.d.ts +9 -0
- package/dist/types/utils/NextCookieAdapter.d.ts.map +1 -0
- package/dist/types/utils/allNextProviderProps.d.ts +1 -1
- package/dist/types/utils/allNextProviderProps.d.ts.map +1 -1
- package/dist/types/utils/config.d.ts +17 -1
- package/dist/types/utils/config.d.ts.map +1 -1
- package/dist/types/utils/fireconfig.d.ts +4 -0
- package/dist/types/utils/fireconfig.d.ts.map +1 -0
- package/dist/types/utils/logger.d.ts +27 -0
- package/dist/types/utils/logger.d.ts.map +1 -0
- package/dist/types/utils/redis.d.ts +8 -0
- package/dist/types/utils/redis.d.ts.map +1 -0
- package/dist/types/utils/response.d.ts +3 -0
- package/dist/types/utils/response.d.ts.map +1 -0
- package/dist/types/utils/serverRedirectAuth.d.ts +6 -0
- package/dist/types/utils/serverRedirectAuth.d.ts.map +1 -0
- package/dist/types/utils/withLogger.d.ts +17 -0
- package/dist/types/utils/withLogger.d.ts.map +1 -0
- package/package.json +21 -7
- package/server/node/package.json +5 -0
- package/server/package.json +5 -0
- package/dist/cjs/app-router/admin/sessionHandler.js +0 -74
- package/dist/cjs/app-router/admin/sessionHandler.js.map +0 -1
- package/dist/cjs/app-router/client/actions.js +0 -4
- package/dist/cjs/app-router/client/actions.js.map +0 -1
- package/dist/cjs/components/uiComponents.js.map +0 -1
- package/dist/cjs/server/auth.js.map +0 -1
- package/dist/cjs/server/ternSecureMiddleware.js +0 -95
- package/dist/cjs/server/ternSecureMiddleware.js.map +0 -1
- package/dist/cjs/utils/tern-ui-script.js +0 -78
- package/dist/cjs/utils/tern-ui-script.js.map +0 -1
- package/dist/esm/app-router/admin/sessionHandler.js +0 -50
- package/dist/esm/app-router/admin/sessionHandler.js.map +0 -1
- package/dist/esm/app-router/client/actions.js +0 -3
- package/dist/esm/app-router/client/actions.js.map +0 -1
- package/dist/esm/components/uiComponents.js +0 -21
- package/dist/esm/components/uiComponents.js.map +0 -1
- package/dist/esm/server/auth.js.map +0 -1
- package/dist/esm/server/ternSecureMiddleware.js +0 -69
- package/dist/esm/server/ternSecureMiddleware.js.map +0 -1
- package/dist/esm/utils/tern-ui-script.js +0 -44
- package/dist/esm/utils/tern-ui-script.js.map +0 -1
- package/dist/types/app-router/admin/sessionHandler.d.ts +0 -3
- package/dist/types/app-router/admin/sessionHandler.d.ts.map +0 -1
- package/dist/types/app-router/client/actions.d.ts +0 -2
- package/dist/types/app-router/client/actions.d.ts.map +0 -1
- package/dist/types/components/uiComponents.d.ts +0 -6
- package/dist/types/components/uiComponents.d.ts.map +0 -1
- package/dist/types/server/auth.d.ts.map +0 -1
- package/dist/types/server/ternSecureMiddleware.d.ts +0 -20
- package/dist/types/server/ternSecureMiddleware.d.ts.map +0 -1
- package/dist/types/utils/tern-ui-script.d.ts +0 -9
- package/dist/types/utils/tern-ui-script.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/jwt.ts"],"sourcesContent":["import { jwtVerify
|
|
1
|
+
{"version":3,"sources":["../../../src/server/jwt.ts"],"sourcesContent":["import { createRemoteJWKSet,jwtVerify } from \"jose\";\r\nimport { cache } from \"react\";\r\n\r\ninterface FirebaseIdTokenPayload {\r\n iss: string;\r\n aud: string;\r\n auth_time: number;\r\n user_id: string;\r\n sub: string;\r\n iat: number;\r\n exp: number;\r\n email?: string;\r\n email_verified?: boolean;\r\n firebase: {\r\n identities: {\r\n [key: string]: any;\r\n };\r\n sign_in_provider: string;\r\n tenant?: string;\r\n };\r\n}\r\n\r\ninterface FirebaseTokenResult {\r\n valid: boolean;\r\n tenant?: string;\r\n uid?: string;\r\n email?: string | null;\r\n emailVerified?: boolean;\r\n authTime?: number;\r\n issuedAt?: number;\r\n expiresAt?: number;\r\n error?: string;\r\n}\r\n\r\n// Firebase public key endpoints\r\nconst FIREBASE_ID_TOKEN_URL =\r\n \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\";\r\nconst FIREBASE_SESSION_CERT_URL =\r\n \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\";\r\n\r\n// Cache the JWKS using React cache\r\nconst getIdTokenJWKS = cache(() => {\r\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\r\n cacheMaxAge: 3600000, // 1 hour\r\n timeoutDuration: 5000, // 5 seconds\r\n cooldownDuration: 30000, // 30 seconds between retries\r\n });\r\n});\r\n\r\nconst getSessionJWKS = cache(() => {\r\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\r\n cacheMaxAge: 3600000, // 1 hour\r\n timeoutDuration: 5000, // 5 seconds\r\n cooldownDuration: 30000, // 30 seconds between retries\r\n });\r\n});\r\n\r\n// Helper to decode JWT without verification\r\nfunction decodeJwt(token: string) {\r\n try {\r\n const [headerB64, payloadB64] = token.split(\".\");\r\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString());\r\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString());\r\n return { header, payload };\r\n } catch (error) {\r\n console.error(\"Error decoding JWT:\", error);\r\n return null;\r\n }\r\n}\r\n\r\nexport async function verifyFirebaseToken(\r\n token: string,\r\n isSessionCookie = false\r\n): Promise<FirebaseTokenResult> {\r\n try {\r\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID;\r\n if (!projectId) {\r\n throw new Error(\"Firebase Project ID is not configured\");\r\n }\r\n\r\n const decoded = decodeJwt(token);\r\n if (!decoded) {\r\n throw new Error(\"Invalid token format\");\r\n }\r\n\r\n let retries = 3;\r\n let lastError: Error | null = null;\r\n\r\n while (retries > 0) {\r\n try {\r\n // Use different JWKS based on token type\r\n const JWKS = isSessionCookie\r\n ? await getSessionJWKS()\r\n : await getIdTokenJWKS();\r\n\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: isSessionCookie\r\n ? \"https://session.firebase.google.com/\" + projectId\r\n : \"https://securetoken.google.com/\" + projectId,\r\n audience: projectId,\r\n algorithms: [\"RS256\"],\r\n });\r\n\r\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload;\r\n const now = Math.floor(Date.now() / 1000);\r\n\r\n // Verify token claims\r\n if (firebasePayload.exp <= now) {\r\n throw new Error(\"Token has expired\");\r\n }\r\n\r\n if (firebasePayload.iat > now) {\r\n throw new Error(\"Token issued time is in the future\");\r\n }\r\n\r\n if (!firebasePayload.sub) {\r\n throw new Error(\"Token subject is empty\");\r\n }\r\n\r\n if (firebasePayload.auth_time > now) {\r\n throw new Error(\"Token auth time is in the future\");\r\n }\r\n\r\n return {\r\n valid: true,\r\n uid: firebasePayload.sub,\r\n email: firebasePayload.email,\r\n emailVerified: firebasePayload.email_verified,\r\n tenant: firebasePayload.firebase.tenant,\r\n authTime: firebasePayload.auth_time,\r\n issuedAt: firebasePayload.iat,\r\n expiresAt: firebasePayload.exp,\r\n };\r\n } catch (error) {\r\n lastError = error as Error;\r\n if (error instanceof Error && error.name === \"JWKSNoMatchingKey\") {\r\n console.warn(`JWKS retry attempt ${4 - retries}:`, error.message);\r\n retries--;\r\n if (retries > 0) {\r\n await new Promise((resolve) => setTimeout(resolve, 1000));\r\n continue;\r\n }\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n throw lastError || new Error(\"Failed to verify token after retries\");\r\n } catch (error) {\r\n console.error(\"Token verification details:\", {\r\n error:\r\n error instanceof Error\r\n ? {\r\n name: error.name,\r\n message: error.message,\r\n stack: error.stack,\r\n }\r\n : error,\r\n decoded: decodeJwt(token),\r\n //projectId,\r\n isSessionCookie,\r\n });\r\n\r\n return {\r\n valid: false,\r\n error: error instanceof Error ? error.message : \"Invalid token\",\r\n };\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const CONTROL_FLOW_ERROR = {
|
|
2
|
+
REDIRECT_TO_URL: "TERNSECURE_PROTECT_REDIRECT_TO_URL",
|
|
3
|
+
REDIRECT_TO_SIGN_IN: "TERNSECURE_PROTECT_REDIRECT_TO_SIGN_IN",
|
|
4
|
+
REDIRECT_TO_SIGN_UP: "TERNSECURE_PROTECT_REDIRECT_TO_SIGN_UP"
|
|
5
|
+
};
|
|
6
|
+
const LEGACY_NOT_FOUND_ERROR_CODE = "NEXT_NOT_FOUND";
|
|
7
|
+
function isLegacyNextjsNotFoundError(error) {
|
|
8
|
+
if (typeof error !== "object" || error === null || !("digest" in error)) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
return error.digest === LEGACY_NOT_FOUND_ERROR_CODE;
|
|
12
|
+
}
|
|
13
|
+
const HTTPAccessErrorStatusCodes = {
|
|
14
|
+
NOT_FOUND: 404,
|
|
15
|
+
FORBIDDEN: 403,
|
|
16
|
+
UNAUTHORIZED: 401
|
|
17
|
+
};
|
|
18
|
+
const ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatusCodes));
|
|
19
|
+
const HTTP_ERROR_FALLBACK_ERROR_CODE = "NEXT_HTTP_ERROR_FALLBACK";
|
|
20
|
+
function isHTTPAccessFallbackError(error) {
|
|
21
|
+
if (typeof error !== "object" || error === null || !("digest" in error) || typeof error.digest !== "string") {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
const [prefix, httpStatus] = error.digest.split(";");
|
|
25
|
+
return prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));
|
|
26
|
+
}
|
|
27
|
+
function whichHTTPAccessFallbackError(error) {
|
|
28
|
+
if (!isHTTPAccessFallbackError(error)) {
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
const [, httpStatus] = error.digest.split(";");
|
|
32
|
+
return Number(httpStatus);
|
|
33
|
+
}
|
|
34
|
+
function isNextjsNotFoundError(error) {
|
|
35
|
+
return isLegacyNextjsNotFoundError(error) || // Checks for the error thrown from `notFound()` for canary versions of next@15
|
|
36
|
+
whichHTTPAccessFallbackError(error) === HTTPAccessErrorStatusCodes.NOT_FOUND;
|
|
37
|
+
}
|
|
38
|
+
const REDIRECT_ERROR_CODE = "NEXT_REDIRECT";
|
|
39
|
+
function nextjsRedirectError(url, extra, type = "replace", statusCode = 307) {
|
|
40
|
+
const error = new Error(REDIRECT_ERROR_CODE);
|
|
41
|
+
error.digest = `${REDIRECT_ERROR_CODE};${type};${url};${statusCode};`;
|
|
42
|
+
error.tern_digest = CONTROL_FLOW_ERROR.REDIRECT_TO_URL;
|
|
43
|
+
Object.assign(error, extra);
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
function buildReturnBackUrl(url, returnBackUrl) {
|
|
47
|
+
return returnBackUrl === null ? "" : returnBackUrl || url;
|
|
48
|
+
}
|
|
49
|
+
function redirectToSignInError(url, returnBackUrl) {
|
|
50
|
+
nextjsRedirectError(url, {
|
|
51
|
+
tern_digest: CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_IN,
|
|
52
|
+
returnBackUrl: buildReturnBackUrl(url, returnBackUrl)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function redirectToSignUpError(url, returnBackUrl) {
|
|
56
|
+
nextjsRedirectError(url, {
|
|
57
|
+
tern_digest: CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_UP,
|
|
58
|
+
returnBackUrl: buildReturnBackUrl(url, returnBackUrl)
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function isNextjsRedirectError(error) {
|
|
62
|
+
if (typeof error !== "object" || error === null || !("digest" in error) || typeof error.digest !== "string") {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
const digest = error.digest.split(";");
|
|
66
|
+
const [errorCode, type] = digest;
|
|
67
|
+
const destination = digest.slice(2, -2).join(";");
|
|
68
|
+
const status = digest.at(-2);
|
|
69
|
+
const statusCode = Number(status);
|
|
70
|
+
return errorCode === REDIRECT_ERROR_CODE && (type === "replace" || type === "push") && typeof destination === "string" && !isNaN(statusCode) && statusCode === 307;
|
|
71
|
+
}
|
|
72
|
+
function isRedirectToSignInError(error) {
|
|
73
|
+
if (isNextjsRedirectError(error) && "tern_digest" in error) {
|
|
74
|
+
return error.tern_digest === CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_IN;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
function isRedirectToSignUpError(error) {
|
|
79
|
+
if (isNextjsRedirectError(error) && "tern_digest" in error) {
|
|
80
|
+
return error.tern_digest === CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_UP;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
export {
|
|
85
|
+
HTTP_ERROR_FALLBACK_ERROR_CODE,
|
|
86
|
+
isHTTPAccessFallbackError,
|
|
87
|
+
isLegacyNextjsNotFoundError,
|
|
88
|
+
isNextjsNotFoundError,
|
|
89
|
+
isNextjsRedirectError,
|
|
90
|
+
isRedirectToSignInError,
|
|
91
|
+
isRedirectToSignUpError,
|
|
92
|
+
nextjsRedirectError,
|
|
93
|
+
redirectToSignInError,
|
|
94
|
+
redirectToSignUpError,
|
|
95
|
+
whichHTTPAccessFallbackError
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=nextErrors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/nextErrors.ts"],"sourcesContent":["\nconst CONTROL_FLOW_ERROR = {\n REDIRECT_TO_URL: 'TERNSECURE_PROTECT_REDIRECT_TO_URL',\n REDIRECT_TO_SIGN_IN: 'TERNSECURE_PROTECT_REDIRECT_TO_SIGN_IN',\n REDIRECT_TO_SIGN_UP: 'TERNSECURE_PROTECT_REDIRECT_TO_SIGN_UP',\n};\n\n/**\n * In-house implementation of `notFound()`\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/not-found.ts\n */\nconst LEGACY_NOT_FOUND_ERROR_CODE = 'NEXT_NOT_FOUND';\n\ntype LegacyNotFoundError = Error & {\n digest: typeof LEGACY_NOT_FOUND_ERROR_CODE;\n};\n\n/**\n * Checks for the error thrown from `notFound()` for versions <= next@15.0.4\n */\nfunction isLegacyNextjsNotFoundError(error: unknown): error is LegacyNotFoundError {\n if (typeof error !== 'object' || error === null || !('digest' in error)) {\n return false;\n }\n\n return error.digest === LEGACY_NOT_FOUND_ERROR_CODE;\n}\n\nconst HTTPAccessErrorStatusCodes = {\n NOT_FOUND: 404,\n FORBIDDEN: 403,\n UNAUTHORIZED: 401,\n};\n\nconst ALLOWED_CODES = new Set(Object.values(HTTPAccessErrorStatusCodes));\n\nexport const HTTP_ERROR_FALLBACK_ERROR_CODE = 'NEXT_HTTP_ERROR_FALLBACK';\n\nexport type HTTPAccessFallbackError = Error & {\n digest: `${typeof HTTP_ERROR_FALLBACK_ERROR_CODE};${string}`;\n};\n\nexport function isHTTPAccessFallbackError(error: unknown): error is HTTPAccessFallbackError {\n if (typeof error !== 'object' || error === null || !('digest' in error) || typeof error.digest !== 'string') {\n return false;\n }\n const [prefix, httpStatus] = error.digest.split(';');\n\n return prefix === HTTP_ERROR_FALLBACK_ERROR_CODE && ALLOWED_CODES.has(Number(httpStatus));\n}\n\nexport function whichHTTPAccessFallbackError(error: unknown): number | undefined {\n if (!isHTTPAccessFallbackError(error)) {\n return undefined;\n }\n\n const [, httpStatus] = error.digest.split(';');\n return Number(httpStatus);\n}\n\nfunction isNextjsNotFoundError(error: unknown): error is LegacyNotFoundError | HTTPAccessFallbackError {\n return (\n isLegacyNextjsNotFoundError(error) ||\n // Checks for the error thrown from `notFound()` for canary versions of next@15\n whichHTTPAccessFallbackError(error) === HTTPAccessErrorStatusCodes.NOT_FOUND\n );\n}\n\n/**\n * In-house implementation of `redirect()` extended with a `tern_digest` property\n * https://github.com/vercel/next.js/blob/canary/packages/next/src/client/components/redirect.ts\n */\n\nconst REDIRECT_ERROR_CODE = 'NEXT_REDIRECT';\n\ntype RedirectError<T = unknown> = Error & {\n digest: `${typeof REDIRECT_ERROR_CODE};${'replace'};${string};${307};`;\n tern_digest: typeof CONTROL_FLOW_ERROR.REDIRECT_TO_URL | typeof CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_IN;\n} & T;\n\nfunction nextjsRedirectError(\n url: string,\n extra: Record<string, unknown>,\n type: 'replace' = 'replace',\n statusCode: 307 = 307,\n): never {\n const error = new Error(REDIRECT_ERROR_CODE) as RedirectError;\n error.digest = `${REDIRECT_ERROR_CODE};${type};${url};${statusCode};`;\n error.tern_digest = CONTROL_FLOW_ERROR.REDIRECT_TO_URL;\n Object.assign(error, extra);\n throw error;\n}\n\nfunction buildReturnBackUrl(url: string, returnBackUrl?: string | URL | null): string | URL {\n return returnBackUrl === null ? '' : returnBackUrl || url;\n}\n\nfunction redirectToSignInError(url: string, returnBackUrl?: string | URL | null): never {\n nextjsRedirectError(url, {\n tern_digest: CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_IN,\n returnBackUrl: buildReturnBackUrl(url, returnBackUrl),\n });\n}\n\nfunction redirectToSignUpError(url: string, returnBackUrl?: string | URL | null): never {\n nextjsRedirectError(url, {\n tern_digest: CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_UP,\n returnBackUrl: buildReturnBackUrl(url, returnBackUrl),\n });\n}\n\n/**\n * Checks an error to determine if it's an error generated by the\n * `redirect(url)` helper.\n *\n * @param error the error that may reference a redirect error\n * @returns true if the error is a redirect error\n */\nfunction isNextjsRedirectError(error: unknown): error is RedirectError<{ redirectUrl: string | URL }> {\n if (typeof error !== 'object' || error === null || !('digest' in error) || typeof error.digest !== 'string') {\n return false;\n }\n\n const digest = error.digest.split(';');\n const [errorCode, type] = digest;\n const destination = digest.slice(2, -2).join(';');\n const status = digest.at(-2);\n\n const statusCode = Number(status);\n\n return (\n errorCode === REDIRECT_ERROR_CODE &&\n (type === 'replace' || type === 'push') &&\n typeof destination === 'string' &&\n !isNaN(statusCode) &&\n statusCode === 307\n );\n}\n\nfunction isRedirectToSignInError(error: unknown): error is RedirectError<{ returnBackUrl: string | URL }> {\n if (isNextjsRedirectError(error) && 'tern_digest' in error) {\n return error.tern_digest === CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_IN;\n }\n\n return false;\n}\n\nfunction isRedirectToSignUpError(error: unknown): error is RedirectError<{ returnBackUrl: string | URL }> {\n if (isNextjsRedirectError(error) && 'tern_digest' in error) {\n return error.tern_digest === CONTROL_FLOW_ERROR.REDIRECT_TO_SIGN_UP;\n }\n\n return false;\n}\n\nexport {\n isNextjsNotFoundError,\n isLegacyNextjsNotFoundError,\n redirectToSignInError,\n redirectToSignUpError,\n nextjsRedirectError,\n isNextjsRedirectError,\n isRedirectToSignInError,\n isRedirectToSignUpError,\n};\n"],"mappings":"AACA,MAAM,qBAAqB;AAAA,EACzB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,qBAAqB;AACvB;AAMA,MAAM,8BAA8B;AASpC,SAAS,4BAA4B,OAA8C;AACjF,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,YAAY,QAAQ;AACvE,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,WAAW;AAC1B;AAEA,MAAM,6BAA6B;AAAA,EACjC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,cAAc;AAChB;AAEA,MAAM,gBAAgB,IAAI,IAAI,OAAO,OAAO,0BAA0B,CAAC;AAEhE,MAAM,iCAAiC;AAMvC,SAAS,0BAA0B,OAAkD;AAC1F,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,YAAY,UAAU,OAAO,MAAM,WAAW,UAAU;AAC3G,WAAO;AAAA,EACT;AACA,QAAM,CAAC,QAAQ,UAAU,IAAI,MAAM,OAAO,MAAM,GAAG;AAEnD,SAAO,WAAW,kCAAkC,cAAc,IAAI,OAAO,UAAU,CAAC;AAC1F;AAEO,SAAS,6BAA6B,OAAoC;AAC/E,MAAI,CAAC,0BAA0B,KAAK,GAAG;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,EAAE,UAAU,IAAI,MAAM,OAAO,MAAM,GAAG;AAC7C,SAAO,OAAO,UAAU;AAC1B;AAEA,SAAS,sBAAsB,OAAwE;AACrG,SACE,4BAA4B,KAAK;AAAA,EAEjC,6BAA6B,KAAK,MAAM,2BAA2B;AAEvE;AAOA,MAAM,sBAAsB;AAO5B,SAAS,oBACP,KACA,OACA,OAAkB,WAClB,aAAkB,KACX;AACP,QAAM,QAAQ,IAAI,MAAM,mBAAmB;AAC3C,QAAM,SAAS,GAAG,mBAAmB,IAAI,IAAI,IAAI,GAAG,IAAI,UAAU;AAClE,QAAM,cAAc,mBAAmB;AACvC,SAAO,OAAO,OAAO,KAAK;AAC1B,QAAM;AACR;AAEA,SAAS,mBAAmB,KAAa,eAAmD;AAC1F,SAAO,kBAAkB,OAAO,KAAK,iBAAiB;AACxD;AAEA,SAAS,sBAAsB,KAAa,eAA4C;AACtF,sBAAoB,KAAK;AAAA,IACvB,aAAa,mBAAmB;AAAA,IAChC,eAAe,mBAAmB,KAAK,aAAa;AAAA,EACtD,CAAC;AACH;AAEA,SAAS,sBAAsB,KAAa,eAA4C;AACtF,sBAAoB,KAAK;AAAA,IACvB,aAAa,mBAAmB;AAAA,IAChC,eAAe,mBAAmB,KAAK,aAAa;AAAA,EACtD,CAAC;AACH;AASA,SAAS,sBAAsB,OAAuE;AACpG,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,YAAY,UAAU,OAAO,MAAM,WAAW,UAAU;AAC3G,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM,OAAO,MAAM,GAAG;AACrC,QAAM,CAAC,WAAW,IAAI,IAAI;AAC1B,QAAM,cAAc,OAAO,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG;AAChD,QAAM,SAAS,OAAO,GAAG,EAAE;AAE3B,QAAM,aAAa,OAAO,MAAM;AAEhC,SACE,cAAc,wBACb,SAAS,aAAa,SAAS,WAChC,OAAO,gBAAgB,YACvB,CAAC,MAAM,UAAU,KACjB,eAAe;AAEnB;AAEA,SAAS,wBAAwB,OAAyE;AACxG,MAAI,sBAAsB,KAAK,KAAK,iBAAiB,OAAO;AAC1D,WAAO,MAAM,gBAAgB,mBAAmB;AAAA,EAClD;AAEA,SAAO;AACT;AAEA,SAAS,wBAAwB,OAAyE;AACxG,MAAI,sBAAsB,KAAK,KAAK,iBAAiB,OAAO;AAC1D,WAAO,MAAM,gBAAgB,mBAAmB;AAAA,EAClD;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/nextFetcher.ts"],"sourcesContent":["type Fetcher = typeof globalThis.fetch;\n\n/**\n * Based on nextjs internal implementation https://github.com/vercel/next.js/blob/6185444e0a944a82e7719ac37dad8becfed86acd/packages/next/src/server/lib/patch-fetch.ts#L23\n */\ntype NextFetcher = Fetcher & {\n readonly __nextPatched: true;\n readonly __nextGetStaticStore: () => { getStore: () => StaticGenerationAsyncStorage | undefined };\n};\n\n/**\n * Full type can be found https://github.com/vercel/next.js/blob/6185444e0a944a82e7719ac37dad8becfed86acd/packages/next/src/client/components/static-generation-async-storage.external.ts#L4\n */\ninterface StaticGenerationAsyncStorage {\n /**\n * Available for Next 14\n */\n readonly pagePath?: string;\n /**\n * Available for Next 15\n */\n readonly page?: string;\n}\n\nfunction isNextFetcher(fetch: Fetcher | NextFetcher): fetch is NextFetcher {\n return '__nextPatched' in fetch && fetch.__nextPatched === true;\n}\n\nexport { isNextFetcher };\n"],"mappings":"AAwBA,SAAS,cAAc,OAAoD;AACzE,SAAO,mBAAmB,SAAS,MAAM,kBAAkB;AAC7D;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { VerifyNextTernSessionCookie } from "@tern-secure/backend/admin";
|
|
3
|
+
async function verifyFirebaseToken(token) {
|
|
4
|
+
if (!token) {
|
|
5
|
+
return {
|
|
6
|
+
valid: false,
|
|
7
|
+
error: {
|
|
8
|
+
success: false,
|
|
9
|
+
code: "INVALID_TOKEN",
|
|
10
|
+
message: "Token is required for verification"
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
return await VerifyNextTernSessionCookie(token);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error("Error verifying token:", error);
|
|
18
|
+
return {
|
|
19
|
+
valid: false,
|
|
20
|
+
error: {
|
|
21
|
+
success: false,
|
|
22
|
+
code: "INVALID_TOKEN",
|
|
23
|
+
message: error instanceof Error ? error.message : "Token verification failed"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
verifyFirebaseToken
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=SessionTernSecure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/server/node/SessionTernSecure.ts"],"sourcesContent":["\"use server\";\n\nimport { VerifyNextTernSessionCookie } from \"@tern-secure/backend/admin\";\nimport type { TernVerificationResult } from \"@tern-secure/types\";\n\nexport async function verifyFirebaseToken(\n token: string\n): Promise<TernVerificationResult> {\n if (!token) {\n return {\n valid: false,\n error: {\n success: false,\n code: \"INVALID_TOKEN\",\n message: \"Token is required for verification\",\n },\n };\n }\n\n try {\n return await VerifyNextTernSessionCookie(token);\n } catch (error) {\n console.error(\"Error verifying token:\", error);\n return {\n valid: false,\n error: {\n success: false,\n code: \"INVALID_TOKEN\",\n message:\n error instanceof Error ? error.message : \"Token verification failed\",\n },\n };\n }\n}\n"],"mappings":";AAEA,SAAS,mCAAmC;AAG5C,eAAsB,oBACpB,OACiC;AACjC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,WAAO,MAAM,4BAA4B,KAAK;AAAA,EAChD,SAAS,OAAO;AACd,YAAQ,MAAM,0BAA0B,KAAK;AAC7C,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,QACN,SACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,31 +1,19 @@
|
|
|
1
|
-
import { cache } from "react";
|
|
2
1
|
import { cookies } from "next/headers";
|
|
3
|
-
import {
|
|
4
|
-
import { TernSecureError } from "
|
|
2
|
+
import { cache } from "react";
|
|
3
|
+
import { TernSecureError } from "../../errors";
|
|
4
|
+
import { verifyFirebaseToken } from "./SessionTernSecure";
|
|
5
5
|
const auth = cache(async () => {
|
|
6
6
|
try {
|
|
7
|
-
console.log("auth: Starting auth check...");
|
|
8
7
|
const cookieStore = await cookies();
|
|
9
8
|
const sessionCookie = cookieStore.get("_session_cookie")?.value;
|
|
10
9
|
if (sessionCookie) {
|
|
11
|
-
const result = await verifyFirebaseToken(sessionCookie
|
|
12
|
-
if (result.valid) {
|
|
13
|
-
const user = {
|
|
14
|
-
uid: result.uid ?? "",
|
|
15
|
-
email: result.email || null,
|
|
16
|
-
authTime: result.authTime
|
|
17
|
-
};
|
|
18
|
-
return { user, error: null };
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const idToken = cookieStore.get("_session_token")?.value;
|
|
22
|
-
if (idToken) {
|
|
23
|
-
const result = await verifyFirebaseToken(idToken, false);
|
|
10
|
+
const result = await verifyFirebaseToken(sessionCookie);
|
|
24
11
|
if (result.valid) {
|
|
25
12
|
const user = {
|
|
26
13
|
uid: result.uid ?? "",
|
|
27
|
-
email: result.email
|
|
28
|
-
|
|
14
|
+
email: result.email && typeof result.email === "string" ? result.email : null,
|
|
15
|
+
tenantId: result.tenant || "default",
|
|
16
|
+
authTime: result.authTime && typeof result.authTime === "number" ? result.authTime : void 0
|
|
29
17
|
};
|
|
30
18
|
return { user, error: null };
|
|
31
19
|
}
|
|
@@ -44,7 +32,10 @@ const auth = cache(async () => {
|
|
|
44
32
|
}
|
|
45
33
|
return {
|
|
46
34
|
user: null,
|
|
47
|
-
error: new TernSecureError(
|
|
35
|
+
error: new TernSecureError(
|
|
36
|
+
"INTERNAL_ERROR",
|
|
37
|
+
"An unexpected error occurred"
|
|
38
|
+
)
|
|
48
39
|
};
|
|
49
40
|
}
|
|
50
41
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/server/node/auth.ts"],"sourcesContent":["import { cookies } from \"next/headers\";\nimport { cache } from \"react\";\n\nimport { TernSecureError } from \"../../errors\";\nimport type { BaseUser } from \"../../types\";\nimport { verifyFirebaseToken } from \"./SessionTernSecure\";\n\nexport interface AuthResult {\n user: BaseUser | null;\n error: Error | null;\n}\n\n/**\n * Get the current authenticated user from the session cookies\n */\nexport const auth = cache(async (): Promise<AuthResult> => {\n try {\n const cookieStore = await cookies();\n\n const sessionCookie = cookieStore.get(\"_session_cookie\")?.value;\n if (sessionCookie) {\n const result = await verifyFirebaseToken(sessionCookie);\n if (result.valid) {\n const user: BaseUser = {\n uid: result.uid ?? \"\",\n email:\n result.email && typeof result.email === \"string\"\n ? result.email\n : null,\n tenantId: result.tenant || \"default\",\n authTime:\n result.authTime && typeof result.authTime === \"number\"\n ? result.authTime\n : undefined,\n };\n return { user, error: null };\n }\n }\n\n return {\n user: null,\n error: new TernSecureError(\"UNAUTHENTICATED\", \"No valid session found\"),\n };\n } catch (error) {\n console.error(\"Error in Auth:\", error);\n if (error instanceof TernSecureError) {\n return {\n user: null,\n error,\n };\n }\n return {\n user: null,\n error: new TernSecureError(\n \"INTERNAL_ERROR\",\n \"An unexpected error occurred\"\n ),\n };\n }\n});\n\n/**\n * Type guard to check if user is authenticated\n */\nexport const isAuthenticated = cache(async (): Promise<boolean> => {\n const { user } = await auth();\n return user !== null;\n});\n\n/**\n * Get user info from auth result\n */\nexport const getUser = cache(async (): Promise<BaseUser | null> => {\n const { user } = await auth();\n return user;\n});\n\n/**\n * Require authentication\n * Throws error if not authenticated\n */\nexport const requireAuth = cache(async (): Promise<BaseUser> => {\n const { user, error } = await auth();\n\n if (!user) {\n throw error || new Error(\"Authentication required\");\n }\n\n return user;\n});\n"],"mappings":"AAAA,SAAS,eAAe;AACxB,SAAS,aAAa;AAEtB,SAAS,uBAAuB;AAEhC,SAAS,2BAA2B;AAU7B,MAAM,OAAO,MAAM,YAAiC;AACzD,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAElC,UAAM,gBAAgB,YAAY,IAAI,iBAAiB,GAAG;AAC1D,QAAI,eAAe;AACjB,YAAM,SAAS,MAAM,oBAAoB,aAAa;AACtD,UAAI,OAAO,OAAO;AAChB,cAAM,OAAiB;AAAA,UACrB,KAAK,OAAO,OAAO;AAAA,UACnB,OACE,OAAO,SAAS,OAAO,OAAO,UAAU,WACpC,OAAO,QACP;AAAA,UACN,UAAU,OAAO,UAAU;AAAA,UAC3B,UACE,OAAO,YAAY,OAAO,OAAO,aAAa,WAC1C,OAAO,WACP;AAAA,QACR;AACA,eAAO,EAAE,MAAM,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,IAAI,gBAAgB,mBAAmB,wBAAwB;AAAA,IACxE;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,kBAAkB,KAAK;AACrC,QAAI,iBAAiB,iBAAiB;AACpC,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAKM,MAAM,kBAAkB,MAAM,YAA8B;AACjE,QAAM,EAAE,KAAK,IAAI,MAAM,KAAK;AAC5B,SAAO,SAAS;AAClB,CAAC;AAKM,MAAM,UAAU,MAAM,YAAsC;AACjE,QAAM,EAAE,KAAK,IAAI,MAAM,KAAK;AAC5B,SAAO;AACT,CAAC;AAMM,MAAM,cAAc,MAAM,YAA+B;AAC9D,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK;AAEnC,MAAI,CAAC,MAAM;AACT,UAAM,SAAS,IAAI,MAAM,yBAAyB;AAAA,EACpD;AAEA,SAAO;AACT,CAAC;","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ternSecureMiddleware,
|
|
3
|
+
createRouteMatcher
|
|
4
|
+
} from "./ternSecureNodeMiddleware";
|
|
5
|
+
import {
|
|
6
|
+
auth,
|
|
7
|
+
getUser,
|
|
8
|
+
isAuthenticated,
|
|
9
|
+
requireAuth
|
|
10
|
+
} from "./auth";
|
|
11
|
+
export {
|
|
12
|
+
auth,
|
|
13
|
+
createRouteMatcher,
|
|
14
|
+
getUser,
|
|
15
|
+
isAuthenticated,
|
|
16
|
+
requireAuth,
|
|
17
|
+
ternSecureMiddleware
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/server/node/index.ts"],"sourcesContent":["export {\n ternSecureMiddleware,\n createRouteMatcher,\n} from \"./ternSecureNodeMiddleware\";\nexport {\n auth,\n getUser,\n isAuthenticated,\n requireAuth,\n type AuthResult,\n} from \"./auth\";"],"mappings":"AAAA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;","names":[]}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { verifyFirebaseToken } from "./SessionTernSecure";
|
|
2
|
+
async function verifySession(request) {
|
|
3
|
+
try {
|
|
4
|
+
const sessionCookie = request.cookies.get("_session_cookie")?.value;
|
|
5
|
+
if (sessionCookie) {
|
|
6
|
+
const result = await verifyFirebaseToken(sessionCookie);
|
|
7
|
+
if (result.valid) {
|
|
8
|
+
return {
|
|
9
|
+
isAuthenticated: true,
|
|
10
|
+
user: {
|
|
11
|
+
uid: result.uid ?? "",
|
|
12
|
+
email: result.email || null,
|
|
13
|
+
tenantId: result.tenant || "default",
|
|
14
|
+
disabled: false
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
isAuthenticated: false,
|
|
21
|
+
user: null,
|
|
22
|
+
error: "No valid session found"
|
|
23
|
+
};
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error("Session verification error:", error);
|
|
26
|
+
return {
|
|
27
|
+
isAuthenticated: false,
|
|
28
|
+
user: null,
|
|
29
|
+
error: error instanceof Error ? error.message : "Session verification failed"
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
verifySession
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=node-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/server/node/node-session.ts"],"sourcesContent":["import type { NextRequest } from \"next/server\";\n\nimport type { SessionResult } from \"../types\";\nimport { verifyFirebaseToken } from \"./SessionTernSecure\";\n\nexport async function verifySession(\n request: NextRequest\n): Promise<SessionResult> {\n try {\n const sessionCookie = request.cookies.get(\"_session_cookie\")?.value;\n if (sessionCookie) {\n const result = await verifyFirebaseToken(sessionCookie);\n if (result.valid) {\n //const disabledKey = `disabled_user:${result.uid}`;\n //const disabledUser: DisabledUserRecord | null =\n // await redis.get(disabledKey);\n //const isDisabled = !!disabledUser;\n return {\n isAuthenticated: true,\n user: {\n uid: result.uid ?? \"\",\n email: result.email || null,\n tenantId: result.tenant || \"default\",\n disabled: false,\n },\n };\n }\n }\n return {\n isAuthenticated: false,\n user: null,\n error: \"No valid session found\",\n };\n } catch (error) {\n console.error(\"Session verification error:\", error);\n return {\n isAuthenticated: false,\n user: null,\n error:\n error instanceof Error ? error.message : \"Session verification failed\",\n };\n }\n}\n"],"mappings":"AAGA,SAAS,2BAA2B;AAEpC,eAAsB,cACpB,SACwB;AACxB,MAAI;AACF,UAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AAC9D,QAAI,eAAe;AACjB,YAAM,SAAS,MAAM,oBAAoB,aAAa;AACtD,UAAI,OAAO,OAAO;AAKhB,eAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,MAAM;AAAA,YACJ,KAAK,OAAO,OAAO;AAAA,YACnB,OAAO,OAAO,SAAS;AAAA,YACvB,UAAU,OAAO,UAAU;AAAA,YAC3B,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,+BAA+B,KAAK;AAClD,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,OACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC7C;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createTernSecureRequest } from "@tern-secure/backend";
|
|
2
|
+
import {
|
|
3
|
+
createBackendInstance
|
|
4
|
+
} from "@tern-secure/backend/admin";
|
|
5
|
+
import { NextResponse } from "next/server";
|
|
6
|
+
import { SIGN_IN_URL, SIGN_UP_URL } from "../constant";
|
|
7
|
+
import {
|
|
8
|
+
isNextjsNotFoundError,
|
|
9
|
+
isRedirectToSignInError,
|
|
10
|
+
isRedirectToSignUpError,
|
|
11
|
+
redirectToSignInError,
|
|
12
|
+
redirectToSignUpError
|
|
13
|
+
} from "../nextErrors";
|
|
14
|
+
import { createRedirect } from "../redirect";
|
|
15
|
+
const createRouteMatcher = (patterns) => {
|
|
16
|
+
return (request) => {
|
|
17
|
+
const { pathname } = request.nextUrl;
|
|
18
|
+
return patterns.some((pattern) => {
|
|
19
|
+
const regexPattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\*/g, ".*");
|
|
20
|
+
return new RegExp(`^${regexPattern}$`).test(pathname);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
const authenticateMiddlewareRequest = async (request) => {
|
|
25
|
+
try {
|
|
26
|
+
const requestState = await createBackendInstance(request);
|
|
27
|
+
const authResult = requestState.requestState.auth();
|
|
28
|
+
return {
|
|
29
|
+
user: {
|
|
30
|
+
uid: authResult.session.uid,
|
|
31
|
+
email: authResult.session.email || null,
|
|
32
|
+
tenantId: authResult.session.firebase?.tenant || "default",
|
|
33
|
+
authTime: authResult.session.auth_time
|
|
34
|
+
},
|
|
35
|
+
session: requestState.requestState.token
|
|
36
|
+
};
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error(
|
|
39
|
+
"Auth check error:",
|
|
40
|
+
error instanceof Error ? error.message : "Unknown error"
|
|
41
|
+
);
|
|
42
|
+
return {
|
|
43
|
+
user: null,
|
|
44
|
+
session: null
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const ternSecureMiddleware = (...args) => {
|
|
49
|
+
const [request, event] = parseRequestAndEvent(args);
|
|
50
|
+
const [handler, params] = parseHandlerAndOptions(args);
|
|
51
|
+
const middleware = () => {
|
|
52
|
+
const withAuthNextMiddleware = async (request2, event2) => {
|
|
53
|
+
const resolvedParams = typeof params === "function" ? await params(request2) : params;
|
|
54
|
+
const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;
|
|
55
|
+
const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;
|
|
56
|
+
let handlerResult = NextResponse.next();
|
|
57
|
+
if (handler) {
|
|
58
|
+
const createAuthHandler = async () => {
|
|
59
|
+
const authObject = await authenticateMiddlewareRequest(request2);
|
|
60
|
+
const getAuth = async () => {
|
|
61
|
+
const ternSecureRequest = createTernSecureRequest(request2);
|
|
62
|
+
const { redirectToSignIn, redirectToSignUp } = createMiddlewareRedirects(
|
|
63
|
+
ternSecureRequest,
|
|
64
|
+
signInUrl,
|
|
65
|
+
signUpUrl
|
|
66
|
+
);
|
|
67
|
+
return {
|
|
68
|
+
...authObject,
|
|
69
|
+
redirectToSignIn,
|
|
70
|
+
redirectToSignUp
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
const protect = async () => {
|
|
74
|
+
if (!authObject.user || !authObject.session) {
|
|
75
|
+
const redirectUrl = new URL(signInUrl || "/sign-in", request2.url);
|
|
76
|
+
redirectUrl.searchParams.set(
|
|
77
|
+
"redirect",
|
|
78
|
+
request2.nextUrl.pathname
|
|
79
|
+
);
|
|
80
|
+
redirectToSignInError(redirectUrl.toString());
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const authHandler = Object.assign(getAuth, {
|
|
84
|
+
protect,
|
|
85
|
+
user: authObject.user,
|
|
86
|
+
session: authObject.session
|
|
87
|
+
});
|
|
88
|
+
return authHandler;
|
|
89
|
+
};
|
|
90
|
+
try {
|
|
91
|
+
const auth = await createAuthHandler();
|
|
92
|
+
const userHandlerResult = await handler(auth, request2, event2);
|
|
93
|
+
handlerResult = userHandlerResult || handlerResult;
|
|
94
|
+
} catch (error) {
|
|
95
|
+
const ternSecureRequest = createTernSecureRequest(request2);
|
|
96
|
+
handlerResult = handleControlError(error, ternSecureRequest, request2);
|
|
97
|
+
}
|
|
98
|
+
return handlerResult;
|
|
99
|
+
}
|
|
100
|
+
return handlerResult;
|
|
101
|
+
};
|
|
102
|
+
const nextMiddleware = async (request2, event2) => {
|
|
103
|
+
return withAuthNextMiddleware(request2, event2);
|
|
104
|
+
};
|
|
105
|
+
if (request && event) {
|
|
106
|
+
return nextMiddleware(request, event);
|
|
107
|
+
}
|
|
108
|
+
return nextMiddleware;
|
|
109
|
+
};
|
|
110
|
+
return middleware();
|
|
111
|
+
};
|
|
112
|
+
const parseRequestAndEvent = (args) => {
|
|
113
|
+
return [
|
|
114
|
+
args[0] instanceof Request ? args[0] : void 0,
|
|
115
|
+
args[0] instanceof Request ? args[1] : void 0
|
|
116
|
+
];
|
|
117
|
+
};
|
|
118
|
+
const parseHandlerAndOptions = (args) => {
|
|
119
|
+
return [
|
|
120
|
+
typeof args[0] === "function" ? args[0] : void 0,
|
|
121
|
+
(args.length === 2 ? args[1] : typeof args[0] === "function" ? {} : args[0]) || {}
|
|
122
|
+
];
|
|
123
|
+
};
|
|
124
|
+
const createMiddlewareRedirects = (ternSecureRequest, signInUrl, signUpUrl) => {
|
|
125
|
+
const redirectToSignIn = (opts = {}) => {
|
|
126
|
+
const url = signInUrl || ternSecureRequest.ternUrl.toString();
|
|
127
|
+
redirectToSignInError(url, opts.returnBackUrl);
|
|
128
|
+
};
|
|
129
|
+
const redirectToSignUp = (opts = {}) => {
|
|
130
|
+
const url = signUpUrl || ternSecureRequest.ternUrl.toString();
|
|
131
|
+
redirectToSignUpError(url, opts.returnBackUrl);
|
|
132
|
+
};
|
|
133
|
+
return { redirectToSignIn, redirectToSignUp };
|
|
134
|
+
};
|
|
135
|
+
const handleControlError = (error, ternSecureRequest, nextrequest) => {
|
|
136
|
+
if (isNextjsNotFoundError(error)) {
|
|
137
|
+
return NextResponse.rewrite(new URL("/404", nextrequest.url));
|
|
138
|
+
}
|
|
139
|
+
if (isRedirectToSignInError(error)) {
|
|
140
|
+
const redirectAdapter = (url) => NextResponse.redirect(new URL(url, nextrequest.url));
|
|
141
|
+
const { redirectToSignIn } = createRedirect({
|
|
142
|
+
redirectAdapter,
|
|
143
|
+
baseUrl: ternSecureRequest.ternUrl.origin,
|
|
144
|
+
signInUrl: SIGN_IN_URL,
|
|
145
|
+
signUpUrl: SIGN_UP_URL
|
|
146
|
+
});
|
|
147
|
+
return redirectToSignIn({ returnBackUrl: error.returnBackUrl });
|
|
148
|
+
}
|
|
149
|
+
if (isRedirectToSignUpError(error)) {
|
|
150
|
+
const redirectAdapter = (url) => NextResponse.redirect(new URL(url, nextrequest.url));
|
|
151
|
+
const { redirectToSignUp } = createRedirect({
|
|
152
|
+
redirectAdapter,
|
|
153
|
+
baseUrl: ternSecureRequest.ternUrl.origin,
|
|
154
|
+
signInUrl: SIGN_IN_URL,
|
|
155
|
+
signUpUrl: SIGN_UP_URL
|
|
156
|
+
});
|
|
157
|
+
return redirectToSignUp({ returnBackUrl: error.returnBackUrl });
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
};
|
|
161
|
+
export {
|
|
162
|
+
createRouteMatcher,
|
|
163
|
+
ternSecureMiddleware
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=ternSecureNodeMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/server/node/ternSecureNodeMiddleware.ts"],"sourcesContent":["import {createTernSecureRequest, type TernSecureRequest } from \"@tern-secure/backend\";\nimport {\n createBackendInstance,\n} from \"@tern-secure/backend/admin\";\nimport type { NextMiddleware,NextRequest } from \"next/server\";\nimport {NextResponse } from \"next/server\";\n\nimport { SIGN_IN_URL, SIGN_UP_URL } from \"../constant\";\nimport {\n isNextjsNotFoundError,\n isRedirectToSignInError,\n isRedirectToSignUpError,\n redirectToSignInError,\n redirectToSignUpError,\n} from \"../nextErrors\";\nimport { createRedirect } from \"../redirect\";\nimport type { BaseUser ,\n NextMiddlewareEvtParam,\n NextMiddlewareRequestParam,\n NextMiddlewareReturn,\n} from \"../types\";\n\ntype RedirectToParams = { returnBackUrl?: string | URL | null };\nexport type RedirectFun<ReturnType> = (params?: RedirectToParams) => ReturnType;\n\nexport type AuthObject = {\n user: BaseUser | null;\n session: string | null;\n};\n\nexport interface MiddlewareAuth extends AuthObject {\n (): Promise<MiddlewareAuthObject>;\n protect: () => Promise<void>;\n}\n\ntype MiddlewareHandler = (\n auth: MiddlewareAuth,\n request: NextMiddlewareRequestParam,\n event: NextMiddlewareEvtParam\n) => NextMiddlewareReturn;\n\nexport type MiddlewareAuthObject = AuthObject & {\n redirectToSignIn: RedirectFun<Response>;\n redirectToSignUp: RedirectFun<Response>;\n};\n\n/**\n * Create a route matcher function for public paths\n */\nexport const createRouteMatcher = (patterns: string[]) => {\n return (request: NextRequest): boolean => {\n const { pathname } = request.nextUrl;\n return patterns.some((pattern) => {\n const regexPattern = pattern\n .replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\")\n .replace(/\\\\\\*/g, \".*\");\n\n return new RegExp(`^${regexPattern}$`).test(pathname);\n });\n };\n};\n\nconst authenticateMiddlewareRequest = async (\n request: NextRequest\n): Promise<AuthObject> => {\n try {\n const requestState = await createBackendInstance(request);\n const authResult = requestState.requestState.auth();\n\n return {\n user: {\n uid: authResult.session.uid,\n email: authResult.session.email || null,\n tenantId: authResult.session.firebase?.tenant || \"default\",\n authTime: authResult.session.auth_time,\n },\n session: requestState.requestState.token,\n };\n } catch (error) {\n console.error(\n \"Auth check error:\",\n error instanceof Error ? error.message : \"Unknown error\"\n );\n return {\n user: null,\n session: null,\n };\n }\n};\n\nexport interface MiddlewareOptions {\n signInUrl?: string;\n signUpUrl?: string;\n debug?: boolean;\n}\ntype MiddlewareOptionsCallback = (\n req: NextRequest\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\n\ninterface TernSecureMiddleware {\n /**\n * @example\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\n */\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\n\n /**\n * @example\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\n */\n (\n handler: MiddlewareHandler,\n options?: MiddlewareOptionsCallback\n ): NextMiddleware;\n\n /**\n * @example\n * export default ternSecureMiddleware(options);\n */\n (options?: MiddlewareOptions): NextMiddleware;\n /**\n * @example\n * export default ternSecureMiddleware;\n */\n (\n request: NextMiddlewareRequestParam,\n event: NextMiddlewareEvtParam\n ): NextMiddlewareReturn;\n}\n\nexport const ternSecureMiddleware = ((\n ...args: unknown[]\n): NextMiddleware | NextMiddlewareReturn => {\n const [request, event] = parseRequestAndEvent(args);\n const [handler, params] = parseHandlerAndOptions(args);\n\n const middleware = () => {\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\n const resolvedParams =\n typeof params === \"function\" ? await params(request) : params;\n\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\n\n let handlerResult: Response = NextResponse.next();\n\n if (handler) {\n const createAuthHandler = async (): Promise<MiddlewareAuth> => {\n const authObject = await authenticateMiddlewareRequest(request);\n\n const getAuth = async (): Promise<MiddlewareAuthObject> => {\n const ternSecureRequest = createTernSecureRequest(request);\n const { redirectToSignIn, redirectToSignUp } =\n createMiddlewareRedirects(\n ternSecureRequest,\n signInUrl,\n signUpUrl\n );\n\n return {\n ...authObject,\n redirectToSignIn,\n redirectToSignUp,\n };\n };\n\n const protect = async (): Promise<void> => {\n if (!authObject.user || !authObject.session) {\n const redirectUrl = new URL(signInUrl || \"/sign-in\", request.url);\n redirectUrl.searchParams.set(\n \"redirect\",\n request.nextUrl.pathname\n );\n redirectToSignInError(redirectUrl.toString());\n }\n };\n\n // Return the MiddlewareAuth object with direct property access\n const authHandler = Object.assign(getAuth, {\n protect,\n user: authObject.user,\n session: authObject.session,\n });\n\n return authHandler as MiddlewareAuth;\n };\n\n try {\n const auth = await createAuthHandler();\n const userHandlerResult = await handler(auth, request, event);\n handlerResult = userHandlerResult || handlerResult;\n } catch (error) {\n const ternSecureRequest = createTernSecureRequest(request);\n handlerResult = handleControlError(error, ternSecureRequest, request);\n }\n\n return handlerResult;\n }\n\n return handlerResult;\n };\n\n const nextMiddleware: NextMiddleware = async (request, event) => {\n return withAuthNextMiddleware(request, event);\n };\n\n if (request && event) {\n return nextMiddleware(request, event);\n }\n\n return nextMiddleware;\n };\n return middleware();\n}) as TernSecureMiddleware;\n\nconst parseRequestAndEvent = (args: unknown[]) => {\n return [\n args[0] instanceof Request ? args[0] : undefined,\n args[0] instanceof Request ? args[1] : undefined,\n ] as [\n NextMiddlewareRequestParam | undefined,\n NextMiddlewareEvtParam | undefined,\n ];\n};\n\nconst parseHandlerAndOptions = (args: unknown[]) => {\n return [\n typeof args[0] === \"function\" ? args[0] : undefined,\n (args.length === 2\n ? args[1]\n : typeof args[0] === \"function\"\n ? {}\n : args[0]) || {},\n ] as [\n MiddlewareHandler | undefined,\n MiddlewareOptions | MiddlewareOptionsCallback,\n ];\n};\n\n/**\n * Create middleware redirect functions\n */\nconst createMiddlewareRedirects = (\n ternSecureRequest: TernSecureRequest,\n signInUrl: string,\n signUpUrl: string\n) => {\n const redirectToSignIn: MiddlewareAuthObject[\"redirectToSignIn\"] = (\n opts = {}\n ) => {\n const url = signInUrl || ternSecureRequest.ternUrl.toString();\n redirectToSignInError(url, opts.returnBackUrl);\n };\n\n const redirectToSignUp: MiddlewareAuthObject[\"redirectToSignUp\"] = (\n opts = {}\n ) => {\n const url = signUpUrl || ternSecureRequest.ternUrl.toString();\n redirectToSignUpError(url, opts.returnBackUrl);\n };\n\n return { redirectToSignIn, redirectToSignUp };\n};\n\n/**\n * Handle control flow errors in middleware\n */\nconst handleControlError = (\n error: any,\n ternSecureRequest: TernSecureRequest,\n nextrequest: NextRequest\n): Response => {\n if (isNextjsNotFoundError(error)) {\n return NextResponse.rewrite(new URL(\"/404\", nextrequest.url));\n }\n\n // Handle redirect to sign in errors\n if (isRedirectToSignInError(error)) {\n const redirectAdapter = (url: string) =>\n NextResponse.redirect(new URL(url, nextrequest.url));\n const { redirectToSignIn } = createRedirect({\n redirectAdapter,\n baseUrl: ternSecureRequest.ternUrl.origin,\n signInUrl: SIGN_IN_URL,\n signUpUrl: SIGN_UP_URL,\n });\n\n return redirectToSignIn({ returnBackUrl: error.returnBackUrl });\n }\n\n // Handle redirect to sign up errors\n if (isRedirectToSignUpError(error)) {\n const redirectAdapter = (url: string) =>\n NextResponse.redirect(new URL(url, nextrequest.url));\n const { redirectToSignUp } = createRedirect({\n redirectAdapter,\n baseUrl: ternSecureRequest.ternUrl.origin,\n signInUrl: SIGN_IN_URL,\n signUpUrl: SIGN_UP_URL,\n });\n\n return redirectToSignUp({ returnBackUrl: error.returnBackUrl });\n }\n\n throw error;\n};\n"],"mappings":"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","names":["request","event"]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { constants } from "@tern-secure/backend";
|
|
2
|
+
import { constants as nextConstants } from "../constants";
|
|
3
|
+
import { isNextFetcher } from "./nextFetcher";
|
|
4
|
+
function createProtect(opts) {
|
|
5
|
+
const { redirectToSignIn, authObject, redirect, notFound, request } = opts;
|
|
6
|
+
return async (...args) => {
|
|
7
|
+
const optionValuesAsParam = args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;
|
|
8
|
+
const paramsOrFunction = optionValuesAsParam ? void 0 : args[0];
|
|
9
|
+
const unauthenticatedUrl = args[0]?.unauthenticatedUrl || args[1]?.unauthenticatedUrl;
|
|
10
|
+
const unauthorizedUrl = args[0]?.unauthorizedUrl || args[1]?.unauthorizedUrl;
|
|
11
|
+
const handleUnauthenticated = () => {
|
|
12
|
+
if (unauthenticatedUrl) {
|
|
13
|
+
redirect(unauthenticatedUrl);
|
|
14
|
+
}
|
|
15
|
+
if (isPageRequest(request)) {
|
|
16
|
+
return redirectToSignIn();
|
|
17
|
+
}
|
|
18
|
+
return notFound();
|
|
19
|
+
};
|
|
20
|
+
const handleUnauthorized = () => {
|
|
21
|
+
if (unauthorizedUrl) {
|
|
22
|
+
redirect(unauthorizedUrl);
|
|
23
|
+
}
|
|
24
|
+
notFound();
|
|
25
|
+
};
|
|
26
|
+
if (!authObject.userId) {
|
|
27
|
+
handleUnauthenticated();
|
|
28
|
+
}
|
|
29
|
+
if (!paramsOrFunction) {
|
|
30
|
+
return authObject;
|
|
31
|
+
}
|
|
32
|
+
if (typeof paramsOrFunction === "function") {
|
|
33
|
+
if (paramsOrFunction(authObject.require)) {
|
|
34
|
+
return authObject;
|
|
35
|
+
}
|
|
36
|
+
return handleUnauthorized();
|
|
37
|
+
}
|
|
38
|
+
if (authObject.require(paramsOrFunction)) {
|
|
39
|
+
return authObject;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const isServerActionRequest = (req) => {
|
|
44
|
+
return !!req.headers.get(nextConstants.Headers.NextUrl) && (req.headers.get(constants.Headers.Accept)?.includes("text/x-component") || req.headers.get(constants.Headers.ContentType)?.includes("multipart/form-data") || !!req.headers.get(nextConstants.Headers.NextAction));
|
|
45
|
+
};
|
|
46
|
+
const isPageRequest = (req) => {
|
|
47
|
+
return req.headers.get(constants.Headers.SecFetchDest) === "document" || req.headers.get(constants.Headers.SecFetchDest) === "iframe" || req.headers.get(constants.Headers.Accept)?.includes("text/html") || isAppRouterInternalNavigation(req) || isPagesRouterInternalNavigation(req);
|
|
48
|
+
};
|
|
49
|
+
const isAppRouterInternalNavigation = (req) => !!req.headers.get(nextConstants.Headers.NextUrl) && !isServerActionRequest(req) || isPagePathAvailable();
|
|
50
|
+
const isPagePathAvailable = () => {
|
|
51
|
+
const __fetch = globalThis.fetch;
|
|
52
|
+
if (!isNextFetcher(__fetch)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
const { page, pagePath } = __fetch.__nextGetStaticStore().getStore() || {};
|
|
56
|
+
return Boolean(
|
|
57
|
+
// available on next@14
|
|
58
|
+
pagePath || // available on next@15
|
|
59
|
+
page
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
const isPagesRouterInternalNavigation = (req) => !!req.headers.get(nextConstants.Headers.NextjsData);
|
|
63
|
+
export {
|
|
64
|
+
createProtect
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=protect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/protect.ts"],"sourcesContent":["import type { AuthObject, SignedInAuthObject } from \"@tern-secure/backend\";\nimport { constants } from \"@tern-secure/backend\";\nimport type { CheckAuthorizationFromSessionClaims } from \"@tern-secure/types\";\n\nimport { constants as nextConstants } from \"../constants\";\nimport { isNextFetcher } from \"./nextFetcher\";\nimport type { RedirectFun } from \"./redirect\";\n\ntype AuthProtectOptions = {\n /**\n * The URL to redirect the user to if they are not authorized.\n */\n unauthorizedUrl?: string;\n /**\n * The URL to redirect the user to if they are not authenticated.\n */\n unauthenticatedUrl?: string;\n};\n\nexport interface AuthProtect {\n (\n params?: (require: CheckAuthorizationFromSessionClaims) => boolean,\n options?: AuthProtectOptions\n ): Promise<SignedInAuthObject>;\n (options?: AuthProtectOptions): Promise<SignedInAuthObject>;\n}\n\nexport function createProtect(opts: {\n request: Request;\n authObject: AuthObject;\n notFound: () => never;\n redirect: (url: string) => void;\n redirectToSignIn: RedirectFun<unknown>;\n}): AuthProtect {\n const { redirectToSignIn, authObject, redirect, notFound, request } = opts;\n\n return (async (...args: any[]) => {\n const optionValuesAsParam =\n args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;\n const paramsOrFunction = optionValuesAsParam ? undefined : (args[0] as \n | CheckAuthorizationFromSessionClaims\n | ((require: CheckAuthorizationFromSessionClaims) => boolean));\n const unauthenticatedUrl = (args[0]?.unauthenticatedUrl ||\n args[1]?.unauthenticatedUrl) as string | undefined;\n const unauthorizedUrl = (args[0]?.unauthorizedUrl ||\n args[1]?.unauthorizedUrl) as string | undefined;\n\n const handleUnauthenticated = () => {\n if (unauthenticatedUrl) {\n redirect(unauthenticatedUrl);\n }\n if (isPageRequest(request)) {\n return redirectToSignIn();\n }\n return notFound();\n };\n\n const handleUnauthorized = () => {\n if (unauthorizedUrl) {\n redirect(unauthorizedUrl);\n }\n notFound();\n };\n\n if (!authObject.userId) {\n handleUnauthenticated();\n }\n\n if (!paramsOrFunction) {\n return authObject;\n }\n\n if (typeof paramsOrFunction === \"function\") {\n if (paramsOrFunction(authObject.require)) {\n return authObject;\n }\n return handleUnauthorized();\n }\n\n if (authObject.require(paramsOrFunction)) {\n return authObject;\n }\n }) as AuthProtect;\n}\n\nconst isServerActionRequest = (req: Request) => {\n return (\n !!req.headers.get(nextConstants.Headers.NextUrl) &&\n (req.headers.get(constants.Headers.Accept)?.includes(\"text/x-component\") ||\n req.headers\n .get(constants.Headers.ContentType)\n ?.includes(\"multipart/form-data\") ||\n !!req.headers.get(nextConstants.Headers.NextAction))\n );\n};\n\nconst isPageRequest = (req: Request): boolean => {\n return (\n req.headers.get(constants.Headers.SecFetchDest) === \"document\" ||\n req.headers.get(constants.Headers.SecFetchDest) === \"iframe\" ||\n req.headers.get(constants.Headers.Accept)?.includes(\"text/html\") ||\n isAppRouterInternalNavigation(req) ||\n isPagesRouterInternalNavigation(req)\n );\n};\n\nconst isAppRouterInternalNavigation = (req: Request) =>\n (!!req.headers.get(nextConstants.Headers.NextUrl) &&\n !isServerActionRequest(req)) ||\n isPagePathAvailable();\n\nconst isPagePathAvailable = () => {\n const __fetch = globalThis.fetch;\n\n if (!isNextFetcher(__fetch)) {\n return false;\n }\n\n const { page, pagePath } = __fetch.__nextGetStaticStore().getStore() || {};\n\n return Boolean(\n // available on next@14\n pagePath ||\n // available on next@15\n page\n );\n};\n\nconst isPagesRouterInternalNavigation = (req: Request) =>\n !!req.headers.get(nextConstants.Headers.NextjsData);\n"],"mappings":"AACA,SAAS,iBAAiB;AAG1B,SAAS,aAAa,qBAAqB;AAC3C,SAAS,qBAAqB;AAsBvB,SAAS,cAAc,MAMd;AACd,QAAM,EAAE,kBAAkB,YAAY,UAAU,UAAU,QAAQ,IAAI;AAEtE,SAAQ,UAAU,SAAgB;AAChC,UAAM,sBACJ,KAAK,CAAC,GAAG,sBAAsB,KAAK,CAAC,GAAG;AAC1C,UAAM,mBAAmB,sBAAsB,SAAa,KAAK,CAAC;AAGlE,UAAM,qBAAsB,KAAK,CAAC,GAAG,sBACnC,KAAK,CAAC,GAAG;AACX,UAAM,kBAAmB,KAAK,CAAC,GAAG,mBAChC,KAAK,CAAC,GAAG;AAEX,UAAM,wBAAwB,MAAM;AAClC,UAAI,oBAAoB;AACtB,iBAAS,kBAAkB;AAAA,MAC7B;AACA,UAAI,cAAc,OAAO,GAAG;AAC1B,eAAO,iBAAiB;AAAA,MAC1B;AACA,aAAO,SAAS;AAAA,IAClB;AAEA,UAAM,qBAAqB,MAAM;AAC/B,UAAI,iBAAiB;AACnB,iBAAS,eAAe;AAAA,MAC1B;AACA,eAAS;AAAA,IACX;AAEA,QAAI,CAAC,WAAW,QAAQ;AACtB,4BAAsB;AAAA,IACxB;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,qBAAqB,YAAY;AAC1C,UAAI,iBAAiB,WAAW,OAAO,GAAG;AACxC,eAAO;AAAA,MACT;AACA,aAAO,mBAAmB;AAAA,IAC5B;AAEA,QAAI,WAAW,QAAQ,gBAAgB,GAAG;AACxC,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,wBAAwB,CAAC,QAAiB;AAC9C,SACE,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,OAAO,MAC9C,IAAI,QAAQ,IAAI,UAAU,QAAQ,MAAM,GAAG,SAAS,kBAAkB,KACrE,IAAI,QACD,IAAI,UAAU,QAAQ,WAAW,GAChC,SAAS,qBAAqB,KAClC,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,UAAU;AAExD;AAEA,MAAM,gBAAgB,CAAC,QAA0B;AAC/C,SACE,IAAI,QAAQ,IAAI,UAAU,QAAQ,YAAY,MAAM,cACpD,IAAI,QAAQ,IAAI,UAAU,QAAQ,YAAY,MAAM,YACpD,IAAI,QAAQ,IAAI,UAAU,QAAQ,MAAM,GAAG,SAAS,WAAW,KAC/D,8BAA8B,GAAG,KACjC,gCAAgC,GAAG;AAEvC;AAEA,MAAM,gCAAgC,CAAC,QACpC,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,OAAO,KAC9C,CAAC,sBAAsB,GAAG,KAC5B,oBAAoB;AAEtB,MAAM,sBAAsB,MAAM;AAChC,QAAM,UAAU,WAAW;AAE3B,MAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,MAAM,SAAS,IAAI,QAAQ,qBAAqB,EAAE,SAAS,KAAK,CAAC;AAEzE,SAAO;AAAA;AAAA,IAEL;AAAA,IAEE;AAAA,EACJ;AACF;AAEA,MAAM,kCAAkC,CAAC,QACvC,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,UAAU;","names":[]}
|