@tern-secure/nextjs 5.1.8 → 5.1.10
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/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/index.d.ts +0 -2
- package/dist/types/app-router/admin/index.d.ts.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/TernSecureProvider.d.ts +0 -25
- package/dist/types/app-router/client/TernSecureProvider.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/app-router/route-handler/internal-route.d.ts +0 -2
- package/dist/types/app-router/route-handler/internal-route.d.ts.map +0 -1
- package/dist/types/boundary/components.d.ts +0 -2
- package/dist/types/boundary/components.d.ts.map +0 -1
- package/dist/types/boundary/hooks.d.ts +0 -2
- package/dist/types/boundary/hooks.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/errors.d.ts +0 -44
- package/dist/types/errors.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -5
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/server/auth.d.ts +0 -23
- package/dist/types/server/auth.d.ts.map +0 -1
- package/dist/types/server/crypto.d.ts +0 -3
- package/dist/types/server/crypto.d.ts.map +0 -1
- package/dist/types/server/ctx-store.d.ts +0 -24
- package/dist/types/server/ctx-store.d.ts.map +0 -1
- package/dist/types/server/edge-session.d.ts +0 -4
- package/dist/types/server/edge-session.d.ts.map +0 -1
- package/dist/types/server/index.d.ts +0 -4
- package/dist/types/server/index.d.ts.map +0 -1
- package/dist/types/server/jwt-edge.d.ts +0 -20
- package/dist/types/server/jwt-edge.d.ts.map +0 -1
- package/dist/types/server/jwt.d.ts +0 -20
- package/dist/types/server/jwt.d.ts.map +0 -1
- package/dist/types/server/session-store.d.ts +0 -30
- package/dist/types/server/session-store.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/server/types.d.ts +0 -26
- package/dist/types/server/types.d.ts.map +0 -1
- package/dist/types/server/utils.d.ts +0 -22
- package/dist/types/server/utils.d.ts.map +0 -1
- package/dist/types/types.d.ts +0 -112
- package/dist/types/types.d.ts.map +0 -1
- package/dist/types/utils/admin-init.d.ts +0 -2
- package/dist/types/utils/admin-init.d.ts.map +0 -1
- package/dist/types/utils/allNextProviderProps.d.ts +0 -6
- package/dist/types/utils/allNextProviderProps.d.ts.map +0 -1
- package/dist/types/utils/client-init.d.ts +0 -2
- package/dist/types/utils/client-init.d.ts.map +0 -1
- package/dist/types/utils/config.d.ts +0 -35
- package/dist/types/utils/config.d.ts.map +0 -1
- package/dist/types/utils/construct.d.ts +0 -38
- package/dist/types/utils/construct.d.ts.map +0 -1
- package/dist/types/utils/create-styles.d.ts +0 -99
- package/dist/types/utils/create-styles.d.ts.map +0 -1
- package/dist/types/utils/redirect.d.ts +0 -9
- package/dist/types/utils/redirect.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
- package/dist/types/utils/ternsecure-sw.d.ts +0 -8
- package/dist/types/utils/ternsecure-sw.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/boundary/components.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/boundary/components.ts"],"sourcesContent":["export { \n useAuth,\n useIdToken,\n useSession,\n useSignIn,\n signIn,\n} from '@tern-secure/react' "],"mappings":"AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const Headers = {
|
|
2
|
+
NextRewrite: "x-middleware-rewrite",
|
|
3
|
+
NextResume: "x-middleware-next",
|
|
4
|
+
NextRedirect: "Location",
|
|
5
|
+
// Used by next to identify internal navigation for app router
|
|
6
|
+
NextUrl: "next-url",
|
|
7
|
+
NextAction: "next-action",
|
|
8
|
+
// Used by next to identify internal navigation for pages router
|
|
9
|
+
NextjsData: "x-nextjs-data"
|
|
10
|
+
};
|
|
11
|
+
const constants = {
|
|
12
|
+
Headers
|
|
13
|
+
};
|
|
14
|
+
export {
|
|
15
|
+
constants
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/constants.ts"],"sourcesContent":["const Headers = {\n NextRewrite: 'x-middleware-rewrite',\n NextResume: 'x-middleware-next',\n NextRedirect: 'Location',\n // Used by next to identify internal navigation for app router\n NextUrl: 'next-url',\n NextAction: 'next-action',\n // Used by next to identify internal navigation for pages router\n NextjsData: 'x-nextjs-data',\n} as const;\n\nexport const constants = {\n Headers,\n} as const;\n"],"mappings":"AAAA,MAAM,UAAU;AAAA,EACd,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,cAAc;AAAA;AAAA,EAEd,SAAS;AAAA,EACT,YAAY;AAAA;AAAA,EAEZ,YAAY;AACd;AAEO,MAAM,YAAY;AAAA,EACvB;AACF;","names":[]}
|
package/dist/esm/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/errors.ts"],"sourcesContent":["import { SignInResponse } from \"@tern-secure/types\"\r\n\r\nexport type ErrorCode = keyof typeof ERRORS\r\n\r\nexport interface AuthErrorResponse {\r\n success: false\r\n message: string\r\n code: ErrorCode\r\n}\r\n\r\nexport const ERRORS = {\r\n SERVER_SIDE_INITIALIZATION: \"TernSecure must be initialized on the client side\",\r\n REQUIRES_VERIFICATION: \"AUTH_REQUIRES_VERIFICATION\",\r\n AUTHENTICATED: \"AUTHENTICATED\",\r\n UNAUTHENTICATED: \"UNAUTHENTICATED\",\r\n UNVERIFIED: \"UNVERIFIED\",\r\n NOT_INITIALIZED: \"TernSecure services are not initialized. Call initializeTernSecure() first\",\r\n HOOK_CONTEXT: \"Hook must be used within TernSecureProvider\",\r\n EMAIL_NOT_VERIFIED: \"EMAIL_NOT_VERIFIED\",\r\n INVALID_CREDENTIALS: \"INVALID_CREDENTIALS\",\r\n USER_DISABLED: \"USER_DISABLED\",\r\n TOO_MANY_ATTEMPTS: \"TOO_MANY_ATTEMPTS\",\r\n NETWORK_ERROR: \"NETWORK_ERROR\",\r\n INVALID_EMAIL: \"INVALID_EMAIL\",\r\n WEAK_PASSWORD: \"WEAK_PASSWORD\",\r\n EMAIL_EXISTS: \"EMAIL_EXISTS\",\r\n POPUP_BLOCKED: \"POPUP_BLOCKED\",\r\n OPERATION_NOT_ALLOWED: \"OPERATION_NOT_ALLOWED\",\r\n EXPIRED_TOKEN: \"EXPIRED_TOKEN\",\r\n INVALID_TOKEN: \"INVALID_TOKEN\",\r\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\r\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\r\n} as const\r\n\r\n// Firebase Auth Error Code patterns\r\nconst ERROR_PATTERNS = {\r\n INVALID_EMAIL: /auth.*invalid.*email|invalid.*email.*auth|Firebase:.*Error.*auth\\/invalid-email/i,\r\n INVALID_CREDENTIALS:\r\n /auth.*invalid.*credential|invalid.*password|wrong.*password|Firebase:.*Error.*auth\\/(invalid-credential|wrong-password|user-not-found)/i,\r\n USER_DISABLED: /user.*disabled|disabled.*user|Firebase:.*Error.*auth\\/user-disabled/i,\r\n TOO_MANY_ATTEMPTS: /too.*many.*attempts|too.*many.*requests|Firebase:.*Error.*auth\\/too-many-requests/i,\r\n NETWORK_ERROR: /network.*request.*failed|failed.*network|Firebase:.*Error.*auth\\/network-request-failed/i,\r\n OPERATION_NOT_ALLOWED: /operation.*not.*allowed|method.*not.*allowed|Firebase:.*Error.*auth\\/operation-not-allowed/i,\r\n POPUP_BLOCKED: /popup.*blocked|blocked.*popup|Firebase:.*Error.*auth\\/popup-blocked/i,\r\n EMAIL_EXISTS: /email.*exists|email.*already.*use|Firebase:.*Error.*auth\\/email-already-in-use/i,\r\n EXPIRED_TOKEN: /token.*expired|expired.*token|Firebase:.*Error.*auth\\/expired-token/i,\r\n INVALID_TOKEN: /invalid.*token|token.*invalid|Firebase:.*Error.*auth\\/invalid-token/i,\r\n SESSION_EXPIRED: /session.*expired|expired.*session|Firebase:.*Error.*auth\\/session-expired/i,\r\n WEAK_PASSWORD: /weak.*password|password.*weak|Firebase:.*Error.*auth\\/weak-password/i,\r\n} as const\r\n\r\nexport class TernSecureError extends Error {\r\n code: ErrorCode\r\n\r\n constructor(code: ErrorCode, message?: string) {\r\n super(message || code)\r\n this.name = \"TernSecureError\"\r\n this.code = code\r\n }\r\n}\r\n\r\ninterface SerializedFirebaseError {\r\n name?: string\r\n code?: string\r\n message?: string\r\n stack?: string\r\n}\r\n\r\n/**\r\n * Determines if an object matches the shape of a Firebase Error\r\n */\r\nfunction isFirebaseErrorLike(error: unknown): error is SerializedFirebaseError {\r\n if (!error || typeof error !== \"object\") return false\r\n\r\n const err = error as SerializedFirebaseError\r\n\r\n // Check for bundled Firebase error format: \"Firebase: Error (auth/error-code)\"\r\n if (typeof err.message === \"string\") {\r\n const bundledErrorMatch = err.message.match(/Firebase:\\s*Error\\s*$$auth\\/([^)]+)$$/)\r\n if (bundledErrorMatch) {\r\n // Add the extracted code to the error object\r\n err.code = `auth/${bundledErrorMatch[1]}`\r\n return true\r\n }\r\n }\r\n\r\n return (\r\n (typeof err.code === \"string\" && err.code.startsWith(\"auth/\")) ||\r\n (typeof err.name === \"string\" && err.name.includes(\"FirebaseError\"))\r\n )\r\n}\r\n\r\n/**\r\n * Extracts the error code from a Firebase-like error object\r\n */\r\nfunction extractFirebaseErrorCode(error: SerializedFirebaseError): string {\r\n // First try to extract from bundled error message format\r\n if (typeof error.message === \"string\") {\r\n const bundledErrorMatch = error.message.match(/Firebase:\\s*Error\\s*$$auth\\/([^)]+)$$/)\r\n if (bundledErrorMatch) {\r\n return bundledErrorMatch[1]\r\n }\r\n }\r\n\r\n // Then try the standard code property\r\n if (error.code) {\r\n return error.code.replace(\"auth/\", \"\")\r\n }\r\n\r\n // Finally try to extract from error message if it contains an error code\r\n if (typeof error.message === \"string\") {\r\n const messageCodeMatch = error.message.match(/auth\\/([a-z-]+)/)\r\n if (messageCodeMatch) {\r\n return messageCodeMatch[1]\r\n }\r\n }\r\n\r\n return \"\"\r\n}\r\n\r\n/**\r\n * Maps a Firebase error code to our internal error code\r\n */\r\nfunction mapFirebaseErrorCode(code: string): ErrorCode {\r\n // Direct mapping for known error codes\r\n const directMappings: Record<string, ErrorCode> = {\r\n \"invalid-email\": \"INVALID_EMAIL\",\r\n \"user-disabled\": \"USER_DISABLED\",\r\n \"too-many-requests\": \"TOO_MANY_ATTEMPTS\",\r\n \"network-request-failed\": \"NETWORK_ERROR\",\r\n \"operation-not-allowed\": \"OPERATION_NOT_ALLOWED\",\r\n \"popup-blocked\": \"POPUP_BLOCKED\",\r\n \"email-already-in-use\": \"EMAIL_EXISTS\",\r\n \"weak-password\": \"WEAK_PASSWORD\",\r\n \"invalid-credential\": \"INVALID_CREDENTIALS\",\r\n \"wrong-password\": \"INVALID_CREDENTIALS\",\r\n \"user-not-found\": \"INVALID_CREDENTIALS\",\r\n \"invalid-password\": \"INVALID_CREDENTIALS\",\r\n \"user-token-expired\": \"EXPIRED_TOKEN\",\r\n \"invalid-id-token\": \"INVALID_TOKEN\",\r\n }\r\n\r\n return directMappings[code] || \"INTERNAL_ERROR\"\r\n}\r\n\r\n/**\r\n * Determines error type based on error message pattern matching\r\n */\r\nfunction determineErrorTypeFromMessage(message: string): ErrorCode {\r\n // First check for bundled Firebase error format\r\n const bundledErrorMatch = message.match(/Firebase:\\s*Error\\s*$$auth\\/([^)]+)$$/)\r\n if (bundledErrorMatch) {\r\n const errorCode = bundledErrorMatch[1]\r\n const mappedCode = mapFirebaseErrorCode(errorCode)\r\n if (mappedCode) {\r\n return mappedCode\r\n }\r\n }\r\n\r\n // Then check standard patterns\r\n for (const [errorType, pattern] of Object.entries(ERROR_PATTERNS)) {\r\n if (pattern.test(message)) {\r\n return errorType as ErrorCode\r\n }\r\n }\r\n\r\n return \"INTERNAL_ERROR\"\r\n}\r\n\r\n/**\r\n * Creates a standardized error response\r\n */\r\nfunction createErrorResponse(code: ErrorCode, message: string): AuthErrorResponse {\r\n const defaultMessages: Record<ErrorCode, string> = {\r\n INVALID_EMAIL: \"Invalid email format\",\r\n INVALID_CREDENTIALS: \"Invalid email or password\",\r\n USER_DISABLED: \"This account has been disabled\",\r\n TOO_MANY_ATTEMPTS: \"Too many attempts. Please try again later\",\r\n NETWORK_ERROR: \"Network error. Please check your connection\",\r\n OPERATION_NOT_ALLOWED: \"This login method is not enabled\",\r\n POPUP_BLOCKED: \"Login popup was blocked. Please enable popups\",\r\n EMAIL_EXISTS: \"This email is already in use\",\r\n EXPIRED_TOKEN: \"Your session has expired. Please login again\",\r\n INVALID_TOKEN: \"Invalid authentication token\",\r\n SESSION_EXPIRED: \"Your session has expired\",\r\n WEAK_PASSWORD: \"Password is too weak\",\r\n EMAIL_NOT_VERIFIED: \"Email verification required\",\r\n INTERNAL_ERROR: \"An internal error occurred. Please try again\",\r\n SERVER_SIDE_INITIALIZATION: \"TernSecure must be initialized on the client side\",\r\n REQUIRES_VERIFICATION: \"Email verification required\",\r\n AUTHENTICATED: \"Already authenticated\",\r\n UNAUTHENTICATED: \"Authentication required\",\r\n UNVERIFIED: \"Email verification required\",\r\n NOT_INITIALIZED: \"TernSecure services are not initialized\",\r\n HOOK_CONTEXT: \"Hook must be used within TernSecureProvider\",\r\n }\r\n\r\n return {\r\n success: false,\r\n message: message || defaultMessages[code],\r\n code,\r\n }\r\n}\r\n\r\n/**\r\n * Handles Firebase authentication errors with multiple fallback mechanisms\r\n */\r\nexport function handleFirebaseAuthError(error: unknown): AuthErrorResponse {\r\n // Helper to extract clean error code from bundled format\r\n function extractErrorInfo(input: unknown): { code: string; message: string } | null {\r\n // Case 1: String input (direct Firebase error message)\r\n if (typeof input === 'string') {\r\n const match = input.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\r\n if (match) {\r\n return { code: match[1], message: input };\r\n }\r\n }\r\n\r\n // Case 2: Error object\r\n if (input && typeof input === 'object') {\r\n const err = input as { code?: string; message?: string };\r\n \r\n // Check for bundled message format first\r\n if (err.message) {\r\n const match = err.message.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\r\n if (match) {\r\n return { code: match[1], message: err.message };\r\n }\r\n }\r\n\r\n // Check for direct code\r\n if (err.code) {\r\n return {\r\n code: err.code.replace('auth/', ''),\r\n message: err.message || ''\r\n };\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // Map error codes to user-friendly messages\r\n const ERROR_MESSAGES: Record<string, { message: string; code: ErrorCode }> = {\r\n 'invalid-email': { message: 'Invalid email format', code: 'INVALID_EMAIL' },\r\n 'invalid-credential': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'invalid-login-credentials': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'wrong-password': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'user-not-found': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'user-disabled': { message: 'This account has been disabled', code: 'USER_DISABLED' },\r\n 'too-many-requests': { message: 'Too many attempts. Please try again later', code: 'TOO_MANY_ATTEMPTS' },\r\n 'network-request-failed': { message: 'Network error. Please check your connection', code: 'NETWORK_ERROR' },\r\n 'email-already-in-use': { message: 'This email is already in use', code: 'EMAIL_EXISTS' },\r\n 'weak-password': { message: 'Password is too weak', code: 'WEAK_PASSWORD' },\r\n 'operation-not-allowed': { message: 'This login method is not enabled', code: 'OPERATION_NOT_ALLOWED' },\r\n 'popup-blocked': { message: 'Login popup was blocked. Please enable popups', code: 'POPUP_BLOCKED' },\r\n 'expired-action-code': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' },\r\n 'user-token-expired': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' }\r\n };\r\n\r\n try {\r\n // Extract error information\r\n const errorInfo = extractErrorInfo(error);\r\n \r\n if (errorInfo) {\r\n const mappedError = ERROR_MESSAGES[errorInfo.code];\r\n if (mappedError) {\r\n return {\r\n success: false,\r\n message: mappedError.message,\r\n code: mappedError.code\r\n };\r\n }\r\n }\r\n\r\n // If we couldn't extract or map the error, try one last time with string conversion\r\n const errorString = String(error);\r\n const lastMatch = errorString.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\r\n if (lastMatch && ERROR_MESSAGES[lastMatch[1]]) {\r\n return {\r\n success: false,\r\n ...ERROR_MESSAGES[lastMatch[1]]\r\n };\r\n }\r\n\r\n } catch (e) {\r\n // Silent catch - we'll return the default error\r\n }\r\n\r\n // Default fallback\r\n return {\r\n success: false,\r\n message: 'An unexpected error occurred. Please try again later',\r\n code: 'INTERNAL_ERROR'\r\n };\r\n}\r\n\r\n/**\r\n * Type guard to check if a response is an AuthErrorResponse\r\n */\r\nexport function isAuthErrorResponse(response: unknown): response is AuthErrorResponse {\r\n return (\r\n typeof response === \"object\" &&\r\n response !== null &&\r\n \"success\" in response &&\r\n (response as { success: boolean }).success === false &&\r\n \"code\" in response &&\r\n \"message\" in response\r\n )\r\n}\r\n\r\n\r\n\r\nexport function getErrorAlertVariant(error: SignInResponse | undefined) {\r\n if (!error) return \"destructive\"\r\n\r\n switch (error.error) {\r\n case \"AUTHENTICATED\":\r\n return \"default\"\r\n case \"EMAIL_EXISTS\":\r\n case \"UNAUTHENTICATED\":\r\n case \"UNVERIFIED\":\r\n case \"REQUIRES_VERIFICATION\":\r\n case \"INVALID_EMAIL\":\r\n case \"INVALID_TOKEN\":\r\n case \"INTERNAL_ERROR\":\r\n case \"USER_DISABLED\":\r\n case \"TOO_MANY_ATTEMPTS\":\r\n case \"NETWORK_ERROR\":\r\n case \"SESSION_EXPIRED\":\r\n case \"EXPIRED_TOKEN\":\r\n case \"INVALID_CREDENTIALS\":\r\n default:\r\n return \"destructive\"\r\n }\r\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/errors.ts"],"sourcesContent":["import type { SignInResponse } from \"@tern-secure/types\"\r\n\r\nexport type ErrorCode = keyof typeof ERRORS\r\n\r\nexport interface AuthErrorResponse {\r\n success: false\r\n message: string\r\n code: ErrorCode\r\n}\r\n\r\nexport const ERRORS = {\r\n SERVER_SIDE_INITIALIZATION: \"TernSecure must be initialized on the client side\",\r\n REQUIRES_VERIFICATION: \"AUTH_REQUIRES_VERIFICATION\",\r\n AUTHENTICATED: \"AUTHENTICATED\",\r\n UNAUTHENTICATED: \"UNAUTHENTICATED\",\r\n UNVERIFIED: \"UNVERIFIED\",\r\n NOT_INITIALIZED: \"TernSecure services are not initialized. Call initializeTernSecure() first\",\r\n HOOK_CONTEXT: \"Hook must be used within TernSecureProvider\",\r\n EMAIL_NOT_VERIFIED: \"EMAIL_NOT_VERIFIED\",\r\n INVALID_CREDENTIALS: \"INVALID_CREDENTIALS\",\r\n USER_DISABLED: \"USER_DISABLED\",\r\n TOO_MANY_ATTEMPTS: \"TOO_MANY_ATTEMPTS\",\r\n NETWORK_ERROR: \"NETWORK_ERROR\",\r\n INVALID_EMAIL: \"INVALID_EMAIL\",\r\n WEAK_PASSWORD: \"WEAK_PASSWORD\",\r\n EMAIL_EXISTS: \"EMAIL_EXISTS\",\r\n POPUP_BLOCKED: \"POPUP_BLOCKED\",\r\n OPERATION_NOT_ALLOWED: \"OPERATION_NOT_ALLOWED\",\r\n EXPIRED_TOKEN: \"EXPIRED_TOKEN\",\r\n INVALID_TOKEN: \"INVALID_TOKEN\",\r\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\r\n INTERNAL_ERROR: \"INTERNAL_ERROR\",\r\n} as const\r\n\r\n// Firebase Auth Error Code patterns\r\nconst ERROR_PATTERNS = {\r\n INVALID_EMAIL: /auth.*invalid.*email|invalid.*email.*auth|Firebase:.*Error.*auth\\/invalid-email/i,\r\n INVALID_CREDENTIALS:\r\n /auth.*invalid.*credential|invalid.*password|wrong.*password|Firebase:.*Error.*auth\\/(invalid-credential|wrong-password|user-not-found)/i,\r\n USER_DISABLED: /user.*disabled|disabled.*user|Firebase:.*Error.*auth\\/user-disabled/i,\r\n TOO_MANY_ATTEMPTS: /too.*many.*attempts|too.*many.*requests|Firebase:.*Error.*auth\\/too-many-requests/i,\r\n NETWORK_ERROR: /network.*request.*failed|failed.*network|Firebase:.*Error.*auth\\/network-request-failed/i,\r\n OPERATION_NOT_ALLOWED: /operation.*not.*allowed|method.*not.*allowed|Firebase:.*Error.*auth\\/operation-not-allowed/i,\r\n POPUP_BLOCKED: /popup.*blocked|blocked.*popup|Firebase:.*Error.*auth\\/popup-blocked/i,\r\n EMAIL_EXISTS: /email.*exists|email.*already.*use|Firebase:.*Error.*auth\\/email-already-in-use/i,\r\n EXPIRED_TOKEN: /token.*expired|expired.*token|Firebase:.*Error.*auth\\/expired-token/i,\r\n INVALID_TOKEN: /invalid.*token|token.*invalid|Firebase:.*Error.*auth\\/invalid-token/i,\r\n SESSION_EXPIRED: /session.*expired|expired.*session|Firebase:.*Error.*auth\\/session-expired/i,\r\n WEAK_PASSWORD: /weak.*password|password.*weak|Firebase:.*Error.*auth\\/weak-password/i,\r\n} as const\r\n\r\nexport class TernSecureError extends Error {\r\n code: ErrorCode\r\n\r\n constructor(code: ErrorCode, message?: string) {\r\n super(message || code)\r\n this.name = \"TernSecureError\"\r\n this.code = code\r\n }\r\n}\r\n\r\ninterface SerializedFirebaseError {\r\n name?: string\r\n code?: string\r\n message?: string\r\n stack?: string\r\n}\r\n\r\n/**\r\n * Determines if an object matches the shape of a Firebase Error\r\n */\r\nfunction isFirebaseErrorLike(error: unknown): error is SerializedFirebaseError {\r\n if (!error || typeof error !== \"object\") return false\r\n\r\n const err = error as SerializedFirebaseError\r\n\r\n // Check for bundled Firebase error format: \"Firebase: Error (auth/error-code)\"\r\n if (typeof err.message === \"string\") {\r\n const bundledErrorMatch = err.message.match(/Firebase:\\s*Error\\s*$$auth\\/([^)]+)$$/)\r\n if (bundledErrorMatch) {\r\n // Add the extracted code to the error object\r\n err.code = `auth/${bundledErrorMatch[1]}`\r\n return true\r\n }\r\n }\r\n\r\n return (\r\n (typeof err.code === \"string\" && err.code.startsWith(\"auth/\")) ||\r\n (typeof err.name === \"string\" && err.name.includes(\"FirebaseError\"))\r\n )\r\n}\r\n\r\n/**\r\n * Extracts the error code from a Firebase-like error object\r\n */\r\nfunction extractFirebaseErrorCode(error: SerializedFirebaseError): string {\r\n // First try to extract from bundled error message format\r\n if (typeof error.message === \"string\") {\r\n const bundledErrorMatch = error.message.match(/Firebase:\\s*Error\\s*$$auth\\/([^)]+)$$/)\r\n if (bundledErrorMatch) {\r\n return bundledErrorMatch[1]\r\n }\r\n }\r\n\r\n // Then try the standard code property\r\n if (error.code) {\r\n return error.code.replace(\"auth/\", \"\")\r\n }\r\n\r\n // Finally try to extract from error message if it contains an error code\r\n if (typeof error.message === \"string\") {\r\n const messageCodeMatch = error.message.match(/auth\\/([a-z-]+)/)\r\n if (messageCodeMatch) {\r\n return messageCodeMatch[1]\r\n }\r\n }\r\n\r\n return \"\"\r\n}\r\n\r\n/**\r\n * Maps a Firebase error code to our internal error code\r\n */\r\nfunction mapFirebaseErrorCode(code: string): ErrorCode {\r\n // Direct mapping for known error codes\r\n const directMappings: Record<string, ErrorCode> = {\r\n \"invalid-email\": \"INVALID_EMAIL\",\r\n \"user-disabled\": \"USER_DISABLED\",\r\n \"too-many-requests\": \"TOO_MANY_ATTEMPTS\",\r\n \"network-request-failed\": \"NETWORK_ERROR\",\r\n \"operation-not-allowed\": \"OPERATION_NOT_ALLOWED\",\r\n \"popup-blocked\": \"POPUP_BLOCKED\",\r\n \"email-already-in-use\": \"EMAIL_EXISTS\",\r\n \"weak-password\": \"WEAK_PASSWORD\",\r\n \"invalid-credential\": \"INVALID_CREDENTIALS\",\r\n \"wrong-password\": \"INVALID_CREDENTIALS\",\r\n \"user-not-found\": \"INVALID_CREDENTIALS\",\r\n \"invalid-password\": \"INVALID_CREDENTIALS\",\r\n \"user-token-expired\": \"EXPIRED_TOKEN\",\r\n \"invalid-id-token\": \"INVALID_TOKEN\",\r\n }\r\n\r\n return directMappings[code] || \"INTERNAL_ERROR\"\r\n}\r\n\r\n/**\r\n * Determines error type based on error message pattern matching\r\n */\r\nfunction determineErrorTypeFromMessage(message: string): ErrorCode {\r\n // First check for bundled Firebase error format\r\n const bundledErrorMatch = message.match(/Firebase:\\s*Error\\s*$$auth\\/([^)]+)$$/)\r\n if (bundledErrorMatch) {\r\n const errorCode = bundledErrorMatch[1]\r\n const mappedCode = mapFirebaseErrorCode(errorCode)\r\n if (mappedCode) {\r\n return mappedCode\r\n }\r\n }\r\n\r\n // Then check standard patterns\r\n for (const [errorType, pattern] of Object.entries(ERROR_PATTERNS)) {\r\n if (pattern.test(message)) {\r\n return errorType as ErrorCode\r\n }\r\n }\r\n\r\n return \"INTERNAL_ERROR\"\r\n}\r\n\r\n/**\r\n * Creates a standardized error response\r\n */\r\nfunction createErrorResponse(code: ErrorCode, message: string): AuthErrorResponse {\r\n const defaultMessages: Record<ErrorCode, string> = {\r\n INVALID_EMAIL: \"Invalid email format\",\r\n INVALID_CREDENTIALS: \"Invalid email or password\",\r\n USER_DISABLED: \"This account has been disabled\",\r\n TOO_MANY_ATTEMPTS: \"Too many attempts. Please try again later\",\r\n NETWORK_ERROR: \"Network error. Please check your connection\",\r\n OPERATION_NOT_ALLOWED: \"This login method is not enabled\",\r\n POPUP_BLOCKED: \"Login popup was blocked. Please enable popups\",\r\n EMAIL_EXISTS: \"This email is already in use\",\r\n EXPIRED_TOKEN: \"Your session has expired. Please login again\",\r\n INVALID_TOKEN: \"Invalid authentication token\",\r\n SESSION_EXPIRED: \"Your session has expired\",\r\n WEAK_PASSWORD: \"Password is too weak\",\r\n EMAIL_NOT_VERIFIED: \"Email verification required\",\r\n INTERNAL_ERROR: \"An internal error occurred. Please try again\",\r\n SERVER_SIDE_INITIALIZATION: \"TernSecure must be initialized on the client side\",\r\n REQUIRES_VERIFICATION: \"Email verification required\",\r\n AUTHENTICATED: \"Already authenticated\",\r\n UNAUTHENTICATED: \"Authentication required\",\r\n UNVERIFIED: \"Email verification required\",\r\n NOT_INITIALIZED: \"TernSecure services are not initialized\",\r\n HOOK_CONTEXT: \"Hook must be used within TernSecureProvider\",\r\n }\r\n\r\n return {\r\n success: false,\r\n message: message || defaultMessages[code],\r\n code,\r\n }\r\n}\r\n\r\n/**\r\n * Handles Firebase authentication errors with multiple fallback mechanisms\r\n */\r\nexport function handleFirebaseAuthError(error: unknown): AuthErrorResponse {\r\n // Helper to extract clean error code from bundled format\r\n function extractErrorInfo(input: unknown): { code: string; message: string } | null {\r\n // Case 1: String input (direct Firebase error message)\r\n if (typeof input === 'string') {\r\n const match = input.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\r\n if (match) {\r\n return { code: match[1], message: input };\r\n }\r\n }\r\n\r\n // Case 2: Error object\r\n if (input && typeof input === 'object') {\r\n const err = input as { code?: string; message?: string };\r\n \r\n // Check for bundled message format first\r\n if (err.message) {\r\n const match = err.message.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\r\n if (match) {\r\n return { code: match[1], message: err.message };\r\n }\r\n }\r\n\r\n // Check for direct code\r\n if (err.code) {\r\n return {\r\n code: err.code.replace('auth/', ''),\r\n message: err.message || ''\r\n };\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n // Map error codes to user-friendly messages\r\n const ERROR_MESSAGES: Record<string, { message: string; code: ErrorCode }> = {\r\n 'invalid-email': { message: 'Invalid email format', code: 'INVALID_EMAIL' },\r\n 'invalid-credential': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'invalid-login-credentials': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'wrong-password': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'user-not-found': { message: 'Invalid email or password', code: 'INVALID_CREDENTIALS' },\r\n 'user-disabled': { message: 'This account has been disabled', code: 'USER_DISABLED' },\r\n 'too-many-requests': { message: 'Too many attempts. Please try again later', code: 'TOO_MANY_ATTEMPTS' },\r\n 'network-request-failed': { message: 'Network error. Please check your connection', code: 'NETWORK_ERROR' },\r\n 'email-already-in-use': { message: 'This email is already in use', code: 'EMAIL_EXISTS' },\r\n 'weak-password': { message: 'Password is too weak', code: 'WEAK_PASSWORD' },\r\n 'operation-not-allowed': { message: 'This login method is not enabled', code: 'OPERATION_NOT_ALLOWED' },\r\n 'popup-blocked': { message: 'Login popup was blocked. Please enable popups', code: 'POPUP_BLOCKED' },\r\n 'expired-action-code': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' },\r\n 'user-token-expired': { message: 'Your session has expired. Please login again', code: 'EXPIRED_TOKEN' }\r\n };\r\n\r\n try {\r\n // Extract error information\r\n const errorInfo = extractErrorInfo(error);\r\n \r\n if (errorInfo) {\r\n const mappedError = ERROR_MESSAGES[errorInfo.code];\r\n if (mappedError) {\r\n return {\r\n success: false,\r\n message: mappedError.message,\r\n code: mappedError.code\r\n };\r\n }\r\n }\r\n\r\n // If we couldn't extract or map the error, try one last time with string conversion\r\n const errorString = String(error);\r\n const lastMatch = errorString.match(/Firebase:\\s*Error\\s*\\(auth\\/([^)]+)\\)/);\r\n if (lastMatch && ERROR_MESSAGES[lastMatch[1]]) {\r\n return {\r\n success: false,\r\n ...ERROR_MESSAGES[lastMatch[1]]\r\n };\r\n }\r\n\r\n } catch (e) {\r\n // Silent catch - we'll return the default error\r\n }\r\n\r\n // Default fallback\r\n return {\r\n success: false,\r\n message: 'An unexpected error occurred. Please try again later',\r\n code: 'INTERNAL_ERROR'\r\n };\r\n}\r\n\r\n/**\r\n * Type guard to check if a response is an AuthErrorResponse\r\n */\r\nexport function isAuthErrorResponse(response: unknown): response is AuthErrorResponse {\r\n return (\r\n typeof response === \"object\" &&\r\n response !== null &&\r\n \"success\" in response &&\r\n (response as { success: boolean }).success === false &&\r\n \"code\" in response &&\r\n \"message\" in response\r\n )\r\n}\r\n\r\n\r\n\r\nexport function getErrorAlertVariant(error: SignInResponse | undefined) {\r\n if (!error) return \"destructive\"\r\n\r\n switch (error.error) {\r\n case \"AUTHENTICATED\":\r\n return \"default\"\r\n case \"EMAIL_EXISTS\":\r\n case \"UNAUTHENTICATED\":\r\n case \"UNVERIFIED\":\r\n case \"REQUIRES_VERIFICATION\":\r\n case \"INVALID_EMAIL\":\r\n case \"INVALID_TOKEN\":\r\n case \"INTERNAL_ERROR\":\r\n case \"USER_DISABLED\":\r\n case \"TOO_MANY_ATTEMPTS\":\r\n case \"NETWORK_ERROR\":\r\n case \"SESSION_EXPIRED\":\r\n case \"EXPIRED_TOKEN\":\r\n case \"INVALID_CREDENTIALS\":\r\n default:\r\n return \"destructive\"\r\n }\r\n}"],"mappings":"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","names":[]}
|
package/dist/esm/index.js
CHANGED
|
@@ -2,22 +2,16 @@ import { TernSecureProvider } from "./app-router/client/TernSecureProvider";
|
|
|
2
2
|
import {
|
|
3
3
|
useAuth,
|
|
4
4
|
useIdToken,
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
useSession,
|
|
6
|
+
useSignIn,
|
|
7
|
+
signIn
|
|
7
8
|
} from "./boundary/components";
|
|
8
|
-
import {
|
|
9
|
-
SignIn,
|
|
10
|
-
SignUp,
|
|
11
|
-
UserButton
|
|
12
|
-
} from "./components/uiComponents";
|
|
13
9
|
export {
|
|
14
|
-
SignIn,
|
|
15
|
-
SignUp,
|
|
16
10
|
TernSecureProvider,
|
|
17
|
-
|
|
11
|
+
signIn,
|
|
18
12
|
useAuth,
|
|
19
13
|
useIdToken,
|
|
20
14
|
useSession,
|
|
21
|
-
|
|
15
|
+
useSignIn
|
|
22
16
|
};
|
|
23
17
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureProvider } from './app-router/client/TernSecureProvider'\r\nexport {\r\n useAuth,\r\n useIdToken,\r\n useSession,\r\n useSignIn,\r\n signIn\r\n //SignIn,\r\n //SignOut,\r\n //SignOutButton,\r\n //SignUp,\r\n} from './boundary/components'\r\n\r\nexport type { TernSecureUser, TernSecureUserData, SignInResponseTree } from '@tern-secure/types'\r\n\r\nexport type {\r\n UserInfo,\r\n SessionResult\r\n} from './types'"],"mappings":"AAAA,SAAS,0BAA0B;AACnC;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAKG;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const API_URL = process.env.TERNSECURE_API_URL;
|
|
2
|
+
const API_VERSION = process.env.TERNSECURE_API_VERSION || "v1";
|
|
3
|
+
const SIGN_IN_URL = process.env.NEXT_PUBLIC_SIGN_IN_URL || "";
|
|
4
|
+
const SIGN_UP_URL = process.env.NEXT_PUBLIC_SIGN_UP_URL || "";
|
|
5
|
+
export {
|
|
6
|
+
API_URL,
|
|
7
|
+
API_VERSION,
|
|
8
|
+
SIGN_IN_URL,
|
|
9
|
+
SIGN_UP_URL
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=constant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/constant.ts"],"sourcesContent":["\nexport const API_URL = process.env.TERNSECURE_API_URL\nexport const API_VERSION = process.env.TERNSECURE_API_VERSION || 'v1';\nexport const SIGN_IN_URL = process.env.NEXT_PUBLIC_SIGN_IN_URL || '';\nexport const SIGN_UP_URL = process.env.NEXT_PUBLIC_SIGN_UP_URL || '';"],"mappings":"AACO,MAAM,UAAU,QAAQ,IAAI;AAC5B,MAAM,cAAc,QAAQ,IAAI,0BAA0B;AAC1D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;AAC3D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;","names":[]}
|
|
@@ -1,39 +1,127 @@
|
|
|
1
|
-
import { verifyFirebaseToken } from "./jwt
|
|
1
|
+
import { verifyFirebaseToken } from "./jwt";
|
|
2
2
|
async function verifySession(request) {
|
|
3
3
|
try {
|
|
4
4
|
const sessionCookie = request.cookies.get("_session_cookie")?.value;
|
|
5
|
-
const idToken = request.cookies.get("_session_token")?.value;
|
|
6
5
|
if (sessionCookie) {
|
|
7
6
|
const result = await verifyFirebaseToken(sessionCookie, true);
|
|
8
7
|
if (result.valid) {
|
|
9
|
-
const user = {
|
|
10
|
-
uid: result.uid ?? "",
|
|
11
|
-
email: result.email || null,
|
|
12
|
-
emailVerified: result.emailVerified ?? false,
|
|
13
|
-
disabled: false,
|
|
14
|
-
authTime: result.authTime
|
|
15
|
-
};
|
|
16
8
|
return {
|
|
17
9
|
isAuthenticated: true,
|
|
18
|
-
user
|
|
10
|
+
user: {
|
|
11
|
+
uid: result.uid ?? "",
|
|
12
|
+
email: result.email || null,
|
|
13
|
+
tenantId: result.tenant || "default",
|
|
14
|
+
emailVerified: result.emailVerified ?? false,
|
|
15
|
+
disabled: false
|
|
16
|
+
}
|
|
19
17
|
};
|
|
20
18
|
}
|
|
21
19
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
20
|
+
return {
|
|
21
|
+
isAuthenticated: false,
|
|
22
|
+
user: null,
|
|
23
|
+
error: "No valid session found"
|
|
24
|
+
};
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error("Session verification error:", error);
|
|
27
|
+
return {
|
|
28
|
+
isAuthenticated: false,
|
|
29
|
+
user: null,
|
|
30
|
+
error: error instanceof Error ? error.message : "Session verification failed"
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function verifyTokenEdge(idToken) {
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(
|
|
37
|
+
`https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}`,
|
|
38
|
+
{
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: {
|
|
41
|
+
"Content-Type": "application/json"
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify({ idToken })
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
const data = await response.json();
|
|
47
|
+
console.log("data Token", data);
|
|
48
|
+
if (!response.ok || !data.users?.[0]) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const user = data.users[0];
|
|
52
|
+
return {
|
|
53
|
+
uid: user.localId,
|
|
54
|
+
email: user.email || null,
|
|
55
|
+
tenantId: user.tenantId || "default",
|
|
56
|
+
disabled: user.disabled || false
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error("Token verification error:", error);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function verifySessionEdge(sessionCookie) {
|
|
64
|
+
try {
|
|
65
|
+
const response = await fetch(
|
|
66
|
+
`https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}`,
|
|
67
|
+
{
|
|
68
|
+
method: "POST",
|
|
69
|
+
headers: {
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
Authorization: `Bearer ${sessionCookie}`
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
const data = await response.json();
|
|
76
|
+
console.log("data Session", data);
|
|
77
|
+
if (!response.ok || !data.users?.[0]) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
const user = data.users[0];
|
|
81
|
+
return {
|
|
82
|
+
uid: user.localId,
|
|
83
|
+
email: user.email || null,
|
|
84
|
+
tenantId: user.tenant || "default",
|
|
85
|
+
disabled: user.disabled || false
|
|
86
|
+
};
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error("Session verification error:", error);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function VerifySessionWithRestApi(request) {
|
|
93
|
+
try {
|
|
94
|
+
const sessionCookie = request.cookies.get("_session_cookie")?.value;
|
|
95
|
+
if (sessionCookie) {
|
|
96
|
+
const response = await fetch(
|
|
97
|
+
`https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${process.env.GOOGLE_CLIENT_ID}`,
|
|
98
|
+
{
|
|
99
|
+
method: "POST",
|
|
100
|
+
headers: {
|
|
101
|
+
"Content-Type": "application/json",
|
|
102
|
+
Authorization: `Bearer ${sessionCookie}`
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
const data = await response.json();
|
|
107
|
+
console.log("[edge-session] data with session cookie", data);
|
|
108
|
+
if (response.ok && data.users?.[0]) {
|
|
109
|
+
const user = data.users[0];
|
|
32
110
|
return {
|
|
33
111
|
isAuthenticated: true,
|
|
34
|
-
user
|
|
112
|
+
user: {
|
|
113
|
+
uid: user.localId,
|
|
114
|
+
email: user.email || null,
|
|
115
|
+
tenantId: user.tenantId || "default",
|
|
116
|
+
emailVerified: user.emailVerified ?? false,
|
|
117
|
+
disabled: user.disabled || false
|
|
118
|
+
}
|
|
35
119
|
};
|
|
36
120
|
}
|
|
121
|
+
console.log(
|
|
122
|
+
"Session cookie verification failed:",
|
|
123
|
+
data.error?.message || "Invalid session"
|
|
124
|
+
);
|
|
37
125
|
}
|
|
38
126
|
return {
|
|
39
127
|
isAuthenticated: false,
|
|
@@ -50,6 +138,9 @@ async function verifySession(request) {
|
|
|
50
138
|
}
|
|
51
139
|
}
|
|
52
140
|
export {
|
|
53
|
-
|
|
141
|
+
VerifySessionWithRestApi,
|
|
142
|
+
verifySession,
|
|
143
|
+
verifySessionEdge,
|
|
144
|
+
verifyTokenEdge
|
|
54
145
|
};
|
|
55
146
|
//# sourceMappingURL=edge-session.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/edge-session.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../src/server/edge-session.ts"],"sourcesContent":["import type { NextRequest } from \"next/server\";\r\n\r\nimport { verifyFirebaseToken } from \"./jwt\";\r\nimport type { BaseUser,SessionResult } from \"./types\";\r\n\r\nexport async function verifySession(\r\n request: NextRequest\r\n): Promise<SessionResult> {\r\n try {\r\n const sessionCookie = request.cookies.get(\"_session_cookie\")?.value;\r\n if (sessionCookie) {\r\n const result = await verifyFirebaseToken(sessionCookie, true);\r\n if (result.valid) {\r\n return {\r\n isAuthenticated: true,\r\n user: {\r\n uid: result.uid ?? \"\",\r\n email: result.email || null,\r\n tenantId: result.tenant || \"default\",\r\n emailVerified: result.emailVerified ?? false,\r\n disabled: false,\r\n },\r\n };\r\n }\r\n }\r\n return {\r\n isAuthenticated: false,\r\n user: null,\r\n error: \"No valid session found\",\r\n };\r\n } catch (error) {\r\n console.error(\"Session verification error:\", error);\r\n return {\r\n isAuthenticated: false,\r\n user: null,\r\n error:\r\n error instanceof Error ? error.message : \"Session verification failed\",\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Edge-compatible token verification using Firebase Auth REST API\r\n */\r\nexport async function verifyTokenEdge(\r\n idToken: string\r\n): Promise<BaseUser | null> {\r\n try {\r\n const response = await fetch(\r\n `https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n },\r\n body: JSON.stringify({ idToken }),\r\n }\r\n );\r\n\r\n const data = await response.json();\r\n console.log(\"data Token\", data);\r\n\r\n if (!response.ok || !data.users?.[0]) {\r\n return null;\r\n }\r\n\r\n const user = data.users[0];\r\n return {\r\n uid: user.localId,\r\n email: user.email || null,\r\n tenantId: user.tenantId || \"default\",\r\n disabled: user.disabled || false,\r\n };\r\n } catch (error) {\r\n console.error(\"Token verification error:\", error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Edge-compatible session cookie verification\r\n */\r\nexport async function verifySessionEdge(\r\n sessionCookie: string\r\n): Promise<BaseUser | null> {\r\n try {\r\n const response = await fetch(\r\n `https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${process.env.NEXT_PUBLIC_FIREBASE_API_KEY}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Authorization: `Bearer ${sessionCookie}`,\r\n },\r\n }\r\n );\r\n\r\n const data = await response.json();\r\n console.log(\"data Session\", data);\r\n\r\n if (!response.ok || !data.users?.[0]) {\r\n return null;\r\n }\r\n\r\n const user = data.users[0];\r\n return {\r\n uid: user.localId,\r\n email: user.email || null,\r\n tenantId: user.tenant || \"default\",\r\n disabled: user.disabled || false,\r\n };\r\n } catch (error) {\r\n console.error(\"Session verification error:\", error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Edge-compatible session verification using Firebase Auth REST API\r\n */\r\nexport async function VerifySessionWithRestApi(\r\n request: NextRequest\r\n): Promise<SessionResult> {\r\n try {\r\n // First try session cookie\r\n const sessionCookie = request.cookies.get(\"_session_cookie\")?.value;\r\n if (sessionCookie) {\r\n const response = await fetch(\r\n `https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${process.env.GOOGLE_CLIENT_ID}`,\r\n {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Authorization: `Bearer ${sessionCookie}`,\r\n },\r\n }\r\n );\r\n\r\n const data = await response.json();\r\n console.log(\"[edge-session] data with session cookie\", data);\r\n\r\n if (response.ok && data.users?.[0]) {\r\n const user = data.users[0];\r\n return {\r\n isAuthenticated: true,\r\n user: {\r\n uid: user.localId,\r\n email: user.email || null,\r\n tenantId: user.tenantId || \"default\",\r\n emailVerified: user.emailVerified ?? false,\r\n disabled: user.disabled || false,\r\n },\r\n };\r\n }\r\n console.log(\r\n \"Session cookie verification failed:\",\r\n data.error?.message || \"Invalid session\"\r\n );\r\n }\r\n return {\r\n isAuthenticated: false,\r\n user: null,\r\n error: \"No valid session found\",\r\n };\r\n } catch (error) {\r\n console.error(\"Session verification error:\", error);\r\n return {\r\n isAuthenticated: false,\r\n user: null,\r\n error:\r\n error instanceof Error ? error.message : \"Session verification failed\",\r\n };\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { constants } from "@tern-secure/backend";
|
|
2
|
+
function getCustomAttributeFromRequest(req, key) {
|
|
3
|
+
return key in req ? req[key] : void 0;
|
|
4
|
+
}
|
|
5
|
+
function getAuthKeyFromRequest(req, key) {
|
|
6
|
+
return getCustomAttributeFromRequest(req, constants.Attributes[key]) || getHeader(req, constants.Headers[key]);
|
|
7
|
+
}
|
|
8
|
+
function getHeader(req, name) {
|
|
9
|
+
if (isNextRequest(req) || isRequestWebAPI(req)) {
|
|
10
|
+
return req.headers.get(name);
|
|
11
|
+
}
|
|
12
|
+
return req.headers[name] || req.headers[name.toLowerCase()] || req.socket?._httpMessage?.getHeader(name);
|
|
13
|
+
}
|
|
14
|
+
function detectClerkMiddleware(req) {
|
|
15
|
+
return Boolean(getAuthKeyFromRequest(req, "AuthStatus"));
|
|
16
|
+
}
|
|
17
|
+
function isNextRequest(val) {
|
|
18
|
+
try {
|
|
19
|
+
const { headers, nextUrl, cookies } = val || {};
|
|
20
|
+
return typeof headers?.get === "function" && typeof nextUrl?.searchParams.get === "function" && typeof cookies?.get === "function";
|
|
21
|
+
} catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function isRequestWebAPI(val) {
|
|
26
|
+
try {
|
|
27
|
+
const { headers } = val || {};
|
|
28
|
+
return typeof headers?.get === "function";
|
|
29
|
+
} catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
detectClerkMiddleware,
|
|
35
|
+
getAuthKeyFromRequest,
|
|
36
|
+
getCustomAttributeFromRequest,
|
|
37
|
+
getHeader,
|
|
38
|
+
isNextRequest,
|
|
39
|
+
isRequestWebAPI
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=headers-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/headers-utils.ts"],"sourcesContent":["import { constants } from '@tern-secure/backend';\nimport type { NextRequest } from 'next/server';\n\nimport type { RequestLike } from './types';\n\nexport function getCustomAttributeFromRequest(req: RequestLike, key: string): string | null | undefined {\n // @ts-expect-error - TS doesn't like indexing into RequestLike\n return key in req ? req[key] : undefined;\n}\n\nexport function getAuthKeyFromRequest(\n req: RequestLike,\n key: keyof typeof constants.Attributes,\n): string | null | undefined {\n return getCustomAttributeFromRequest(req, constants.Attributes[key]) || getHeader(req, constants.Headers[key]);\n}\n\nexport function getHeader(req: RequestLike, name: string): string | null | undefined {\n if (isNextRequest(req) || isRequestWebAPI(req)) {\n return req.headers.get(name);\n }\n\n // If no header has been determined for IncomingMessage case, check if available within private `socket` headers\n // When deployed to vercel, req.headers for API routes is a `IncomingHttpHeaders` key-val object which does not follow\n // the Headers spec so the name is no longer case-insensitive.\n return req.headers[name] || req.headers[name.toLowerCase()] || (req.socket as any)?._httpMessage?.getHeader(name);\n}\n\nexport function detectClerkMiddleware(req: RequestLike): boolean {\n return Boolean(getAuthKeyFromRequest(req, 'AuthStatus'));\n}\n\nexport function isNextRequest(val: unknown): val is NextRequest {\n try {\n const { headers, nextUrl, cookies } = (val || {}) as NextRequest;\n return (\n typeof headers?.get === 'function' &&\n typeof nextUrl?.searchParams.get === 'function' &&\n typeof cookies?.get === 'function'\n );\n } catch {\n return false;\n }\n}\n\nexport function isRequestWebAPI(val: unknown): val is Request {\n try {\n const { headers } = (val || {}) as Request;\n return typeof headers?.get === 'function';\n } catch {\n return false;\n }\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAKnB,SAAS,8BAA8B,KAAkB,KAAwC;AAEtG,SAAO,OAAO,MAAM,IAAI,GAAG,IAAI;AACjC;AAEO,SAAS,sBACd,KACA,KAC2B;AAC3B,SAAO,8BAA8B,KAAK,UAAU,WAAW,GAAG,CAAC,KAAK,UAAU,KAAK,UAAU,QAAQ,GAAG,CAAC;AAC/G;AAEO,SAAS,UAAU,KAAkB,MAAyC;AACnF,MAAI,cAAc,GAAG,KAAK,gBAAgB,GAAG,GAAG;AAC9C,WAAO,IAAI,QAAQ,IAAI,IAAI;AAAA,EAC7B;AAKA,SAAO,IAAI,QAAQ,IAAI,KAAK,IAAI,QAAQ,KAAK,YAAY,CAAC,KAAM,IAAI,QAAgB,cAAc,UAAU,IAAI;AAClH;AAEO,SAAS,sBAAsB,KAA2B;AAC/D,SAAO,QAAQ,sBAAsB,KAAK,YAAY,CAAC;AACzD;AAEO,SAAS,cAAc,KAAkC;AAC9D,MAAI;AACF,UAAM,EAAE,SAAS,SAAS,QAAQ,IAAK,OAAO,CAAC;AAC/C,WACE,OAAO,SAAS,QAAQ,cACxB,OAAO,SAAS,aAAa,QAAQ,cACrC,OAAO,SAAS,QAAQ;AAAA,EAE5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,gBAAgB,KAA8B;AAC5D,MAAI;AACF,UAAM,EAAE,QAAQ,IAAK,OAAO,CAAC;AAC7B,WAAO,OAAO,SAAS,QAAQ;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/esm/server/index.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
ternSecureMiddleware
|
|
3
|
+
} from "./ternSecureEdgeMiddleware";
|
|
4
|
+
import { createRouteMatcher } from "./routeMatcher";
|
|
5
|
+
import {
|
|
6
|
+
auth
|
|
7
|
+
} from "../app-router/server/auth";
|
|
8
|
+
import { NextCookieStore } from "../utils/NextCookieAdapter";
|
|
3
9
|
export {
|
|
10
|
+
NextCookieStore,
|
|
4
11
|
auth,
|
|
5
12
|
createRouteMatcher,
|
|
6
|
-
getUser,
|
|
7
13
|
ternSecureMiddleware
|
|
8
14
|
};
|
|
9
15
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["export {
|
|
1
|
+
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["export {\r\n ternSecureMiddleware,\r\n} from \"./ternSecureEdgeMiddleware\";\r\nexport { createRouteMatcher } from \"./routeMatcher\";\r\nexport {\r\n auth\r\n} from \"../app-router/server/auth\";\r\nexport type { AuthResult } from \"../app-router/server/auth\";\r\nexport type { BaseUser, SessionResult } from \"./types\";\r\nexport { NextCookieStore } from \"../utils/NextCookieAdapter\";\r\n"],"mappings":"AAAA;AAAA,EACE;AAAA,OACK;AACP,SAAS,0BAA0B;AACnC;AAAA,EACE;AAAA,OACK;AAGP,SAAS,uBAAuB;","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
2
2
|
import { cache } from "react";
|
|
3
3
|
const FIREBASE_ID_TOKEN_URL = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
|
|
4
4
|
const FIREBASE_SESSION_CERT_URL = "https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys";
|
|
@@ -43,26 +43,54 @@ async function verifyFirebaseToken(token, isSessionCookie = false) {
|
|
|
43
43
|
if (!decoded) {
|
|
44
44
|
throw new Error("Invalid token format");
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
let retries = 3;
|
|
47
|
+
let lastError = null;
|
|
48
|
+
while (retries > 0) {
|
|
49
|
+
try {
|
|
50
|
+
const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS();
|
|
51
|
+
const { payload } = await jwtVerify(token, JWKS, {
|
|
52
|
+
issuer: isSessionCookie ? "https://session.firebase.google.com/" + projectId : "https://securetoken.google.com/" + projectId,
|
|
53
|
+
audience: projectId,
|
|
54
|
+
algorithms: ["RS256"]
|
|
55
|
+
});
|
|
56
|
+
const firebasePayload = payload;
|
|
57
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
58
|
+
if (firebasePayload.exp <= now) {
|
|
59
|
+
throw new Error("Token has expired");
|
|
60
|
+
}
|
|
61
|
+
if (firebasePayload.iat > now) {
|
|
62
|
+
throw new Error("Token issued time is in the future");
|
|
63
|
+
}
|
|
64
|
+
if (!firebasePayload.sub) {
|
|
65
|
+
throw new Error("Token subject is empty");
|
|
66
|
+
}
|
|
67
|
+
if (firebasePayload.auth_time > now) {
|
|
68
|
+
throw new Error("Token auth time is in the future");
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
valid: true,
|
|
72
|
+
uid: firebasePayload.sub,
|
|
73
|
+
email: firebasePayload.email,
|
|
74
|
+
emailVerified: firebasePayload.email_verified,
|
|
75
|
+
tenant: firebasePayload.firebase.tenant,
|
|
76
|
+
authTime: firebasePayload.auth_time,
|
|
77
|
+
issuedAt: firebasePayload.iat,
|
|
78
|
+
expiresAt: firebasePayload.exp
|
|
79
|
+
};
|
|
80
|
+
} catch (error) {
|
|
81
|
+
lastError = error;
|
|
82
|
+
if (error instanceof Error && error.name === "JWKSNoMatchingKey") {
|
|
83
|
+
console.warn(`JWKS retry attempt ${4 - retries}:`, error.message);
|
|
84
|
+
retries--;
|
|
85
|
+
if (retries > 0) {
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
56
92
|
}
|
|
57
|
-
|
|
58
|
-
valid: true,
|
|
59
|
-
uid: firebasePayload.sub,
|
|
60
|
-
email: firebasePayload.email,
|
|
61
|
-
emailVerified: firebasePayload.email_verified,
|
|
62
|
-
authTime: firebasePayload.auth_time,
|
|
63
|
-
issuedAt: firebasePayload.iat,
|
|
64
|
-
expiresAt: firebasePayload.exp
|
|
65
|
-
};
|
|
93
|
+
throw lastError || new Error("Failed to verify token after retries");
|
|
66
94
|
} catch (error) {
|
|
67
95
|
console.error("Token verification details:", {
|
|
68
96
|
error: error instanceof Error ? {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/jwt-edge.ts"],"sourcesContent":["import { jwtVerify
|
|
1
|
+
{"version":3,"sources":["../../../src/server/jwt-edge.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 = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\r\nconst FIREBASE_SESSION_CERT_URL = \"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(token: string, isSessionCookie = false): 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 // Decode token for debugging and type checking\r\n const decoded = decodeJwt(token)\r\n if (!decoded) {\r\n throw new Error(\"Invalid token format\")\r\n }\r\n\r\n //console.log(\"Token details:\", {\r\n // header: decoded.header,\r\n // type: isSessionCookie ? \"session_cookie\" : \"id_token\",\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 ? await getSessionJWKS() : 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":[]}
|
package/dist/esm/server/jwt.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
2
2
|
import { cache } from "react";
|
|
3
3
|
const FIREBASE_ID_TOKEN_URL = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
|
|
4
4
|
const FIREBASE_SESSION_CERT_URL = "https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys";
|
|
@@ -43,10 +43,6 @@ async function verifyFirebaseToken(token, isSessionCookie = false) {
|
|
|
43
43
|
if (!decoded) {
|
|
44
44
|
throw new Error("Invalid token format");
|
|
45
45
|
}
|
|
46
|
-
console.log("Token details:", {
|
|
47
|
-
header: decoded.header,
|
|
48
|
-
type: isSessionCookie ? "session_cookie" : "id_token"
|
|
49
|
-
});
|
|
50
46
|
let retries = 3;
|
|
51
47
|
let lastError = null;
|
|
52
48
|
while (retries > 0) {
|
|
@@ -58,14 +54,25 @@ async function verifyFirebaseToken(token, isSessionCookie = false) {
|
|
|
58
54
|
algorithms: ["RS256"]
|
|
59
55
|
});
|
|
60
56
|
const firebasePayload = payload;
|
|
57
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
58
|
+
if (firebasePayload.exp <= now) {
|
|
59
|
+
throw new Error("Token has expired");
|
|
60
|
+
}
|
|
61
|
+
if (firebasePayload.iat > now) {
|
|
62
|
+
throw new Error("Token issued time is in the future");
|
|
63
|
+
}
|
|
61
64
|
if (!firebasePayload.sub) {
|
|
62
65
|
throw new Error("Token subject is empty");
|
|
63
66
|
}
|
|
67
|
+
if (firebasePayload.auth_time > now) {
|
|
68
|
+
throw new Error("Token auth time is in the future");
|
|
69
|
+
}
|
|
64
70
|
return {
|
|
65
71
|
valid: true,
|
|
66
72
|
uid: firebasePayload.sub,
|
|
67
73
|
email: firebasePayload.email,
|
|
68
74
|
emailVerified: firebasePayload.email_verified,
|
|
75
|
+
tenant: firebasePayload.firebase.tenant,
|
|
69
76
|
authTime: firebasePayload.auth_time,
|
|
70
77
|
issuedAt: firebasePayload.iat,
|
|
71
78
|
expiresAt: firebasePayload.exp
|