@tern-secure/nextjs 5.2.0-canary.v20251127235234 → 5.2.0-canary.v20251202162458

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.
Files changed (97) hide show
  1. package/dist/cjs/__tests__/gemini_fnTernSecureNextHandler.bench.js +2 -2
  2. package/dist/cjs/__tests__/gemini_fnTernSecureNextHandler.bench.js.map +1 -1
  3. package/dist/cjs/app-router/admin/actions.js.map +1 -1
  4. package/dist/cjs/app-router/admin/endpointRouter.js +4 -13
  5. package/dist/cjs/app-router/admin/endpointRouter.js.map +1 -1
  6. package/dist/cjs/app-router/admin/{sessionHandlers.js → handlers.js} +16 -115
  7. package/dist/cjs/app-router/admin/handlers.js.map +1 -0
  8. package/dist/cjs/app-router/admin/index.js.map +1 -1
  9. package/dist/cjs/app-router/admin/request.js +1 -8
  10. package/dist/cjs/app-router/admin/request.js.map +1 -1
  11. package/dist/cjs/app-router/admin/signInCreateHandler.js.map +1 -1
  12. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js +7 -17
  13. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
  14. package/dist/cjs/app-router/admin/types.js +9 -0
  15. package/dist/cjs/app-router/admin/types.js.map +1 -1
  16. package/dist/cjs/app-router/admin/validators.js +96 -171
  17. package/dist/cjs/app-router/admin/validators.js.map +1 -1
  18. package/dist/cjs/app-router/server/TernSecureProvider.js +18 -0
  19. package/dist/cjs/app-router/server/TernSecureProvider.js.map +1 -1
  20. package/dist/cjs/server/constant.js +6 -0
  21. package/dist/cjs/server/constant.js.map +1 -1
  22. package/dist/cjs/server/data/getAuthDataFromRequest.js +16 -9
  23. package/dist/cjs/server/data/getAuthDataFromRequest.js.map +1 -1
  24. package/dist/cjs/server/headers-utils.js +3 -3
  25. package/dist/cjs/server/headers-utils.js.map +1 -1
  26. package/dist/cjs/server/proxy-storage.js +33 -0
  27. package/dist/cjs/server/proxy-storage.js.map +1 -0
  28. package/dist/cjs/server/ternSecureProxy.js +2 -13
  29. package/dist/cjs/server/ternSecureProxy.js.map +1 -1
  30. package/dist/cjs/server/utils.js +16 -4
  31. package/dist/cjs/server/utils.js.map +1 -1
  32. package/dist/esm/__tests__/gemini_fnTernSecureNextHandler.bench.js +1 -1
  33. package/dist/esm/__tests__/gemini_fnTernSecureNextHandler.bench.js.map +1 -1
  34. package/dist/esm/app-router/admin/actions.js.map +1 -1
  35. package/dist/esm/app-router/admin/endpointRouter.js +3 -12
  36. package/dist/esm/app-router/admin/endpointRouter.js.map +1 -1
  37. package/dist/esm/app-router/admin/{sessionHandlers.js → handlers.js} +18 -110
  38. package/dist/esm/app-router/admin/handlers.js.map +1 -0
  39. package/dist/esm/app-router/admin/index.js.map +1 -1
  40. package/dist/esm/app-router/admin/request.js +2 -14
  41. package/dist/esm/app-router/admin/request.js.map +1 -1
  42. package/dist/esm/app-router/admin/signInCreateHandler.js.map +1 -1
  43. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js +9 -19
  44. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
  45. package/dist/esm/app-router/admin/types.js +8 -0
  46. package/dist/esm/app-router/admin/types.js.map +1 -1
  47. package/dist/esm/app-router/admin/validators.js +88 -166
  48. package/dist/esm/app-router/admin/validators.js.map +1 -1
  49. package/dist/esm/app-router/server/TernSecureProvider.js +19 -1
  50. package/dist/esm/app-router/server/TernSecureProvider.js.map +1 -1
  51. package/dist/esm/server/constant.js +4 -0
  52. package/dist/esm/server/constant.js.map +1 -1
  53. package/dist/esm/server/data/getAuthDataFromRequest.js +18 -11
  54. package/dist/esm/server/data/getAuthDataFromRequest.js.map +1 -1
  55. package/dist/esm/server/headers-utils.js +2 -2
  56. package/dist/esm/server/headers-utils.js.map +1 -1
  57. package/dist/esm/server/proxy-storage.js +8 -0
  58. package/dist/esm/server/proxy-storage.js.map +1 -0
  59. package/dist/esm/server/ternSecureProxy.js +7 -14
  60. package/dist/esm/server/ternSecureProxy.js.map +1 -1
  61. package/dist/esm/server/utils.js +16 -4
  62. package/dist/esm/server/utils.js.map +1 -1
  63. package/dist/types/app-router/admin/actions.d.ts +2 -2
  64. package/dist/types/app-router/admin/actions.d.ts.map +1 -1
  65. package/dist/types/app-router/admin/endpointRouter.d.ts +4 -4
  66. package/dist/types/app-router/admin/endpointRouter.d.ts.map +1 -1
  67. package/dist/types/app-router/admin/handlers.d.ts +5 -0
  68. package/dist/types/app-router/admin/handlers.d.ts.map +1 -0
  69. package/dist/types/app-router/admin/index.d.ts +1 -1
  70. package/dist/types/app-router/admin/index.d.ts.map +1 -1
  71. package/dist/types/app-router/admin/request.d.ts +2 -2
  72. package/dist/types/app-router/admin/request.d.ts.map +1 -1
  73. package/dist/types/app-router/admin/signInCreateHandler.d.ts +1 -1
  74. package/dist/types/app-router/admin/signInCreateHandler.d.ts.map +1 -1
  75. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts +6 -2
  76. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts.map +1 -1
  77. package/dist/types/app-router/admin/types.d.ts +24 -2
  78. package/dist/types/app-router/admin/types.d.ts.map +1 -1
  79. package/dist/types/app-router/admin/validators.d.ts +36 -33
  80. package/dist/types/app-router/admin/validators.d.ts.map +1 -1
  81. package/dist/types/app-router/server/TernSecureProvider.d.ts.map +1 -1
  82. package/dist/types/server/constant.d.ts +2 -0
  83. package/dist/types/server/constant.d.ts.map +1 -1
  84. package/dist/types/server/data/getAuthDataFromRequest.d.ts.map +1 -1
  85. package/dist/types/server/headers-utils.d.ts +1 -1
  86. package/dist/types/server/headers-utils.d.ts.map +1 -1
  87. package/dist/types/server/proxy-storage.d.ts +5 -0
  88. package/dist/types/server/proxy-storage.d.ts.map +1 -0
  89. package/dist/types/server/ternSecureProxy.d.ts +1 -3
  90. package/dist/types/server/ternSecureProxy.d.ts.map +1 -1
  91. package/dist/types/server/utils.d.ts +2 -2
  92. package/dist/types/server/utils.d.ts.map +1 -1
  93. package/package.json +5 -5
  94. package/dist/cjs/app-router/admin/sessionHandlers.js.map +0 -1
  95. package/dist/esm/app-router/admin/sessionHandlers.js.map +0 -1
  96. package/dist/types/app-router/admin/sessionHandlers.d.ts +0 -7
  97. package/dist/types/app-router/admin/sessionHandlers.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/signInCreateHandler.ts"],"sourcesContent":["import type { SignInCreateParams } from '@tern-secure/types';\n\nimport { RetrieveUser } from './actions';\nimport type { RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport {\n createApiErrorResponse,\n createApiSuccessResponse,\n} from './responses';\n\n\nexport const processSignInCreate = async (\n context: RequestProcessorContext\n): Promise<Response> => {\n try {\n const body = await context.request.json();\n const { strategy, identifier } = body as SignInCreateParams & { identifier?: string; password?: string };\n\n if (!strategy) {\n return createApiErrorResponse(\n 'STRATEGY_REQUIRED',\n 'Authentication strategy is required',\n 400\n );\n }\n\n if (!identifier) {\n return createApiSuccessResponse({\n status: 'needs_identifier',\n strategy,\n message: 'Identifier is required to continue',\n });\n }\n\n if (strategy === 'email_code') {\n return await processEmailCodeStrategy(identifier);\n }\n\n if (strategy === 'password') {\n return await processPasswordStrategy(identifier);\n }\n\n if (strategy === 'phone_code') {\n return processPhoneCodeStrategy(identifier);\n }\n\n if (strategy === 'reset_password_email_code' || strategy === 'reset_password_phone_code') {\n return await processResetPasswordStrategy(strategy, identifier);\n }\n\n return createApiErrorResponse(\n 'INVALID_STRATEGY',\n `Unsupported authentication strategy: ${strategy}`,\n 400\n );\n } catch (error) {\n return createApiErrorResponse(\n 'SIGN_IN_CREATE_ERROR',\n error instanceof Error\n ? error.message\n : 'An error occurred while creating sign-in',\n 500\n );\n }\n};\n\n/**\n * Processes email_code strategy\n * Verifies if user exists by email and returns needs_first_factor status\n */\nexport const processEmailCodeStrategy = async (email: string): Promise<Response> => {\n try {\n const retrieveUser = RetrieveUser();\n const { data: user, error } = await retrieveUser.getUserByEmail(email);\n\n if (error) {\n return createApiErrorResponse(\n error.code,\n error.message,\n 400\n );\n }\n\n if (!user.emailVerified) {\n return createApiSuccessResponse({\n status: 'needs_email_verification',\n identifier: email,\n supportedFirstFactors: [{ strategy: 'email_code' }],\n userId: user.uid,\n message: 'Email verification required',\n });\n }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier: email,\n supportedFirstFactors: [{ strategy: 'email_code' }],\n userId: user.uid,\n message: 'User verified. Proceed with first factor authentication',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('no user record')) {\n return createApiErrorResponse(\n 'USER_NOT_FOUND',\n 'No user found with this email address',\n 404\n );\n }\n\n return createApiErrorResponse(\n 'EMAIL_VERIFICATION_ERROR',\n error instanceof Error ? error.message : 'Failed to verify email',\n 500\n );\n }\n};\n\n\nexport const processPasswordStrategy = async (identifier: string): Promise<Response> => {\n try {\n const retrieveUser = RetrieveUser();\n const { data: user, error } = await retrieveUser.getUserByEmail(identifier);\n\n if (error) {\n return createApiErrorResponse(\n error.code,\n error.message,\n 400\n );\n }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier,\n supportedFirstFactors: [{ strategy: 'password' }],\n userId: user.uid,\n message: 'User verified. Proceed with password authentication',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('no user record')) {\n return createApiErrorResponse(\n 'USER_NOT_FOUND',\n 'No user found with this identifier',\n 404\n );\n }\n\n return createApiErrorResponse(\n 'USER_VERIFICATION_ERROR',\n error instanceof Error ? error.message : 'Failed to verify user',\n 500\n );\n }\n};\n\n\nexport const processPhoneCodeStrategy = async (phoneNumber: string): Promise<Response> => {\n try {\n //const retrieveUser = RetrieveUser();\n //const { data: user, error } = await retrieveUser.getUserByPhoneNumber(phoneNumber);\n\n //if (error) {\n // return createApiErrorResponse(\n // error.code,\n // error.message,\n // 400\n // );\n // }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier: phoneNumber,\n supportedFirstFactors: [{ strategy: 'phone_code' }],\n //userId: user.uid,\n message: 'User verified. Proceed with phone authentication',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('no user record')) {\n return createApiErrorResponse(\n 'USER_NOT_FOUND',\n 'No user found with this phone number',\n 404\n );\n }\n\n return createApiErrorResponse(\n 'PHONE_VERIFICATION_ERROR',\n error instanceof Error ? error.message : 'Failed to verify phone number',\n 500\n );\n }\n};\n\n\nexport const processResetPasswordStrategy = async (\n strategy: 'reset_password_email_code' | 'reset_password_phone_code',\n identifier: string\n): Promise<Response> => {\n try {\n if (strategy === 'reset_password_email_code') {\n const retrieveUser = RetrieveUser();\n const { data: user, error } = await retrieveUser.getUserByEmail(identifier);\n\n if (error) {\n return createApiErrorResponse(\n error.code,\n error.message,\n 400\n );\n }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier,\n strategy,\n userId: user.uid,\n message: 'User verified. Proceed with password reset',\n });\n }\n\n return createApiErrorResponse(\n 'NOT_IMPLEMENTED',\n 'Phone reset password strategy not yet implemented',\n 501\n );\n } catch (error) {\n return createApiErrorResponse(\n 'RESET_PASSWORD_ERROR',\n error instanceof Error ? error.message : 'Failed to process password reset',\n 500\n );\n }\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/signInCreateHandler.ts"],"sourcesContent":["import type { RequestProcessorContext } from '@tern-secure/backend';\nimport type { SignInCreateParams } from '@tern-secure/types';\n\nimport { RetrieveUser } from './actions';\nimport {\n createApiErrorResponse,\n createApiSuccessResponse,\n} from './responses';\n\n\nexport const processSignInCreate = async (\n context: RequestProcessorContext\n): Promise<Response> => {\n try {\n const body = await context.request.json();\n const { strategy, identifier } = body as SignInCreateParams & { identifier?: string; password?: string };\n\n if (!strategy) {\n return createApiErrorResponse(\n 'STRATEGY_REQUIRED',\n 'Authentication strategy is required',\n 400\n );\n }\n\n if (!identifier) {\n return createApiSuccessResponse({\n status: 'needs_identifier',\n strategy,\n message: 'Identifier is required to continue',\n });\n }\n\n if (strategy === 'email_code') {\n return await processEmailCodeStrategy(identifier);\n }\n\n if (strategy === 'password') {\n return await processPasswordStrategy(identifier);\n }\n\n if (strategy === 'phone_code') {\n return processPhoneCodeStrategy(identifier);\n }\n\n if (strategy === 'reset_password_email_code' || strategy === 'reset_password_phone_code') {\n return await processResetPasswordStrategy(strategy, identifier);\n }\n\n return createApiErrorResponse(\n 'INVALID_STRATEGY',\n `Unsupported authentication strategy: ${strategy}`,\n 400\n );\n } catch (error) {\n return createApiErrorResponse(\n 'SIGN_IN_CREATE_ERROR',\n error instanceof Error\n ? error.message\n : 'An error occurred while creating sign-in',\n 500\n );\n }\n};\n\n/**\n * Processes email_code strategy\n * Verifies if user exists by email and returns needs_first_factor status\n */\nexport const processEmailCodeStrategy = async (email: string): Promise<Response> => {\n try {\n const retrieveUser = RetrieveUser();\n const { data: user, error } = await retrieveUser.getUserByEmail(email);\n\n if (error) {\n return createApiErrorResponse(\n error.code,\n error.message,\n 400\n );\n }\n\n if (!user.emailVerified) {\n return createApiSuccessResponse({\n status: 'needs_email_verification',\n identifier: email,\n supportedFirstFactors: [{ strategy: 'email_code' }],\n userId: user.uid,\n message: 'Email verification required',\n });\n }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier: email,\n supportedFirstFactors: [{ strategy: 'email_code' }],\n userId: user.uid,\n message: 'User verified. Proceed with first factor authentication',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('no user record')) {\n return createApiErrorResponse(\n 'USER_NOT_FOUND',\n 'No user found with this email address',\n 404\n );\n }\n\n return createApiErrorResponse(\n 'EMAIL_VERIFICATION_ERROR',\n error instanceof Error ? error.message : 'Failed to verify email',\n 500\n );\n }\n};\n\n\nexport const processPasswordStrategy = async (identifier: string): Promise<Response> => {\n try {\n const retrieveUser = RetrieveUser();\n const { data: user, error } = await retrieveUser.getUserByEmail(identifier);\n\n if (error) {\n return createApiErrorResponse(\n error.code,\n error.message,\n 400\n );\n }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier,\n supportedFirstFactors: [{ strategy: 'password' }],\n userId: user.uid,\n message: 'User verified. Proceed with password authentication',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('no user record')) {\n return createApiErrorResponse(\n 'USER_NOT_FOUND',\n 'No user found with this identifier',\n 404\n );\n }\n\n return createApiErrorResponse(\n 'USER_VERIFICATION_ERROR',\n error instanceof Error ? error.message : 'Failed to verify user',\n 500\n );\n }\n};\n\n\nexport const processPhoneCodeStrategy = async (phoneNumber: string): Promise<Response> => {\n try {\n //const retrieveUser = RetrieveUser();\n //const { data: user, error } = await retrieveUser.getUserByPhoneNumber(phoneNumber);\n\n //if (error) {\n // return createApiErrorResponse(\n // error.code,\n // error.message,\n // 400\n // );\n // }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier: phoneNumber,\n supportedFirstFactors: [{ strategy: 'phone_code' }],\n //userId: user.uid,\n message: 'User verified. Proceed with phone authentication',\n });\n } catch (error) {\n if (error instanceof Error && error.message.includes('no user record')) {\n return createApiErrorResponse(\n 'USER_NOT_FOUND',\n 'No user found with this phone number',\n 404\n );\n }\n\n return createApiErrorResponse(\n 'PHONE_VERIFICATION_ERROR',\n error instanceof Error ? error.message : 'Failed to verify phone number',\n 500\n );\n }\n};\n\n\nexport const processResetPasswordStrategy = async (\n strategy: 'reset_password_email_code' | 'reset_password_phone_code',\n identifier: string\n): Promise<Response> => {\n try {\n if (strategy === 'reset_password_email_code') {\n const retrieveUser = RetrieveUser();\n const { data: user, error } = await retrieveUser.getUserByEmail(identifier);\n\n if (error) {\n return createApiErrorResponse(\n error.code,\n error.message,\n 400\n );\n }\n\n return createApiSuccessResponse({\n status: 'needs_first_factor',\n identifier,\n strategy,\n userId: user.uid,\n message: 'User verified. Proceed with password reset',\n });\n }\n\n return createApiErrorResponse(\n 'NOT_IMPLEMENTED',\n 'Phone reset password strategy not yet implemented',\n 501\n );\n } catch (error) {\n return createApiErrorResponse(\n 'RESET_PASSWORD_ERROR',\n error instanceof Error ? error.message : 'Failed to process password reset',\n 500\n );\n }\n};\n"],"mappings":"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","names":[]}
@@ -1,28 +1,18 @@
1
- import { createTernSecureRequest } from "@tern-secure/backend";
2
- import { createRequestProcessor } from "./c-authenticateRequestProcessor";
1
+ import { createRequestProcessor, createTernSecureRequest } from "@tern-secure/backend";
3
2
  import { TENANT_ID } from "./constants";
4
3
  import { EndpointRouter } from "./endpointRouter";
5
- import { createValidators } from "./fnValidators";
6
4
  import { createApiErrorResponse } from "./responses";
7
- import { DEFAULT_HANDLER_OPTIONS } from "./types";
8
- import { ConfigUtils } from "./utils";
9
- function createHandlerConfig(options) {
10
- const baseConfig = ConfigUtils.mergeWithDefaults(
11
- DEFAULT_HANDLER_OPTIONS,
12
- options
13
- );
14
- return {
15
- ...baseConfig,
16
- tenantId: TENANT_ID
17
- };
18
- }
5
+ import { DEFAULT_API_HANDLER_OPTIONS } from "./types";
19
6
  function createTernSecureNextJsHandler(options) {
20
- const config = createHandlerConfig(options);
7
+ const config = {
8
+ ...DEFAULT_API_HANDLER_OPTIONS,
9
+ ...options,
10
+ tenantId: options?.tenantId || TENANT_ID
11
+ };
21
12
  const handler = async (request) => {
22
13
  try {
23
- const context = createRequestProcessor(createTernSecureRequest(request), options);
24
- const { validateSecurity } = createValidators(context);
25
- await validateSecurity(options.security || {});
14
+ const ternRequest = createTernSecureRequest(request);
15
+ const context = createRequestProcessor(ternRequest, config);
26
16
  if (!context.endpoint) {
27
17
  return createApiErrorResponse("ENDPOINT_REQUIRED", "Endpoint is required", 400);
28
18
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/ternsecureNextjsHandler.ts"],"sourcesContent":["import { createTernSecureRequest } from '@tern-secure/backend';\n\nimport { createRequestProcessor } from './c-authenticateRequestProcessor';\nimport { TENANT_ID } from './constants';\nimport { EndpointRouter } from './endpointRouter';\nimport { createValidators } from './fnValidators';\nimport { createApiErrorResponse } from './responses';\nimport type { TernSecureHandlerOptions } from './types';\nimport { DEFAULT_HANDLER_OPTIONS } from './types';\nimport { ConfigUtils } from './utils';\n\nfunction createHandlerConfig(options?: TernSecureHandlerOptions): TernSecureHandlerOptions {\n const baseConfig: Required<TernSecureHandlerOptions> = ConfigUtils.mergeWithDefaults(\n DEFAULT_HANDLER_OPTIONS,\n options,\n );\n\n return {\n ...baseConfig,\n tenantId: TENANT_ID,\n };\n}\n\nexport function createTernSecureNextJsHandler(options: TernSecureHandlerOptions) {\n const config = createHandlerConfig(options);\n\n const handler = async (request: Request): Promise<Response> => {\n try {\n const context = createRequestProcessor(createTernSecureRequest(request), options);\n\n const { validateSecurity } = createValidators(context);\n await validateSecurity(options.security || {});\n\n if (!context.endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n return await EndpointRouter.route(context, config);\n } catch (error) {\n return createApiErrorResponse('INTERNAL_SERVER_ERROR', 'Internal server error', 500);\n }\n };\n\n return {\n GET: handler,\n POST: handler,\n } as const;\n}\n"],"mappings":"AAAA,SAAS,+BAA+B;AAExC,SAAS,8BAA8B;AACvC,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,8BAA8B;AAEvC,SAAS,+BAA+B;AACxC,SAAS,mBAAmB;AAE5B,SAAS,oBAAoB,SAA8D;AACzF,QAAM,aAAiD,YAAY;AAAA,IACjE;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,8BAA8B,SAAmC;AAC/E,QAAM,SAAS,oBAAoB,OAAO;AAE1C,QAAM,UAAU,OAAO,YAAwC;AAC7D,QAAI;AACF,YAAM,UAAU,uBAAuB,wBAAwB,OAAO,GAAG,OAAO;AAEhF,YAAM,EAAE,iBAAiB,IAAI,iBAAiB,OAAO;AACrD,YAAM,iBAAiB,QAAQ,YAAY,CAAC,CAAC;AAE7C,UAAI,CAAC,QAAQ,UAAU;AACrB,eAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,MAChF;AAEA,aAAO,MAAM,eAAe,MAAM,SAAS,MAAM;AAAA,IACnD,SAAS,OAAO;AACd,aAAO,uBAAuB,yBAAyB,yBAAyB,GAAG;AAAA,IACrF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/ternsecureNextjsHandler.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport { createRequestProcessor, createTernSecureRequest } from '@tern-secure/backend';\n\nimport { TENANT_ID } from './constants';\nimport { EndpointRouter } from './endpointRouter';\nimport { createApiErrorResponse } from './responses';\nimport { DEFAULT_API_HANDLER_OPTIONS } from './types';\n\n/**\n * Create API route handlers with unified options\n * Uses the same AuthenticateRequestOptions as middleware\n */\nexport function createTernSecureNextJsHandler(options?: AuthenticateRequestOptions) {\n const config: AuthenticateRequestOptions = {\n ...DEFAULT_API_HANDLER_OPTIONS,\n ...options,\n tenantId: options?.tenantId || TENANT_ID,\n };\n\n const handler = async (request: Request): Promise<Response> => {\n try {\n \n const ternRequest = createTernSecureRequest(request);\n const context = createRequestProcessor(ternRequest, config);\n\n if (!context.endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n return await EndpointRouter.route(context, config);\n } catch (error) {\n return createApiErrorResponse('INTERNAL_SERVER_ERROR', 'Internal server error', 500);\n }\n };\n\n return {\n GET: handler,\n POST: handler,\n } as const;\n}\n"],"mappings":"AACA,SAAS,wBAAwB,+BAA+B;AAEhE,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,8BAA8B;AACvC,SAAS,mCAAmC;AAMrC,SAAS,8BAA8B,SAAsC;AAClF,QAAM,SAAqC;AAAA,IACzC,GAAG;AAAA,IACH,GAAG;AAAA,IACH,UAAU,SAAS,YAAY;AAAA,EACjC;AAEA,QAAM,UAAU,OAAO,YAAwC;AAC7D,QAAI;AAEF,YAAM,cAAc,wBAAwB,OAAO;AACnD,YAAM,UAAU,uBAAuB,aAAa,MAAM;AAE1D,UAAI,CAAC,QAAQ,UAAU;AACrB,eAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,MAChF;AAEA,aAAO,MAAM,eAAe,MAAM,SAAS,MAAM;AAAA,IACnD,SAAS,OAAO;AACd,aAAO,uBAAuB,yBAAyB,yBAAyB,GAAG;AAAA,IACrF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;","names":[]}
@@ -191,8 +191,16 @@ class CookieUtils {
191
191
  return maxAge >= minAge && maxAge <= maxAgeLimit;
192
192
  }
193
193
  }
194
+ const DEFAULT_API_HANDLER_OPTIONS = {
195
+ tenantId: void 0,
196
+ cookies: DEFAULT_SESSION_COOKIE_OPTIONS,
197
+ enableCustomToken: false,
198
+ debug: false,
199
+ revokeRefreshTokensOnSignOut: true
200
+ };
194
201
  export {
195
202
  CookieUtils,
203
+ DEFAULT_API_HANDLER_OPTIONS,
196
204
  DEFAULT_COOKIE_REQUEST_CONFIG,
197
205
  DEFAULT_CORS_OPTIONS,
198
206
  DEFAULT_ENDPOINT_CONFIG,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n CookieEndpointConfig,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n SignInEndpointConfig,\n SignInSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_SESSION_COOKIE_OPTIONS: CookieOptions = {\n httpOnly: true,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 12 * 60 * 60 * 24, // twelve days\n priority: 'high',\n};\n\nexport const DEFAULT_ID_REFRESH_TOKEN_COOKIE_OPTIONS: CookieOptions = {\n httpOnly: true,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 12 * 60 * 60 * 24, // twelve days\n priority: 'high',\n};\n\n\nexport const FIXED_TOKEN_CONFIGS = {\n id: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600, // 1 hour\n },\n refresh: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 30, // 30 days (changes when user events occur)\n },\n signature: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n custom: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n} as const;\n\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n requireCSRF: true,\n allowedReferers: [],\n requiredHeaders: {},\n ipWhitelist: [],\n userAgent: {\n block: [],\n allow: [],\n },\n};\n\nexport const DEFAULT_ENDPOINT_CONFIG: EndpointConfig = {\n enabled: true,\n methods: ['GET', 'POST'],\n requireAuth: false,\n security: DEFAULT_SECURITY_OPTIONS,\n};\n\nexport const DEFAULT_COOKIE_REQUEST_CONFIG: CookieEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n get: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n },\n};\n\nexport const DEFAULT_SESSIONS_CONFIG: SessionEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n verify: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n createsession: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n },\n },\n refresh: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n revoke: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n },\n};\n\nexport const DEFAULT_SIGNINS_CONFIG: SignInEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n resetPasswordEmail: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false\n },\n },\n};\n\nexport const DEFAULT_HANDLER_OPTIONS: Required<TernSecureHandlerOptions> & {\n endpoints: Required<NonNullable<TernSecureHandlerOptions['endpoints']>>;\n} = {\n cors: DEFAULT_CORS_OPTIONS,\n cookies: DEFAULT_SESSION_COOKIE_OPTIONS,\n rateLimit: {\n windowMs: 15 * 60 * 1000, // 15 minutes\n maxRequests: 100,\n skipSuccessful: false,\n skipFailedRequests: false,\n },\n security: DEFAULT_SECURITY_OPTIONS,\n endpoints: {\n cookies: DEFAULT_COOKIE_REQUEST_CONFIG,\n sessions: DEFAULT_SESSIONS_CONFIG,\n signIns: DEFAULT_SIGNINS_CONFIG,\n },\n tenantId: '',\n revokeRefreshTokensOnSignOut: true,\n enableCustomToken: false,\n debug: false,\n environment: 'production',\n basePath: '/api/auth',\n};\n\nexport interface ValidationResult {\n error?: NextResponse;\n data?: any;\n}\n\nexport interface ValidationConfig {\n cors?: CorsOptions;\n security?: SecurityOptions;\n endpoint?: {\n name: AuthEndpoint;\n config: EndpointConfig;\n };\n subEndpoint?: {\n name: SessionSubEndpoint;\n config: EndpointConfig;\n };\n requireIdToken?: boolean;\n requireCsrfToken?: boolean;\n}\n\nexport interface ComprehensiveValidationResult {\n isValid: boolean;\n error?: Response;\n corsResponse?: Response;\n sessionData?: {\n body: any;\n idToken?: string;\n csrfToken?: string;\n };\n}\n\nexport type suffix = 'session' | 'id' | 'refresh' | 'signature' | 'custom';\n\nexport class CookieUtils {\n static getCookieName(namePrefix: string, tokenType: suffix): string {\n return `${namePrefix}.${tokenType}`;\n }\n\n static getCookieNames(namePrefix: string) {\n return {\n session: this.getCookieName(namePrefix, 'session'),\n id: this.getCookieName(namePrefix, 'id'),\n refresh: this.getCookieName(namePrefix, 'refresh'),\n signature: this.getCookieName(namePrefix, 'signature'),\n custom: this.getCookieName(namePrefix, 'custom'),\n };\n }\n\n static getSessionConfig(cookieOptions: CookieOptions): TokenCookieConfig {\n return {\n path: cookieOptions.path ?? '/',\n httpOnly: cookieOptions.httpOnly ?? true,\n sameSite: cookieOptions.sameSite ?? 'lax',\n maxAge: cookieOptions.maxAge ?? 3600 * 24 * 7,\n };\n }\n\n static getFixedTokenConfig(\n tokenType: Exclude<suffix, 'session'>,\n ): TokenCookieConfig {\n const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];\n\n return {\n path: fixedConfig.path,\n httpOnly: fixedConfig.httpOnly,\n sameSite: fixedConfig.sameSite,\n maxAge: fixedConfig.maxAge,\n };\n }\n\n static validateSessionMaxAge(maxAge: number): boolean {\n const minAge = 300; // 5 minutes\n const maxAgeLimit = 3600 * 24 * 14; // 2 weeks\n return maxAge >= minAge && maxAge <= maxAgeLimit;\n }\n}\n\nexport {\n AuthEndpoint,\n CookieOptions,\n CorsOptions,\n SecurityOptions,\n SessionSubEndpoint,\n EndpointConfig,\n SessionEndpointConfig,\n SignInEndpointConfig,\n SignInSubEndpoint,\n TernSecureHandlerOptions,\n};\n"],"mappings":"AAgBO,MAAM,uBAAoC;AAAA,EAC/C,gBAAgB,CAAC;AAAA,EACjB,gBAAgB,CAAC,OAAO,MAAM;AAAA,EAC9B,gBAAgB,CAAC,gBAAgB,iBAAiB,kBAAkB;AAAA,EACpE,kBAAkB;AAAA,EAClB,QAAQ;AAAA;AACV;AAEO,MAAM,iCAAgD;AAAA,EAC3D,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,EACjC,UAAU;AAAA,EACV,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,EACvB,UAAU;AACZ;AAEO,MAAM,0CAAyD;AAAA,EACpE,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ,QAAQ,IAAI,aAAa;AAAA,EACjC,UAAU;AAAA,EACV,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,EACvB,UAAU;AACZ;AAGO,MAAM,sBAAsB;AAAA,EACjC,IAAI;AAAA,IACF,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ;AAAA;AAAA,EACV;AAAA,EACA,SAAS;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ,OAAO,KAAK;AAAA;AAAA,EACtB;AAAA,EACA,WAAW;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ,OAAO,KAAK;AAAA;AAAA,EACtB;AAAA,EACA,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA,IACV,UAAU;AAAA,IACV,QAAQ,OAAO,KAAK;AAAA;AAAA,EACtB;AACF;AAEO,MAAM,2BAA4C;AAAA,EACvD,aAAa;AAAA,EACb,iBAAiB,CAAC;AAAA,EAClB,iBAAiB,CAAC;AAAA,EAClB,aAAa,CAAC;AAAA,EACd,WAAW;AAAA,IACT,OAAO,CAAC;AAAA,IACR,OAAO,CAAC;AAAA,EACV;AACF;AAEO,MAAM,0BAA0C;AAAA,EACrD,SAAS;AAAA,EACT,SAAS,CAAC,OAAO,MAAM;AAAA,EACvB,aAAa;AAAA,EACb,UAAU;AACZ;AAEO,MAAM,gCAAsD;AAAA,EACjE,GAAG;AAAA,EACH,cAAc;AAAA,IACZ,KAAK;AAAA,MACH,SAAS;AAAA,MACT,SAAS,CAAC,KAAK;AAAA,MACf,aAAa;AAAA,MACb,UAAU;AAAA,QACR,aAAa;AAAA,QACb,iBAAiB,CAAC;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,0BAAiD;AAAA,EAC5D,GAAG;AAAA,EACH,cAAc;AAAA,IACZ,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,SAAS,CAAC,KAAK;AAAA,MACf,aAAa;AAAA,MACb,UAAU;AAAA,QACR,aAAa;AAAA,QACb,iBAAiB,CAAC;AAAA,MACpB;AAAA,IACF;AAAA,IACA,eAAe;AAAA,MACb,SAAS;AAAA,MACT,SAAS,CAAC,MAAM;AAAA,MAChB,aAAa;AAAA,MACb,UAAU;AAAA,QACR,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP,SAAS;AAAA,MACT,SAAS,CAAC,MAAM;AAAA,MAChB,aAAa;AAAA,MACb,UAAU;AAAA,QACR,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,SAAS,CAAC,MAAM;AAAA,MAChB,aAAa;AAAA,MACb,UAAU;AAAA,QACR,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,yBAA+C;AAAA,EAC1D,GAAG;AAAA,EACH,cAAc;AAAA,IACZ,oBAAoB;AAAA,MAClB,SAAS;AAAA,MACT,SAAS,CAAC,MAAM;AAAA,MAChB,aAAa;AAAA,IACf;AAAA,EACF;AACF;AAEO,MAAM,0BAET;AAAA,EACF,MAAM;AAAA,EACN,SAAS;AAAA,EACT,WAAW;AAAA,IACT,UAAU,KAAK,KAAK;AAAA;AAAA,IACpB,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,IACV,SAAS;AAAA,EACX;AAAA,EACA,UAAU;AAAA,EACV,8BAA8B;AAAA,EAC9B,mBAAmB;AAAA,EACnB,OAAO;AAAA,EACP,aAAa;AAAA,EACb,UAAU;AACZ;AAmCO,MAAM,YAAY;AAAA,EACvB,OAAO,cAAc,YAAoB,WAA2B;AAClE,WAAO,GAAG,UAAU,IAAI,SAAS;AAAA,EACnC;AAAA,EAEA,OAAO,eAAe,YAAoB;AACxC,WAAO;AAAA,MACL,SAAS,KAAK,cAAc,YAAY,SAAS;AAAA,MACjD,IAAI,KAAK,cAAc,YAAY,IAAI;AAAA,MACvC,SAAS,KAAK,cAAc,YAAY,SAAS;AAAA,MACjD,WAAW,KAAK,cAAc,YAAY,WAAW;AAAA,MACrD,QAAQ,KAAK,cAAc,YAAY,QAAQ;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,OAAO,iBAAiB,eAAiD;AACvE,WAAO;AAAA,MACL,MAAM,cAAc,QAAQ;AAAA,MAC5B,UAAU,cAAc,YAAY;AAAA,MACpC,UAAU,cAAc,YAAY;AAAA,MACpC,QAAQ,cAAc,UAAU,OAAO,KAAK;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,OAAO,oBACL,WACmB;AACnB,UAAM,cAAc,oBAAoB,SAAS;AAEjD,WAAO;AAAA,MACL,MAAM,YAAY;AAAA,MAClB,UAAU,YAAY;AAAA,MACtB,UAAU,YAAY;AAAA,MACtB,QAAQ,YAAY;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,OAAO,sBAAsB,QAAyB;AACpD,UAAM,SAAS;AACf,UAAM,cAAc,OAAO,KAAK;AAChC,WAAO,UAAU,UAAU,UAAU;AAAA,EACvC;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport type {\n AuthEndpoint,\n AuthSubEndpoint,\n CookieEndpointConfig,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n SignInEndpointConfig,\n SignInSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\n\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_SESSION_COOKIE_OPTIONS: CookieOptions = {\n httpOnly: true,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 12 * 60 * 60 * 24, // twelve days\n priority: 'high',\n};\n\nexport const DEFAULT_ID_REFRESH_TOKEN_COOKIE_OPTIONS: CookieOptions = {\n httpOnly: true,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 12 * 60 * 60 * 24, // twelve days\n priority: 'high',\n};\n\n\nexport const FIXED_TOKEN_CONFIGS = {\n id: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600, // 1 hour\n },\n refresh: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 30, // 30 days (changes when user events occur)\n },\n signature: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n custom: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n} as const;\n\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n requireCSRF: true,\n allowedReferers: [],\n requiredHeaders: {},\n ipWhitelist: [],\n userAgent: {\n block: [],\n allow: [],\n },\n};\n\nexport const DEFAULT_ENDPOINT_CONFIG: EndpointConfig = {\n enabled: true,\n methods: ['GET', 'POST'],\n requireAuth: false,\n security: DEFAULT_SECURITY_OPTIONS,\n};\n\nexport const DEFAULT_COOKIE_REQUEST_CONFIG: CookieEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n get: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n },\n};\n\nexport const DEFAULT_SESSIONS_CONFIG: SessionEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n verify: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n createsession: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n },\n },\n refresh: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n revoke: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n },\n};\n\nexport const DEFAULT_SIGNINS_CONFIG: SignInEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n resetPasswordEmail: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false\n },\n },\n};\n\nexport const DEFAULT_HANDLER_OPTIONS: Required<TernSecureHandlerOptions> & {\n endpoints: Required<NonNullable<TernSecureHandlerOptions['endpoints']>>;\n} = {\n cors: DEFAULT_CORS_OPTIONS,\n cookies: DEFAULT_SESSION_COOKIE_OPTIONS,\n rateLimit: {\n windowMs: 15 * 60 * 1000, // 15 minutes\n maxRequests: 100,\n skipSuccessful: false,\n skipFailedRequests: false,\n },\n security: DEFAULT_SECURITY_OPTIONS,\n endpoints: {\n cookies: DEFAULT_COOKIE_REQUEST_CONFIG,\n sessions: DEFAULT_SESSIONS_CONFIG,\n signIns: DEFAULT_SIGNINS_CONFIG,\n },\n tenantId: '',\n revokeRefreshTokensOnSignOut: true,\n enableCustomToken: false,\n debug: false,\n environment: 'production',\n basePath: '/api/auth',\n};\n\nexport interface ValidationResult {\n error?: NextResponse;\n data?: any;\n}\n\nexport interface ValidationConfig {\n cors?: CorsOptions;\n security?: SecurityOptions;\n endpoint?: {\n name: AuthEndpoint;\n config: EndpointConfig;\n };\n subEndpoint?: {\n name: SessionSubEndpoint;\n config: EndpointConfig;\n };\n requireIdToken?: boolean;\n requireCsrfToken?: boolean;\n}\n\nexport interface ComprehensiveValidationResult {\n isValid: boolean;\n error?: Response;\n corsResponse?: Response;\n sessionData?: {\n body: any;\n idToken?: string;\n csrfToken?: string;\n };\n}\n\nexport type suffix = 'session' | 'id' | 'refresh' | 'signature' | 'custom';\n\nexport class CookieUtils {\n static getCookieName(namePrefix: string, tokenType: suffix): string {\n return `${namePrefix}.${tokenType}`;\n }\n\n static getCookieNames(namePrefix: string) {\n return {\n session: this.getCookieName(namePrefix, 'session'),\n id: this.getCookieName(namePrefix, 'id'),\n refresh: this.getCookieName(namePrefix, 'refresh'),\n signature: this.getCookieName(namePrefix, 'signature'),\n custom: this.getCookieName(namePrefix, 'custom'),\n };\n }\n\n static getSessionConfig(cookieOptions: CookieOptions): TokenCookieConfig {\n return {\n path: cookieOptions.path ?? '/',\n httpOnly: cookieOptions.httpOnly ?? true,\n sameSite: cookieOptions.sameSite ?? 'lax',\n maxAge: cookieOptions.maxAge ?? 3600 * 24 * 7,\n };\n }\n\n static getFixedTokenConfig(\n tokenType: Exclude<suffix, 'session'>,\n ): TokenCookieConfig {\n const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];\n\n return {\n path: fixedConfig.path,\n httpOnly: fixedConfig.httpOnly,\n sameSite: fixedConfig.sameSite,\n maxAge: fixedConfig.maxAge,\n };\n }\n\n static validateSessionMaxAge(maxAge: number): boolean {\n const minAge = 300; // 5 minutes\n const maxAgeLimit = 3600 * 24 * 14; // 2 weeks\n return maxAge >= minAge && maxAge <= maxAgeLimit;\n }\n}\n\n/**\n * API Handler Options - Unified with Middleware\n * \n * Since API routes are protected by middleware, they use the same\n * AuthenticateRequestOptions type. No separate config needed.\n * \n * Key fields used by API handlers:\n * - tenantId: Multi-tenant support\n * - enableCustomToken: Whether to create custom token cookie\n * - debug: Debug logging\n * - revokeRefreshTokensOnSignOut: Token revocation behavior\n * \n * Fields handled by middleware (not needed in API):\n * - firebaseConfig: Used for authentication\n * - firebaseAdminConfig: Server-side Firebase admin\n * - checkRevoked: Token revocation checking\n */\nexport type ApiHandlerOptions = AuthenticateRequestOptions & {\n cookies?: CookieOptions;\n};\n\nexport const DEFAULT_API_HANDLER_OPTIONS: Partial<ApiHandlerOptions> = {\n tenantId: undefined,\n cookies: DEFAULT_SESSION_COOKIE_OPTIONS,\n enableCustomToken: false,\n debug: false,\n revokeRefreshTokensOnSignOut: true,\n};\n\nexport {\n AuthEndpoint,\n AuthSubEndpoint,\n CookieOptions,\n CorsOptions,\n SecurityOptions,\n SessionSubEndpoint,\n EndpointConfig,\n SessionEndpointConfig,\n SignInEndpointConfig,\n SignInSubEndpoint,\n TernSecureHandlerOptions,\n};\n"],"mappings":"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","names":[]}
@@ -1,188 +1,110 @@
1
+ import { constants } from "@tern-secure/backend";
2
+ import { cookies } from "next/headers";
1
3
  import { createApiErrorResponse } from "./responses";
2
- class CorsValidator {
3
- static async validate(request, corsOptions) {
4
- const origin = request.headers.get("origin");
5
- const host = request.headers.get("host");
6
- if (!origin || host && origin.includes(host)) {
7
- return null;
8
- }
9
- if (corsOptions.allowedOrigins !== "*") {
10
- const isAllowed = corsOptions.allowedOrigins.some((allowedOrigin) => {
11
- if (allowedOrigin.startsWith("*")) {
12
- const domain = allowedOrigin.slice(1);
13
- return origin?.endsWith(domain);
14
- }
15
- return origin === allowedOrigin;
16
- });
17
- if (!isAllowed) {
18
- return createApiErrorResponse("CORS_ORIGIN_NOT_ALLOWED", "Origin not allowed", 403);
19
- }
20
- }
21
- return null;
4
+ async function validateJsonBody(request) {
5
+ try {
6
+ const body = await request.json();
7
+ return { body };
8
+ } catch (error) {
9
+ return {
10
+ body: null,
11
+ error: createApiErrorResponse("INVALID_REQUEST_FORMAT", "Invalid JSON in request body", 400)
12
+ };
22
13
  }
23
- static createOptionsResponse(corsOptions) {
24
- const response = new Response(null, { status: 204 });
25
- if (corsOptions.allowedOrigins === "*") {
26
- response.headers.set("Access-Control-Allow-Origin", "*");
27
- } else {
28
- response.headers.set("Access-Control-Allow-Origin", corsOptions.allowedOrigins.join(","));
29
- }
30
- response.headers.set(
31
- "Access-Control-Allow-Methods",
32
- corsOptions.allowedMethods?.join(",") || "GET,POST"
14
+ }
15
+ function validateIdToken(idToken) {
16
+ if (!idToken) {
17
+ return createApiErrorResponse(
18
+ "INVALID_TOKEN",
19
+ "ID token is required",
20
+ 400
33
21
  );
34
- response.headers.set(
35
- "Access-Control-Allow-Headers",
36
- corsOptions.allowedHeaders?.join(",") || "Content-Type,Authorization"
22
+ }
23
+ if (idToken.split(".").length !== 3) {
24
+ return createApiErrorResponse(
25
+ "INVALID_TOKEN_FORMAT",
26
+ "ID token must be a valid JWT",
27
+ 400
37
28
  );
38
- if (corsOptions.allowCredentials) {
39
- response.headers.set("Access-Control-Allow-Credentials", "true");
40
- }
41
- if (corsOptions.maxAge) {
42
- response.headers.set("Access-Control-Max-Age", corsOptions.maxAge.toString());
43
- }
44
- return response;
45
29
  }
30
+ return null;
46
31
  }
47
- class SecurityValidator {
48
- static async validate(request, securityOptions) {
49
- const origin = request.headers.get("origin");
50
- const host = request.headers.get("host");
51
- const referer = request.headers.get("referer");
52
- const userAgent = request.headers.get("user-agent") || "";
53
- const csrfResult = this.validateCsrf(request, securityOptions, origin, host, referer);
54
- if (csrfResult) return csrfResult;
55
- const headersResult = this.validateRequiredHeaders(request, securityOptions);
56
- if (headersResult) return headersResult;
57
- const userAgentResult = this.validateUserAgent(userAgent, securityOptions);
58
- if (userAgentResult) return userAgentResult;
59
- return null;
60
- }
61
- static validateCsrf(request, securityOptions, origin, host, referer) {
62
- if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {
63
- const hasCSRFHeader = request.headers.get("x-requested-with") === "XMLHttpRequest";
64
- const hasValidReferer = referer && host && referer.includes(host);
65
- if (!hasCSRFHeader && !hasValidReferer) {
66
- const isAllowedReferer = securityOptions.allowedReferers?.some(
67
- (allowedRef) => referer?.includes(allowedRef)
68
- );
69
- if (!isAllowedReferer) {
70
- return createApiErrorResponse("CSRF_PROTECTION", "Access denied", 403);
71
- }
72
- }
73
- }
74
- return null;
32
+ async function validateCsrfToken(csrfToken) {
33
+ if (!csrfToken) {
34
+ return createApiErrorResponse("INVALID_CSRF_TOKEN", "CSRF token is required", 400);
75
35
  }
76
- static validateRequiredHeaders(request, securityOptions) {
77
- if (securityOptions.requiredHeaders) {
78
- for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {
79
- const actualValue = request.headers.get(headerName);
80
- if (actualValue !== expectedValue) {
81
- return createApiErrorResponse(
82
- "INVALID_HEADERS",
83
- "Required header missing or invalid",
84
- 400
85
- );
86
- }
87
- }
88
- }
89
- return null;
36
+ const cookieStore = await cookies();
37
+ const csrfCookieValue = cookieStore.get(constants.Cookies.CsrfToken)?.value;
38
+ if (!csrfCookieValue) {
39
+ return createApiErrorResponse("CSRF_MISSING", "CSRF token cookie not found", 403);
90
40
  }
91
- static validateUserAgent(userAgent, securityOptions) {
92
- if (securityOptions.userAgent?.block?.length) {
93
- const isBlocked = securityOptions.userAgent.block.some(
94
- (blocked) => userAgent.toLowerCase().includes(blocked.toLowerCase())
95
- );
96
- if (isBlocked) {
97
- return createApiErrorResponse("USER_AGENT_BLOCKED", "Access denied", 403);
98
- }
99
- }
100
- if (securityOptions.userAgent?.allow?.length) {
101
- const isAllowed = securityOptions.userAgent.allow.some(
102
- (allowed) => userAgent.toLowerCase().includes(allowed.toLowerCase())
103
- );
104
- if (!isAllowed) {
105
- return createApiErrorResponse("USER_AGENT_NOT_ALLOWED", "Access denied", 403);
106
- }
107
- }
108
- return null;
41
+ if (csrfToken !== csrfCookieValue) {
42
+ return createApiErrorResponse("CSRF_TOKEN_MISMATCH", "CSRF token mismatch", 403);
109
43
  }
44
+ return null;
110
45
  }
111
- class CsrfValidator {
112
- static validate(csrfToken, csrfCookieValue) {
113
- if (!csrfToken) {
114
- return createApiErrorResponse("INVALID_CSRF_TOKEN", "CSRF token is required", 400);
115
- }
116
- if (!csrfCookieValue) {
117
- return createApiErrorResponse("CSRF_COOKIE_MISSING", "CSRF token cookie not found", 403);
118
- }
119
- if (csrfToken !== csrfCookieValue) {
120
- return createApiErrorResponse("CSRF_TOKEN_MISMATCH", "CSRF token mismatch", 403);
121
- }
122
- return null;
46
+ function validateEmail(email) {
47
+ if (!email || typeof email !== "string") {
48
+ return createApiErrorResponse("EMAIL_REQUIRED", "Email is required", 400);
123
49
  }
50
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
51
+ if (!emailRegex.test(email)) {
52
+ return createApiErrorResponse("INVALID_EMAIL", "Invalid email format", 400);
53
+ }
54
+ return null;
124
55
  }
125
- class RouteValidator {
126
- static validatePathStructure(pathSegments) {
127
- if (pathSegments.length < 3) {
128
- return createApiErrorResponse(
129
- "INVALID_ROUTE",
130
- "Invalid route structure. Expected: /api/auth/{endpoint}",
131
- 404
132
- );
133
- }
134
- return null;
56
+ function validatePassword(password) {
57
+ if (!password || typeof password !== "string") {
58
+ return createApiErrorResponse("PASSWORD_REQUIRED", "Password is required", 400);
135
59
  }
136
- static validateEndpoint(_endpoint, endpointConfig, method) {
137
- if (!endpointConfig || !endpointConfig.enabled) {
138
- return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
139
- }
140
- if (method !== "OPTIONS" && !endpointConfig.methods.includes(method)) {
141
- return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
142
- }
143
- return null;
60
+ if (password.length < 6) {
61
+ return createApiErrorResponse(
62
+ "PASSWORD_TOO_SHORT",
63
+ "Password must be at least 6 characters",
64
+ 400
65
+ );
144
66
  }
145
- static validateSubEndpoint(subEndpoint, subEndpointConfig, method) {
146
- if (!subEndpoint) {
147
- return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
148
- }
149
- if (!subEndpointConfig || !subEndpointConfig.enabled) {
150
- return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
151
- }
152
- if (!subEndpointConfig.methods?.includes(method)) {
153
- return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
154
- }
155
- return null;
67
+ return null;
68
+ }
69
+ function validateRequiredFields(body, fields) {
70
+ const missingFields = fields.filter((field) => !body[field]);
71
+ if (missingFields.length > 0) {
72
+ return createApiErrorResponse(
73
+ "MISSING_REQUIRED_FIELDS",
74
+ `Missing required fields: ${missingFields.join(", ")}`,
75
+ 400
76
+ );
156
77
  }
78
+ return null;
157
79
  }
158
- class RequestValidator {
159
- static async validateSessionRequest(request) {
160
- try {
161
- const body = await request.json();
162
- return { body, idToken: body.idToken, csrfToken: body.csrfToken };
163
- } catch (error) {
164
- return {
165
- body: null,
166
- error: createApiErrorResponse("INVALID_REQUEST_FORMAT", "Invalid request format", 400)
167
- };
168
- }
80
+ function validateSubEndpointPresent(context, endpointType) {
81
+ if (!context.subEndpoint) {
82
+ return createApiErrorResponse(
83
+ "SUB_ENDPOINT_REQUIRED",
84
+ `${endpointType} sub-endpoint required`,
85
+ 400
86
+ );
169
87
  }
170
- static validateIdToken(idToken) {
171
- if (!idToken) {
172
- return createApiErrorResponse(
173
- "INVALID_TOKEN",
174
- "ID token is required for creating session",
175
- 400
176
- );
177
- }
178
- return null;
88
+ return null;
89
+ }
90
+ async function extractSessionRequestData(request) {
91
+ const { body, error } = await validateJsonBody(request);
92
+ if (error) {
93
+ return { error };
179
94
  }
95
+ return {
96
+ idToken: body.idToken,
97
+ csrfToken: body.csrfToken
98
+ };
180
99
  }
181
100
  export {
182
- CorsValidator,
183
- CsrfValidator,
184
- RequestValidator,
185
- RouteValidator,
186
- SecurityValidator
101
+ extractSessionRequestData,
102
+ validateCsrfToken,
103
+ validateEmail,
104
+ validateIdToken,
105
+ validateJsonBody,
106
+ validatePassword,
107
+ validateRequiredFields,
108
+ validateSubEndpointPresent
187
109
  };
188
110
  //# sourceMappingURL=validators.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/validators.ts"],"sourcesContent":["import { createApiErrorResponse } from './responses';\nimport type { AuthEndpoint, CorsOptions, SecurityOptions, SessionSubEndpoint } from './types';\n\n/**\n * CORS validation utilities\n */\nexport class CorsValidator {\n static async validate(\n request: Request,\n corsOptions: CorsOptions,\n ): Promise<Response | null> {\n const origin = request.headers.get('origin');\n const host = request.headers.get('host');\n\n // Skip CORS for same-origin requests\n if (!origin || (host && origin.includes(host))) {\n return null;\n }\n\n if (corsOptions.allowedOrigins !== '*') {\n const isAllowed = corsOptions.allowedOrigins.some(allowedOrigin => {\n if (allowedOrigin.startsWith('*')) {\n const domain = allowedOrigin.slice(1);\n return origin?.endsWith(domain);\n }\n return origin === allowedOrigin;\n });\n\n if (!isAllowed) {\n return createApiErrorResponse('CORS_ORIGIN_NOT_ALLOWED', 'Origin not allowed', 403);\n }\n }\n\n return null;\n }\n\n static createOptionsResponse(corsOptions: CorsOptions): Response {\n const response = new Response(null, { status: 204 });\n\n if (corsOptions.allowedOrigins === '*') {\n response.headers.set('Access-Control-Allow-Origin', '*');\n } else {\n response.headers.set('Access-Control-Allow-Origin', corsOptions.allowedOrigins.join(','));\n }\n\n response.headers.set(\n 'Access-Control-Allow-Methods',\n corsOptions.allowedMethods?.join(',') || 'GET,POST',\n );\n response.headers.set(\n 'Access-Control-Allow-Headers',\n corsOptions.allowedHeaders?.join(',') || 'Content-Type,Authorization',\n );\n\n if (corsOptions.allowCredentials) {\n response.headers.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (corsOptions.maxAge) {\n response.headers.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n\n return response;\n }\n}\n\n/**\n * Security validation utilities\n */\nexport class SecurityValidator {\n static async validate(\n request: Request,\n securityOptions: SecurityOptions,\n ): Promise<Response | null> {\n const origin = request.headers.get('origin');\n const host = request.headers.get('host');\n const referer = request.headers.get('referer');\n const userAgent = request.headers.get('user-agent') || '';\n\n // CSRF Protection for cross-origin requests\n const csrfResult = this.validateCsrf(request, securityOptions, origin, host, referer);\n if (csrfResult) return csrfResult;\n\n // Required headers validation\n const headersResult = this.validateRequiredHeaders(request, securityOptions);\n if (headersResult) return headersResult;\n\n // User Agent filtering\n const userAgentResult = this.validateUserAgent(userAgent, securityOptions);\n if (userAgentResult) return userAgentResult;\n\n return null;\n }\n\n private static validateCsrf(\n request: Request,\n securityOptions: SecurityOptions,\n origin: string | null,\n host: string | null,\n referer: string | null,\n ): Response | null {\n if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {\n const hasCSRFHeader = request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referer && host && referer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referer?.includes(allowedRef),\n );\n\n if (!isAllowedReferer) {\n return createApiErrorResponse('CSRF_PROTECTION', 'Access denied', 403);\n }\n }\n }\n return null;\n }\n\n private static validateRequiredHeaders(\n request: Request,\n securityOptions: SecurityOptions,\n ): Response | null {\n if (securityOptions.requiredHeaders) {\n for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {\n const actualValue = request.headers.get(headerName);\n if (actualValue !== expectedValue) {\n return createApiErrorResponse(\n 'INVALID_HEADERS',\n 'Required header missing or invalid',\n 400,\n );\n }\n }\n }\n return null;\n }\n\n private static validateUserAgent(\n userAgent: string,\n securityOptions: SecurityOptions,\n ): Response | null {\n // User Agent blocking\n if (securityOptions.userAgent?.block?.length) {\n const isBlocked = securityOptions.userAgent.block.some((blocked: string) =>\n userAgent.toLowerCase().includes(blocked.toLowerCase()),\n );\n\n if (isBlocked) {\n return createApiErrorResponse('USER_AGENT_BLOCKED', 'Access denied', 403);\n }\n }\n\n // User Agent allowlist\n if (securityOptions.userAgent?.allow?.length) {\n const isAllowed = securityOptions.userAgent.allow.some((allowed: string) =>\n userAgent.toLowerCase().includes(allowed.toLowerCase()),\n );\n\n if (!isAllowed) {\n return createApiErrorResponse('USER_AGENT_NOT_ALLOWED', 'Access denied', 403);\n }\n }\n\n return null;\n }\n}\n\n/**\n * CSRF token validation utilities\n */\nexport class CsrfValidator {\n static validate(csrfToken: string, csrfCookieValue: string | undefined): Response | null {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_COOKIE_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n }\n}\n\n/**\n * Route validation utilities\n */\nexport class RouteValidator {\n static validatePathStructure(pathSegments: string[]): Response | null {\n if (pathSegments.length < 3) {\n return createApiErrorResponse(\n 'INVALID_ROUTE',\n 'Invalid route structure. Expected: /api/auth/{endpoint}',\n 404,\n );\n }\n return null;\n }\n\n static validateEndpoint(\n _endpoint: AuthEndpoint,\n endpointConfig: any,\n method: string,\n ): Response | null {\n if (!endpointConfig || !endpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (method !== 'OPTIONS' && !endpointConfig.methods.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n static validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n method: string,\n ): Response | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n}\n\n/**\n * Request body validation utilities\n */\nexport class RequestValidator {\n static async validateSessionRequest(request: Request): Promise<{\n body: any;\n idToken?: string;\n csrfToken?: string;\n error?: Response;\n }> {\n try {\n const body = await request.json();\n return { body, idToken: body.idToken, csrfToken: body.csrfToken };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid request format', 400),\n };\n }\n }\n\n static validateIdToken(idToken: string | undefined): Response | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required for creating session',\n 400,\n );\n }\n return null;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/validators.ts"],"sourcesContent":["import type { RequestProcessorContext } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend'\nimport { cookies } from 'next/headers';\n\nimport { createApiErrorResponse } from './responses';\n\n/**\n * Lightweight validators for API route handlers\n * Note: Middleware already handles CORS, security, and CSRF validation\n * These validators only handle endpoint-specific validation\n */\n\n/**\n * Validates that the request body is valid JSON\n */\nexport async function validateJsonBody(request: Request): Promise<{\n body: any;\n error?: Response;\n}> {\n try {\n const body = await request.json();\n return { body };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid JSON in request body', 400),\n };\n }\n}\n\n/**\n * Validates that an ID token is present and has correct JWT structure\n */\nexport function validateIdToken(idToken: string | undefined): Response | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required',\n 400,\n );\n }\n \n if (idToken.split('.').length !== 3) {\n return createApiErrorResponse(\n 'INVALID_TOKEN_FORMAT',\n 'ID token must be a valid JWT',\n 400,\n );\n }\n \n return null;\n}\n\n/**\n * Validates CSRF token matches the cookie value\n * Note: This is only used for specific endpoints that need double-submit CSRF\n */\nexport async function validateCsrfToken(\n csrfToken: string | undefined,\n): Promise<Response | null> {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n const cookieStore = await cookies();\n const csrfCookieValue = cookieStore.get(constants.Cookies.CsrfToken)?.value;\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n}\n\n/**\n * Validates email format (basic validation)\n */\nexport function validateEmail(email: string | undefined): Response | null {\n if (!email || typeof email !== 'string') {\n return createApiErrorResponse('EMAIL_REQUIRED', 'Email is required', 400);\n }\n\n // Basic email validation\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n if (!emailRegex.test(email)) {\n return createApiErrorResponse('INVALID_EMAIL', 'Invalid email format', 400);\n }\n\n return null;\n}\n\n/**\n * Validates password meets minimum requirements\n */\nexport function validatePassword(password: string | undefined): Response | null {\n if (!password || typeof password !== 'string') {\n return createApiErrorResponse('PASSWORD_REQUIRED', 'Password is required', 400);\n }\n\n if (password.length < 6) {\n return createApiErrorResponse(\n 'PASSWORD_TOO_SHORT',\n 'Password must be at least 6 characters',\n 400,\n );\n }\n\n return null;\n}\n\n/**\n * Validates required fields are present in request body\n */\nexport function validateRequiredFields(\n body: any,\n fields: string[],\n): Response | null {\n const missingFields = fields.filter(field => !body[field]);\n \n if (missingFields.length > 0) {\n return createApiErrorResponse(\n 'MISSING_REQUIRED_FIELDS',\n `Missing required fields: ${missingFields.join(', ')}`,\n 400,\n );\n }\n\n return null;\n}\n\n/**\n * Validates that a sub-endpoint exists in the URL\n */\nexport function validateSubEndpointPresent(\n context: RequestProcessorContext,\n endpointType: string,\n): Response | null {\n if (!context.subEndpoint) {\n return createApiErrorResponse(\n 'SUB_ENDPOINT_REQUIRED',\n `${endpointType} sub-endpoint required`,\n 400,\n );\n }\n \n return null;\n}\n\n/**\n * Helper to extract and validate session request data\n */\nexport async function extractSessionRequestData(request: Request): Promise<{\n idToken?: string;\n csrfToken?: string;\n error?: Response;\n}> {\n const { body, error } = await validateJsonBody(request);\n \n if (error) {\n return { error };\n }\n\n return {\n idToken: body.idToken,\n csrfToken: body.csrfToken,\n };\n}\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AAExB,SAAS,8BAA8B;AAWvC,eAAsB,iBAAiB,SAGpC;AACD,MAAI;AACF,UAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,WAAO,EAAE,KAAK;AAAA,EAChB,SAAS,OAAO;AACd,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,uBAAuB,0BAA0B,gCAAgC,GAAG;AAAA,IAC7F;AAAA,EACF;AACF;AAKO,SAAS,gBAAgB,SAA8C;AAC5E,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,MAAM,GAAG,EAAE,WAAW,GAAG;AACnC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,eAAsB,kBACpB,WAC0B;AAC1B,MAAI,CAAC,WAAW;AACd,WAAO,uBAAuB,sBAAsB,0BAA0B,GAAG;AAAA,EACnF;AAEA,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,kBAAkB,YAAY,IAAI,UAAU,QAAQ,SAAS,GAAG;AAEtE,MAAI,CAAC,iBAAiB;AACpB,WAAO,uBAAuB,gBAAgB,+BAA+B,GAAG;AAAA,EAClF;AAEA,MAAI,cAAc,iBAAiB;AACjC,WAAO,uBAAuB,uBAAuB,uBAAuB,GAAG;AAAA,EACjF;AAEA,SAAO;AACT;AAKO,SAAS,cAAc,OAA4C;AACxE,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,WAAO,uBAAuB,kBAAkB,qBAAqB,GAAG;AAAA,EAC1E;AAGA,QAAM,aAAa;AACnB,MAAI,CAAC,WAAW,KAAK,KAAK,GAAG;AAC3B,WAAO,uBAAuB,iBAAiB,wBAAwB,GAAG;AAAA,EAC5E;AAEA,SAAO;AACT;AAKO,SAAS,iBAAiB,UAA+C;AAC9E,MAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC7C,WAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,EAChF;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,uBACd,MACA,QACiB;AACjB,QAAM,gBAAgB,OAAO,OAAO,WAAS,CAAC,KAAK,KAAK,CAAC;AAEzD,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO;AAAA,MACL;AAAA,MACA,4BAA4B,cAAc,KAAK,IAAI,CAAC;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,2BACd,SACA,cACiB;AACjB,MAAI,CAAC,QAAQ,aAAa;AACxB,WAAO;AAAA,MACL;AAAA,MACA,GAAG,YAAY;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,0BAA0B,SAI7C;AACD,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,iBAAiB,OAAO;AAEtD,MAAI,OAAO;AACT,WAAO,EAAE,MAAM;AAAA,EACjB;AAEA,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,WAAW,KAAK;AAAA,EAClB;AACF;","names":[]}
@@ -1,16 +1,22 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
+ import { headers } from "next/headers";
2
3
  import React from "react";
3
4
  import { PromiseAuthProvider } from "../../boundary/PromiseAuthProvider";
4
5
  import { getTernSecureAuthData } from "../../server/data/getAuthDataFromRequest";
5
6
  import { isNext13 } from "../../server/sdk-versions";
6
7
  import { allNextProviderPropsWithEnv } from "../../utils/allNextProviderProps";
7
8
  import { ClientTernSecureProvider } from "../client/TernSecureProvider";
8
- import { buildRequestLike } from "./utils";
9
+ import { buildRequestLike, getScriptNonceFromHeader } from "./utils";
9
10
  const getTernSecureState = React.cache(async function getTernSecureState2() {
10
11
  const request = await buildRequestLike();
11
12
  const data = getTernSecureAuthData(request);
12
13
  return data;
13
14
  });
15
+ const getNonceHeaders = React.cache(async function getNonceHeaders2() {
16
+ const headersList = await headers();
17
+ const nonce = headersList.get("X-Nonce");
18
+ return nonce ? nonce : getScriptNonceFromHeader(headersList.get("Content-Security-Policy") || "") || "";
19
+ });
14
20
  async function TernSecureProvider(props) {
15
21
  const { children, ...rest } = props;
16
22
  const { persistence } = rest;
@@ -24,6 +30,15 @@ async function TernSecureProvider(props) {
24
30
  }
25
31
  return getTernSecureState();
26
32
  }
33
+ async function generateNonce() {
34
+ if (!browserCookiePersistence) {
35
+ return Promise.resolve("");
36
+ }
37
+ if (isNext13) {
38
+ return Promise.resolve(await getNonceHeaders());
39
+ }
40
+ return getNonceHeaders();
41
+ }
27
42
  const providerProps = allNextProviderPropsWithEnv({ ...rest });
28
43
  let output;
29
44
  if (browserCookiePersistence) {
@@ -35,6 +50,7 @@ async function TernSecureProvider(props) {
35
50
  ClientTernSecureProvider,
36
51
  {
37
52
  ...providerProps,
53
+ nonce: await generateNonce(),
38
54
  initialState: await generateStatePromise(),
39
55
  children
40
56
  }
@@ -46,6 +62,8 @@ async function TernSecureProvider(props) {
46
62
  ClientTernSecureProvider,
47
63
  {
48
64
  ...providerProps,
65
+ nonce: await generateNonce(),
66
+ initialState: await getTernSecureState(),
49
67
  children
50
68
  }
51
69
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/TernSecureProvider.tsx"],"sourcesContent":["import type { TernSecureInitialState } from '@tern-secure/types';\nimport type { ReactNode } from 'react';\nimport React from 'react';\n\nimport { PromiseAuthProvider } from '../../boundary/PromiseAuthProvider';\nimport { getTernSecureAuthData } from '../../server/data/getAuthDataFromRequest';\nimport { isNext13 } from '../../server/sdk-versions';\nimport type { TernSecureNextProps } from '../../types';\nimport { allNextProviderPropsWithEnv } from '../../utils/allNextProviderProps';\nimport { ClientTernSecureProvider } from '../client/TernSecureProvider';\nimport { buildRequestLike } from './utils';\n\nconst getTernSecureState = React.cache(async function getTernSecureState() {\n const request = await buildRequestLike();\n const data = getTernSecureAuthData(request);\n return data;\n});\n\nexport async function TernSecureProvider(props: TernSecureNextProps) {\n const { children, ...rest } = props;\n const { persistence } = rest;\n\n const browserCookiePersistence = persistence === 'browserCookie';\n\n async function generateStatePromise() {\n if (!browserCookiePersistence) {\n return Promise.resolve(undefined);\n }\n if (isNext13) {\n return Promise.resolve(await getTernSecureState());\n }\n return getTernSecureState();\n }\n\n const providerProps = allNextProviderPropsWithEnv({ ...rest });\n\n let output: ReactNode;\n\n if (browserCookiePersistence) {\n output = (\n <PromiseAuthProvider\n authPromise={generateStatePromise() as unknown as Promise<TernSecureInitialState>}\n >\n <ClientTernSecureProvider\n {...providerProps}\n initialState={await generateStatePromise()}\n >\n {children}\n </ClientTernSecureProvider>\n </PromiseAuthProvider>\n );\n } else {\n output = (\n <ClientTernSecureProvider\n {...providerProps}\n >\n {children}\n </ClientTernSecureProvider>\n );\n }\n\n return output;\n}\n"],"mappings":"AA2CQ;AAzCR,OAAO,WAAW;AAElB,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,gBAAgB;AAEzB,SAAS,mCAAmC;AAC5C,SAAS,gCAAgC;AACzC,SAAS,wBAAwB;AAEjC,MAAM,qBAAqB,MAAM,MAAM,eAAeA,sBAAqB;AACzE,QAAM,UAAU,MAAM,iBAAiB;AACvC,QAAM,OAAO,sBAAsB,OAAO;AAC1C,SAAO;AACT,CAAC;AAED,eAAsB,mBAAmB,OAA4B;AACnE,QAAM,EAAE,UAAU,GAAG,KAAK,IAAI;AAC9B,QAAM,EAAE,YAAY,IAAI;AAExB,QAAM,2BAA2B,gBAAgB;AAEjD,iBAAe,uBAAuB;AACpC,QAAI,CAAC,0BAA0B;AAC7B,aAAO,QAAQ,QAAQ,MAAS;AAAA,IAClC;AACA,QAAI,UAAU;AACZ,aAAO,QAAQ,QAAQ,MAAM,mBAAmB,CAAC;AAAA,IACnD;AACA,WAAO,mBAAmB;AAAA,EAC5B;AAEA,QAAM,gBAAgB,4BAA4B,EAAE,GAAG,KAAK,CAAC;AAE7D,MAAI;AAEJ,MAAI,0BAA0B;AAC5B,aACE;AAAA,MAAC;AAAA;AAAA,QACC,aAAa,qBAAqB;AAAA,QAElC;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,cAAc,MAAM,qBAAqB;AAAA,YAExC;AAAA;AAAA,QACH;AAAA;AAAA,IACF;AAAA,EAEJ,OAAO;AACL,aACE;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,SAAO;AACT;","names":["getTernSecureState"]}
1
+ {"version":3,"sources":["../../../../src/app-router/server/TernSecureProvider.tsx"],"sourcesContent":["import type { TernSecureInitialState } from '@tern-secure/types';\nimport { headers } from 'next/headers';\nimport type { ReactNode } from 'react';\nimport React from 'react';\n\nimport { PromiseAuthProvider } from '../../boundary/PromiseAuthProvider';\nimport { getTernSecureAuthData } from '../../server/data/getAuthDataFromRequest';\nimport { isNext13 } from '../../server/sdk-versions';\nimport type { TernSecureNextProps } from '../../types';\nimport { allNextProviderPropsWithEnv } from '../../utils/allNextProviderProps';\nimport { ClientTernSecureProvider } from '../client/TernSecureProvider';\nimport { buildRequestLike, getScriptNonceFromHeader } from './utils';\n\nconst getTernSecureState = React.cache(async function getTernSecureState() {\n const request = await buildRequestLike();\n const data = getTernSecureAuthData(request);\n\n return data;\n});\n\nconst getNonceHeaders = React.cache(async function getNonceHeaders() {\n const headersList = await headers();\n const nonce = headersList.get('X-Nonce');\n return nonce \n ? nonce\n : getScriptNonceFromHeader(headersList.get('Content-Security-Policy') || '') || '';\n});\n\nexport async function TernSecureProvider(props: TernSecureNextProps) {\n const { children, ...rest } = props;\n const { persistence } = rest;\n\n const browserCookiePersistence = persistence === 'browserCookie';\n\n async function generateStatePromise() {\n if (!browserCookiePersistence) {\n return Promise.resolve(undefined);\n }\n if (isNext13) {\n return Promise.resolve(await getTernSecureState());\n }\n return getTernSecureState();\n }\n\n async function generateNonce() {\n if (!browserCookiePersistence) {\n return Promise.resolve('');\n }\n if (isNext13) {\n return Promise.resolve(await getNonceHeaders());\n }\n return getNonceHeaders();\n }\n\n const providerProps = allNextProviderPropsWithEnv({ ...rest });\n\n let output: ReactNode;\n\n if (browserCookiePersistence) {\n output = (\n <PromiseAuthProvider\n authPromise={generateStatePromise() as unknown as Promise<TernSecureInitialState>}\n >\n <ClientTernSecureProvider\n {...providerProps}\n nonce={await generateNonce()}\n initialState={await generateStatePromise()}\n >\n {children}\n </ClientTernSecureProvider>\n </PromiseAuthProvider>\n );\n } else {\n output = (\n <ClientTernSecureProvider\n {...providerProps}\n nonce={await generateNonce()}\n initialState={await getTernSecureState()}\n >\n {children}\n </ClientTernSecureProvider>\n );\n }\n\n return output;\n}\n"],"mappings":"AA+DQ;AA9DR,SAAS,eAAe;AAExB,OAAO,WAAW;AAElB,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,gBAAgB;AAEzB,SAAS,mCAAmC;AAC5C,SAAS,gCAAgC;AACzC,SAAS,kBAAkB,gCAAgC;AAE3D,MAAM,qBAAqB,MAAM,MAAM,eAAeA,sBAAqB;AACzE,QAAM,UAAU,MAAM,iBAAiB;AACvC,QAAM,OAAO,sBAAsB,OAAO;AAE1C,SAAO;AACT,CAAC;AAED,MAAM,kBAAkB,MAAM,MAAM,eAAeC,mBAAkB;AACnE,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,QAAQ,YAAY,IAAI,SAAS;AACvC,SAAO,QACH,QACA,yBAAyB,YAAY,IAAI,yBAAyB,KAAK,EAAE,KAAK;AACpF,CAAC;AAED,eAAsB,mBAAmB,OAA4B;AACnE,QAAM,EAAE,UAAU,GAAG,KAAK,IAAI;AAC9B,QAAM,EAAE,YAAY,IAAI;AAExB,QAAM,2BAA2B,gBAAgB;AAEjD,iBAAe,uBAAuB;AACpC,QAAI,CAAC,0BAA0B;AAC7B,aAAO,QAAQ,QAAQ,MAAS;AAAA,IAClC;AACA,QAAI,UAAU;AACZ,aAAO,QAAQ,QAAQ,MAAM,mBAAmB,CAAC;AAAA,IACnD;AACA,WAAO,mBAAmB;AAAA,EAC5B;AAEA,iBAAe,gBAAgB;AAC7B,QAAI,CAAC,0BAA0B;AAC7B,aAAO,QAAQ,QAAQ,EAAE;AAAA,IAC3B;AACA,QAAI,UAAU;AACZ,aAAO,QAAQ,QAAQ,MAAM,gBAAgB,CAAC;AAAA,IAChD;AACA,WAAO,gBAAgB;AAAA,EACzB;AAEA,QAAM,gBAAgB,4BAA4B,EAAE,GAAG,KAAK,CAAC;AAE7D,MAAI;AAEJ,MAAI,0BAA0B;AAC5B,aACE;AAAA,MAAC;AAAA;AAAA,QACC,aAAa,qBAAqB;AAAA,QAElC;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ,OAAO,MAAM,cAAc;AAAA,YAC3B,cAAc,MAAM,qBAAqB;AAAA,YAExC;AAAA;AAAA,QACH;AAAA;AAAA,IACF;AAAA,EAEJ,OAAO;AACL,aACE;AAAA,MAAC;AAAA;AAAA,QACE,GAAG;AAAA,QACJ,OAAO,MAAM,cAAc;AAAA,QAC3B,cAAc,MAAM,mBAAmB;AAAA,QAEtC;AAAA;AAAA,IACH;AAAA,EAEJ;AAEA,SAAO;AACT;","names":["getTernSecureState","getNonceHeaders"]}
@@ -5,6 +5,8 @@ const FIREBASE_STORAGE_BUCKET = process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET
5
5
  const FIREBASE_MESSAGING_SENDER_ID = process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || "";
6
6
  const FIREBASE_APP_ID = process.env.NEXT_PUBLIC_FIREBASE_APP_ID || "";
7
7
  const FIREBASE_MEASUREMENT_ID = process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || "";
8
+ const FIREBASE_CLIENT_EMAIL = process.env.FIREBASE_CLIENT_EMAIL || "";
9
+ const FIREBASE_PRIVATE_KEY = process.env.FIREBASE_PRIVATE_KEY;
8
10
  const API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || "";
9
11
  const API_URL = process.env.TERNSECURE_API_URL || "";
10
12
  const API_VERSION = process.env.TERNSECURE_API_VERSION || "v1";
@@ -17,8 +19,10 @@ export {
17
19
  FIREBASE_API_KEY,
18
20
  FIREBASE_APP_ID,
19
21
  FIREBASE_AUTH_DOMAIN,
22
+ FIREBASE_CLIENT_EMAIL,
20
23
  FIREBASE_MEASUREMENT_ID,
21
24
  FIREBASE_MESSAGING_SENDER_ID,
25
+ FIREBASE_PRIVATE_KEY,
22
26
  FIREBASE_PROJECT_ID,
23
27
  FIREBASE_STORAGE_BUCKET,
24
28
  SIGN_IN_URL,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/constant.ts"],"sourcesContent":["export const FIREBASE_API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '';\nexport const FIREBASE_AUTH_DOMAIN = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '';\nexport const FIREBASE_PROJECT_ID = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '';\nexport const FIREBASE_STORAGE_BUCKET = process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '';\nexport const FIREBASE_MESSAGING_SENDER_ID = process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '';\nexport const FIREBASE_APP_ID = process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '';\nexport const FIREBASE_MEASUREMENT_ID = process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || '';\n\nexport const API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '';\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":"AAAO,MAAM,mBAAmB,QAAQ,IAAI,gCAAgC;AACrE,MAAM,uBAAuB,QAAQ,IAAI,oCAAoC;AAC7E,MAAM,sBAAsB,QAAQ,IAAI,mCAAmC;AAC3E,MAAM,0BAA0B,QAAQ,IAAI,uCAAuC;AACnF,MAAM,+BAA+B,QAAQ,IAAI,4CAA4C;AAC7F,MAAM,kBAAkB,QAAQ,IAAI,+BAA+B;AACnE,MAAM,0BAA0B,QAAQ,IAAI,uCAAuC;AAEnF,MAAM,UAAU,QAAQ,IAAI,gCAAgC;AAC5D,MAAM,UAAU,QAAQ,IAAI,sBAAsB;AAClD,MAAM,cAAc,QAAQ,IAAI,0BAA0B;AAC1D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;AAC3D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/constant.ts"],"sourcesContent":["export const FIREBASE_API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '';\nexport const FIREBASE_AUTH_DOMAIN = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '';\nexport const FIREBASE_PROJECT_ID = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '';\nexport const FIREBASE_STORAGE_BUCKET = process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '';\nexport const FIREBASE_MESSAGING_SENDER_ID = process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '';\nexport const FIREBASE_APP_ID = process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '';\nexport const FIREBASE_MEASUREMENT_ID = process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || '';\n\nexport const FIREBASE_CLIENT_EMAIL = process.env.FIREBASE_CLIENT_EMAIL || '';\nexport const FIREBASE_PRIVATE_KEY = process.env.FIREBASE_PRIVATE_KEY\n\nexport const API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '';\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":"AAAO,MAAM,mBAAmB,QAAQ,IAAI,gCAAgC;AACrE,MAAM,uBAAuB,QAAQ,IAAI,oCAAoC;AAC7E,MAAM,sBAAsB,QAAQ,IAAI,mCAAmC;AAC3E,MAAM,0BAA0B,QAAQ,IAAI,uCAAuC;AACnF,MAAM,+BAA+B,QAAQ,IAAI,4CAA4C;AAC7F,MAAM,kBAAkB,QAAQ,IAAI,+BAA+B;AACnE,MAAM,0BAA0B,QAAQ,IAAI,uCAAuC;AAEnF,MAAM,wBAAwB,QAAQ,IAAI,yBAAyB;AACnE,MAAM,uBAAuB,QAAQ,IAAI;AAEzC,MAAM,UAAU,QAAQ,IAAI,gCAAgC;AAC5D,MAAM,UAAU,QAAQ,IAAI,sBAAsB;AAClD,MAAM,cAAc,QAAQ,IAAI,0BAA0B;AAC1D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;AAC3D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;","names":[]}