@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
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var proxy_storage_exports = {};
20
+ __export(proxy_storage_exports, {
21
+ ternSecureProxyRequestDataStorage: () => ternSecureProxyRequestDataStorage,
22
+ ternSecureProxyRequestDataStore: () => ternSecureProxyRequestDataStore
23
+ });
24
+ module.exports = __toCommonJS(proxy_storage_exports);
25
+ var import_node_async_hooks = require("node:async_hooks");
26
+ const ternSecureProxyRequestDataStore = /* @__PURE__ */ new Map();
27
+ const ternSecureProxyRequestDataStorage = new import_node_async_hooks.AsyncLocalStorage();
28
+ // Annotate the CommonJS export names for ESM import in node:
29
+ 0 && (module.exports = {
30
+ ternSecureProxyRequestDataStorage,
31
+ ternSecureProxyRequestDataStore
32
+ });
33
+ //# sourceMappingURL=proxy-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/proxy-storage.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks';\n\nimport type { AuthenticateRequestOptions } from '@tern-secure/backend';\n\nexport const ternSecureProxyRequestDataStore = new Map<'requestData', AuthenticateRequestOptions>();\nexport const ternSecureProxyRequestDataStorage = new AsyncLocalStorage<typeof ternSecureProxyRequestDataStore>();"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAAkC;AAI3B,MAAM,kCAAkC,oBAAI,IAA+C;AAC3F,MAAM,oCAAoC,IAAI,0CAA0D;","names":[]}
@@ -41,20 +41,10 @@ const ternSecureProxy = ((...args) => {
41
41
  const signInUrl = resolvedParams.signInUrl || import_constant.SIGN_IN_URL;
42
42
  const signUpUrl = resolvedParams.signUpUrl || import_constant.SIGN_UP_URL;
43
43
  const apiKey = resolvedParams.apiKey || import_constant.FIREBASE_API_KEY;
44
- const appId = import_constant.FIREBASE_APP_ID;
45
- const projectId = import_constant.FIREBASE_PROJECT_ID;
46
- const firebaseConfig = resolvedParams.firebaseConfig || {
47
- apiKey,
48
- appId,
49
- projectId
50
- };
51
- const firebaseAdminConfig = resolvedParams.firebaseAdminConfig;
52
44
  const options = {
53
45
  signInUrl,
54
46
  signUpUrl,
55
47
  apiKey,
56
- firebaseConfig,
57
- firebaseAdminConfig,
58
48
  ...resolvedParams
59
49
  };
60
50
  const reqBackendClient = await (0, import_ternsecureClient.ternSecureBackendClient)();
@@ -63,9 +53,8 @@ const ternSecureProxy = ((...args) => {
63
53
  ternSecureRequest,
64
54
  options
65
55
  );
66
- const locationHeader = requestStateClient.headers.get(import_backend.constants.Headers.Location);
67
56
  const appCheckToken = requestStateClient.headers.get(import_backend.constants.Headers.AppCheckToken);
68
- console.log("[ternSecureProxy] App Check Token in Proxy:", appCheckToken);
57
+ const locationHeader = requestStateClient.headers.get(import_backend.constants.Headers.Location);
69
58
  if (locationHeader) {
70
59
  return new Response(null, {
71
60
  status: 307,
@@ -103,7 +92,7 @@ const ternSecureProxy = ((...args) => {
103
92
  if ((0, import_response.isRedirect)(handlerResult)) {
104
93
  return (0, import_serverRedirectAuth.serverRedirectWithAuth)(ternSecureRequest, handlerResult);
105
94
  }
106
- (0, import_utils.decorateRequest)(ternSecureRequest, handlerResult, requestStateClient, appCheckToken || void 0);
95
+ (0, import_utils.decorateRequest)(ternSecureRequest, handlerResult, requestStateClient, resolvedParams, appCheckToken || void 0);
107
96
  return handlerResult;
108
97
  };
109
98
  const nextMiddleware = async (request2, event2) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/ternSecureProxy.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n RedirectFun,\r\n RequestState,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { AuthStatus, constants, createRedirect, createTernSecureRequest } from '@tern-secure/backend';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware, NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { FIREBASE_API_KEY, FIREBASE_APP_ID, FIREBASE_PROJECT_ID,SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect, createProtect } from './protect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends AuthenticateRequestOptions {\r\n debug?: boolean;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureProxy = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n const apiKey = resolvedParams.apiKey || FIREBASE_API_KEY;\r\n const appId = FIREBASE_APP_ID;\r\n const projectId = FIREBASE_PROJECT_ID;\r\n const firebaseConfig = resolvedParams.firebaseConfig || {\r\n apiKey,\r\n appId,\r\n projectId,\r\n }\r\n const firebaseAdminConfig = resolvedParams.firebaseAdminConfig;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n apiKey,\r\n firebaseConfig,\r\n firebaseAdminConfig,\r\n ...resolvedParams,\r\n };\r\n\r\n const reqBackendClient = await ternSecureBackendClient();\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const locationHeader = requestStateClient.headers.get(constants.Headers.Location);\r\n const appCheckToken = requestStateClient.headers.get(constants.Headers.AppCheckToken);\r\n console.log(\"[ternSecureProxy] App Check Token in Proxy:\", appCheckToken);\r\n if (locationHeader) {\r\n return new Response(null, {\r\n status: 307,\r\n headers: requestStateClient.headers,\r\n });\r\n } else if (requestStateClient.status === AuthStatus.Handshake) {\r\n throw new Error('TernSecure: handshake status without redirect is not supported.');\r\n }\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const redirectToSignIn = createProxyRedirectToSignIn(ternSecureRequest);\r\n const redirectToSignUp = createProxyRedirectToSignUp(ternSecureRequest);\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request, requestStateClient);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient, appCheckToken || undefined);\r\n return handlerResult;\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\n\r\nconst createProxyRedirectToSignIn = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignIn'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\nconst createProxyRedirectToSignUp = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignUp'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\n/**\r\n * Create middleware redirect functions\r\n * @deprecated\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n requestState: RequestState,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: requestState.signInUrl,\r\n signUpUrl: requestState.signUpUrl,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n"],"mappings":"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","names":["request","event","nextjsNotFound"]}
1
+ {"version":3,"sources":["../../../src/server/ternSecureProxy.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n RedirectFun,\r\n RequestState,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { AuthStatus, constants, createRedirect, createTernSecureRequest } from '@tern-secure/backend';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware, NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { \r\n FIREBASE_API_KEY,\r\n SIGN_IN_URL, \r\n SIGN_UP_URL \r\n} from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect, createProtect } from './protect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\n\r\nexport type MiddlewareOptions = AuthenticateRequestOptions;\r\n\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureProxy = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n const apiKey = resolvedParams.apiKey || FIREBASE_API_KEY;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n apiKey,\r\n ...resolvedParams,\r\n };\r\n\r\n const reqBackendClient = await ternSecureBackendClient();\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const appCheckToken = requestStateClient.headers.get(constants.Headers.AppCheckToken);\r\n const locationHeader = requestStateClient.headers.get(constants.Headers.Location);\r\n if (locationHeader) {\r\n return new Response(null, {\r\n status: 307,\r\n headers: requestStateClient.headers,\r\n });\r\n } else if (requestStateClient.status === AuthStatus.Handshake) {\r\n throw new Error('TernSecure: handshake status without redirect is not supported.');\r\n }\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const redirectToSignIn = createProxyRedirectToSignIn(ternSecureRequest);\r\n const redirectToSignUp = createProxyRedirectToSignUp(ternSecureRequest);\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request, requestStateClient);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient, resolvedParams, appCheckToken || undefined);\r\n return handlerResult;\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\n\r\nconst createProxyRedirectToSignIn = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignIn'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\nconst createProxyRedirectToSignUp = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignUp'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\n/**\r\n * Create middleware redirect functions\r\n * @deprecated\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n requestState: RequestState,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: requestState.signInUrl,\r\n signUpUrl: requestState.signUpUrl,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n"],"mappings":"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","names":["request","event","nextjsNotFound"]}
@@ -133,8 +133,18 @@ const setRequestHeadersOnNextResponse = (res, req, newHeaders) => {
133
133
  res.headers.set(`${MIDDLEWARE_HEADER_PREFIX}-${key}`, val);
134
134
  });
135
135
  };
136
- function decorateRequest(req, res, requestState, appCheckToken) {
137
- const { reason, token, status } = requestState;
136
+ const sanitizeRequestData = (requestData) => {
137
+ const {
138
+ apiClient,
139
+ // Internal client instance - not serializable
140
+ checkRevoked,
141
+ // Function/config - not needed in SSR
142
+ ...safeData
143
+ } = requestData;
144
+ return safeData;
145
+ };
146
+ function decorateRequest(req, res, requestState, requestData, appCheckToken) {
147
+ const { reason, token, status, headers } = requestState;
138
148
  if (!res) {
139
149
  res = import_server.NextResponse.next();
140
150
  }
@@ -155,12 +165,14 @@ function decorateRequest(req, res, requestState, appCheckToken) {
155
165
  }
156
166
  }
157
167
  if (rewriteURL) {
168
+ const ternsecureRequestData = sanitizeRequestData(requestData);
158
169
  setRequestHeadersOnNextResponse(res, req, {
159
170
  [import_backend.constants.Headers.AuthStatus]: status,
160
171
  [import_backend.constants.Headers.AuthToken]: token || "",
161
- [import_backend.constants.Headers.AppCheckToken]: appCheckToken || req.headers.get(import_backend.constants.Headers.AppCheckToken) || "",
172
+ [import_backend.constants.Headers.AppCheckToken]: appCheckToken || headers.get(import_backend.constants.Headers.AppCheckToken) || "",
162
173
  [import_backend.constants.Headers.AuthReason]: reason || "",
163
- [import_backend.constants.Headers.TernSecureUrl]: req.ternUrl.toString()
174
+ [import_backend.constants.Headers.TernSecureUrl]: req.ternUrl.toString(),
175
+ ...ternsecureRequestData ? { [import_backend.constants.Headers.TernSecureRequestData]: JSON.stringify(ternsecureRequestData) } : {}
164
176
  });
165
177
  res.headers.set(import_constants.constants.Headers.NextRewrite, rewriteURL.href);
166
178
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/utils.ts"],"sourcesContent":["import type {\r\n RequestState,\r\n TernSecureRequest,\r\n} from \"@tern-secure/backend\";\r\nimport { constants } from \"@tern-secure/backend\";\r\nimport { NextRequest,NextResponse } from 'next/server';\r\n\r\nimport { constants as nextConstants } from \"../constants\";\r\nimport type { User } from \"./types\"\r\n\r\nconst OVERRIDE_HEADERS = 'x-middleware-override-headers';\r\nconst MIDDLEWARE_HEADER_PREFIX = 'x-middleware-request' as string;\r\n\r\ninterface RequestContext {\r\n user: User\r\n sessionId: string\r\n}\r\n\r\n// Use process.env in Node.js and globalThis in Edge\r\nconst getGlobalObject = () => {\r\n if (typeof process !== 'undefined') {\r\n return process\r\n }\r\n return globalThis\r\n}\r\n\r\nconst STORE_KEY = '__TERN_AUTH_STORE__'\r\n\r\nexport class Store {\r\n private static getStore() {\r\n const global = getGlobalObject() as any\r\n \r\n if (!global[STORE_KEY]) {\r\n global[STORE_KEY] = {\r\n contexts: new Map<string, RequestContext>(),\r\n sessions: new Map<string, User>(),\r\n currentSession: null as RequestContext | null\r\n }\r\n }\r\n \r\n return global[STORE_KEY]\r\n }\r\n\r\n static setContext(context: RequestContext) {\r\n const store = this.getStore()\r\n const { user, sessionId } = context\r\n \r\n console.log(\"Store: Setting context:\", { sessionId, user })\r\n \r\n // Store in both maps\r\n store.contexts.set(sessionId, context)\r\n store.sessions.set(sessionId, user)\r\n \r\n // Set as current session\r\n store.currentSession = context\r\n \r\n console.log(\"Store: Updated state:\", {\r\n contextsSize: store.contexts.size,\r\n sessionsSize: store.sessions.size,\r\n currentSession: store.currentSession\r\n })\r\n }\r\n\r\n static getContext(): RequestContext | null {\r\n const store = this.getStore()\r\n \r\n // First try current session\r\n if (store.currentSession) {\r\n const session = this.getSession(store.currentSession.sessionId)\r\n if (session && session.uid === store.currentSession.user.uid) {\r\n return store.currentSession\r\n }\r\n }\r\n \r\n // Then try to find any valid context\r\n for (const [sessionId, user] of store.sessions.entries()) {\r\n const context = store.contexts.get(sessionId)\r\n if (context && context.user.uid === user.uid) {\r\n // Update current session\r\n store.currentSession = context\r\n return context\r\n }\r\n }\r\n \r\n return null\r\n }\r\n\r\n static setSession(sessionId: string, user: User) {\r\n const store = this.getStore()\r\n store.sessions.set(sessionId, user)\r\n }\r\n\r\n static getSession(sessionId: string): User | null {\r\n const store = this.getStore()\r\n return store.sessions.get(sessionId) || null\r\n }\r\n\r\n static debug() {\r\n const store = this.getStore()\r\n return {\r\n contextsSize: store.contexts.size,\r\n sessionsSize: store.sessions.size,\r\n currentSession: store.currentSession,\r\n contexts: Array.from(store.contexts.entries()),\r\n sessions: Array.from(store.sessions.entries())\r\n }\r\n }\r\n\r\n static cleanup() {\r\n const store = this.getStore()\r\n const MAX_ENTRIES = 1000\r\n \r\n if (store.contexts.size > MAX_ENTRIES) {\r\n const keys = Array.from(store.contexts.keys())\r\n const toDelete = keys.slice(0, keys.length - MAX_ENTRIES)\r\n \r\n toDelete.forEach(key => {\r\n store.contexts.delete(key)\r\n store.sessions.delete(key)\r\n })\r\n }\r\n }\r\n}\r\n\r\n\r\nexport const setRequestHeadersOnNextResponse = (\r\n res: NextResponse | Response,\r\n req: Request,\r\n newHeaders: Record<string, string>,\r\n) => {\r\n if (!res.headers.get(OVERRIDE_HEADERS)) {\r\n // Emulate a user setting overrides by explicitly adding the required nextjs headers\r\n // https://github.com/vercel/next.js/pull/41380\r\n // @ts-expect-error -- property keys does not exist on type Headers\r\n res.headers.set(OVERRIDE_HEADERS, [...req.headers.keys()]);\r\n req.headers.forEach((val, key) => {\r\n res.headers.set(`${MIDDLEWARE_HEADER_PREFIX}-${key}`, val);\r\n });\r\n }\r\n\r\n // Now that we have normalised res to include overrides, just append the new header\r\n Object.entries(newHeaders).forEach(([key, val]) => {\r\n res.headers.set(OVERRIDE_HEADERS, `${res.headers.get(OVERRIDE_HEADERS)},${key}`);\r\n res.headers.set(`${MIDDLEWARE_HEADER_PREFIX}-${key}`, val);\r\n });\r\n};\r\n\r\nexport function decorateRequest(\r\n req: TernSecureRequest,\r\n res: Response,\r\n requestState: RequestState,\r\n appCheckToken?: string,\r\n): Response {\r\n const { reason, token, status } = requestState;\r\n // pass-through case, convert to next()\r\n if (!res) {\r\n res = NextResponse.next();\r\n }\r\n\r\n // redirect() case, return early\r\n if (res.headers.get(nextConstants.Headers.NextRedirect)) {\r\n return res;\r\n }\r\n\r\n let rewriteURL;\r\n\r\n // next() case, convert to a rewrite\r\n if (res.headers.get(nextConstants.Headers.NextResume) === '1') {\r\n res.headers.delete(nextConstants.Headers.NextResume);\r\n rewriteURL = new URL(req.url);\r\n }\r\n\r\n // rewrite() case, set auth result only if origin remains the same\r\n const rewriteURLHeader = res.headers.get(nextConstants.Headers.NextRewrite);\r\n\r\n if (rewriteURLHeader) {\r\n const reqURL = new URL(req.url);\r\n rewriteURL = new URL(rewriteURLHeader);\r\n\r\n // if the origin has changed, return early\r\n if (rewriteURL.origin !== reqURL.origin) {\r\n return res;\r\n }\r\n }\r\n\r\n if (rewriteURL) {\r\n setRequestHeadersOnNextResponse(res, req, {\r\n [constants.Headers.AuthStatus]: status,\r\n [constants.Headers.AuthToken]: token || '',\r\n [constants.Headers.AppCheckToken]: appCheckToken || req.headers.get(constants.Headers.AppCheckToken) || '',\r\n [constants.Headers.AuthReason]: reason || '',\r\n [constants.Headers.TernSecureUrl]: req.ternUrl.toString(),\r\n });\r\n res.headers.set(nextConstants.Headers.NextRewrite, rewriteURL.href);\r\n }\r\n\r\n return res;\r\n}\r\n\r\n\r\nexport const isPrerenderingBailout = (e: unknown) => {\r\n if (!(e instanceof Error) || !('message' in e)) {\r\n return false;\r\n }\r\n\r\n const { message } = e;\r\n\r\n const lowerCaseInput = message.toLowerCase();\r\n const dynamicServerUsage = lowerCaseInput.includes('dynamic server usage');\r\n const bailOutPrerendering = lowerCaseInput.includes('this page needs to bail out of prerendering');\r\n\r\n // note: new error message syntax introduced in next@14.1.1-canary.21\r\n // but we still want to support older versions.\r\n // https://github.com/vercel/next.js/pull/61332 (dynamic-rendering.ts:153)\r\n const routeRegex = /Route .*? needs to bail out of prerendering at this point because it used .*?./;\r\n\r\n return routeRegex.test(message) || dynamicServerUsage || bailOutPrerendering;\r\n};\r\n\r\nexport async function buildRequestLike(): Promise<NextRequest> {\r\n try {\r\n // Dynamically import next/headers, otherwise Next12 apps will break\r\n // @ts-expect-error: Cannot find module 'next/headers' or its corresponding type declarations.ts(2307)\r\n const { headers } = await import('next/headers');\r\n const resolvedHeaders = await headers();\r\n return new NextRequest('https://placeholder.com', { headers: resolvedHeaders });\r\n } catch (e: any) {\r\n // rethrow the error when react throws a prerendering bailout\r\n // https://nextjs.org/docs/messages/ppr-caught-error\r\n if (e && isPrerenderingBailout(e)) {\r\n throw e;\r\n }\r\n\r\n throw new Error(\r\n `TernSecure: auth(), currentUser() and ternSecureClient(), are only supported in App Router (/app directory).\\nIf you're using /pages, try getAuth() instead.\\nOriginal error: ${e}`,\r\n );\r\n }\r\n}\r\n\r\n// Original source: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/get-script-nonce-from-header.tsx\r\nexport function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {\r\n const directives = cspHeaderValue\r\n // Directives are split by ';'.\r\n .split(';')\r\n .map(directive => directive.trim());\r\n\r\n // First try to find the directive for the 'script-src', otherwise try to\r\n // fallback to the 'default-src'.\r\n const directive =\r\n directives.find(dir => dir.startsWith('script-src')) || directives.find(dir => dir.startsWith('default-src'));\r\n\r\n // If no directive could be found, then we're done.\r\n if (!directive) {\r\n return;\r\n }\r\n\r\n // Extract the nonce from the directive\r\n const nonce = directive\r\n .split(' ')\r\n // Remove the 'strict-src'/'default-src' string, this can't be the nonce.\r\n .slice(1)\r\n .map(source => source.trim())\r\n // Find the first source with the 'nonce-' prefix.\r\n .find(source => source.startsWith(\"'nonce-\") && source.length > 8 && source.endsWith(\"'\"))\r\n // Grab the nonce by trimming the 'nonce-' prefix.\r\n ?.slice(7, -1);\r\n\r\n // If we couldn't find the nonce, then we're done.\r\n if (!nonce) {\r\n return;\r\n }\r\n\r\n // Don't accept the nonce value if it contains HTML escape characters.\r\n // Technically, the spec requires a base64'd value, but this is just an\r\n // extra layer.\r\n if (/[&><\\u2028\\u2029]/g.test(nonce)) {\r\n throw new Error(\r\n 'Nonce value from Content-Security-Policy contained invalid HTML escape characters, which is disallowed for security reasons. Make sure that your nonce value does not contain the following characters: `<`, `>`, `&`',\r\n );\r\n }\r\n\r\n return nonce;\r\n}\r\n"],"mappings":"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","names":["nextConstants","directive"]}
1
+ {"version":3,"sources":["../../../src/server/utils.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n RequestState,\r\n TernSecureRequest\r\n} from \"@tern-secure/backend\";\r\nimport { constants } from \"@tern-secure/backend\";\r\nimport { NextRequest,NextResponse } from 'next/server';\r\n\r\nimport { constants as nextConstants } from \"../constants\";\r\nimport type { User } from \"./types\"\r\n\r\nconst OVERRIDE_HEADERS = 'x-middleware-override-headers';\r\nconst MIDDLEWARE_HEADER_PREFIX = 'x-middleware-request' as string;\r\n\r\ninterface RequestContext {\r\n user: User\r\n sessionId: string\r\n}\r\n\r\n// Use process.env in Node.js and globalThis in Edge\r\nconst getGlobalObject = () => {\r\n if (typeof process !== 'undefined') {\r\n return process\r\n }\r\n return globalThis\r\n}\r\n\r\nconst STORE_KEY = '__TERN_AUTH_STORE__'\r\n\r\nexport class Store {\r\n private static getStore() {\r\n const global = getGlobalObject() as any\r\n \r\n if (!global[STORE_KEY]) {\r\n global[STORE_KEY] = {\r\n contexts: new Map<string, RequestContext>(),\r\n sessions: new Map<string, User>(),\r\n currentSession: null as RequestContext | null\r\n }\r\n }\r\n \r\n return global[STORE_KEY]\r\n }\r\n\r\n static setContext(context: RequestContext) {\r\n const store = this.getStore()\r\n const { user, sessionId } = context\r\n \r\n console.log(\"Store: Setting context:\", { sessionId, user })\r\n \r\n // Store in both maps\r\n store.contexts.set(sessionId, context)\r\n store.sessions.set(sessionId, user)\r\n \r\n // Set as current session\r\n store.currentSession = context\r\n \r\n console.log(\"Store: Updated state:\", {\r\n contextsSize: store.contexts.size,\r\n sessionsSize: store.sessions.size,\r\n currentSession: store.currentSession\r\n })\r\n }\r\n\r\n static getContext(): RequestContext | null {\r\n const store = this.getStore()\r\n \r\n // First try current session\r\n if (store.currentSession) {\r\n const session = this.getSession(store.currentSession.sessionId)\r\n if (session && session.uid === store.currentSession.user.uid) {\r\n return store.currentSession\r\n }\r\n }\r\n \r\n // Then try to find any valid context\r\n for (const [sessionId, user] of store.sessions.entries()) {\r\n const context = store.contexts.get(sessionId)\r\n if (context && context.user.uid === user.uid) {\r\n // Update current session\r\n store.currentSession = context\r\n return context\r\n }\r\n }\r\n \r\n return null\r\n }\r\n\r\n static setSession(sessionId: string, user: User) {\r\n const store = this.getStore()\r\n store.sessions.set(sessionId, user)\r\n }\r\n\r\n static getSession(sessionId: string): User | null {\r\n const store = this.getStore()\r\n return store.sessions.get(sessionId) || null\r\n }\r\n\r\n static debug() {\r\n const store = this.getStore()\r\n return {\r\n contextsSize: store.contexts.size,\r\n sessionsSize: store.sessions.size,\r\n currentSession: store.currentSession,\r\n contexts: Array.from(store.contexts.entries()),\r\n sessions: Array.from(store.sessions.entries())\r\n }\r\n }\r\n\r\n static cleanup() {\r\n const store = this.getStore()\r\n const MAX_ENTRIES = 1000\r\n \r\n if (store.contexts.size > MAX_ENTRIES) {\r\n const keys = Array.from(store.contexts.keys())\r\n const toDelete = keys.slice(0, keys.length - MAX_ENTRIES)\r\n \r\n toDelete.forEach(key => {\r\n store.contexts.delete(key)\r\n store.sessions.delete(key)\r\n })\r\n }\r\n }\r\n}\r\n\r\n\r\nexport const setRequestHeadersOnNextResponse = (\r\n res: NextResponse | Response,\r\n req: Request,\r\n newHeaders: Record<string, string>,\r\n) => {\r\n if (!res.headers.get(OVERRIDE_HEADERS)) {\r\n // Emulate a user setting overrides by explicitly adding the required nextjs headers\r\n // https://github.com/vercel/next.js/pull/41380\r\n // @ts-expect-error -- property keys does not exist on type Headers\r\n res.headers.set(OVERRIDE_HEADERS, [...req.headers.keys()]);\r\n req.headers.forEach((val, key) => {\r\n res.headers.set(`${MIDDLEWARE_HEADER_PREFIX}-${key}`, val);\r\n });\r\n }\r\n\r\n // Now that we have normalised res to include overrides, just append the new header\r\n Object.entries(newHeaders).forEach(([key, val]) => {\r\n res.headers.set(OVERRIDE_HEADERS, `${res.headers.get(OVERRIDE_HEADERS)},${key}`);\r\n res.headers.set(`${MIDDLEWARE_HEADER_PREFIX}-${key}`, val);\r\n });\r\n};\r\n\r\n/**\r\n * Sanitize requestData by removing sensitive fields before storing in headers\r\n * Headers with x-middleware-request- prefix are internal to Next.js SSR and not exposed to browser\r\n * However, we still filter sensitive data as a security best practice\r\n */\r\nconst sanitizeRequestData = (requestData: AuthenticateRequestOptions): Partial<AuthenticateRequestOptions> => {\r\n const { \r\n apiClient, // Internal client instance - not serializable\r\n checkRevoked, // Function/config - not needed in SSR\r\n ...safeData \r\n } = requestData;\r\n\r\n return safeData;\r\n};\r\n\r\nexport function decorateRequest(\r\n req: TernSecureRequest,\r\n res: Response,\r\n requestState: RequestState,\r\n requestData: AuthenticateRequestOptions,\r\n appCheckToken?: string,\r\n): Response {\r\n const { reason, token, status, headers} = requestState;\r\n // pass-through case, convert to next()\r\n if (!res) {\r\n res = NextResponse.next();\r\n }\r\n\r\n // redirect() case, return early\r\n if (res.headers.get(nextConstants.Headers.NextRedirect)) {\r\n return res;\r\n }\r\n\r\n let rewriteURL;\r\n\r\n // next() case, convert to a rewrite\r\n if (res.headers.get(nextConstants.Headers.NextResume) === '1') {\r\n res.headers.delete(nextConstants.Headers.NextResume);\r\n rewriteURL = new URL(req.url);\r\n }\r\n\r\n // rewrite() case, set auth result only if origin remains the same\r\n const rewriteURLHeader = res.headers.get(nextConstants.Headers.NextRewrite);\r\n\r\n if (rewriteURLHeader) {\r\n const reqURL = new URL(req.url);\r\n rewriteURL = new URL(rewriteURLHeader);\r\n\r\n // if the origin has changed, return early\r\n if (rewriteURL.origin !== reqURL.origin) {\r\n return res;\r\n }\r\n }\r\n\r\n if (rewriteURL) {\r\n const ternsecureRequestData = sanitizeRequestData(requestData);\r\n \r\n setRequestHeadersOnNextResponse(res, req, {\r\n [constants.Headers.AuthStatus]: status,\r\n [constants.Headers.AuthToken]: token || '',\r\n [constants.Headers.AppCheckToken]: appCheckToken || headers.get(constants.Headers.AppCheckToken) || '',\r\n [constants.Headers.AuthReason]: reason || '',\r\n [constants.Headers.TernSecureUrl]: req.ternUrl.toString(),\r\n ...(ternsecureRequestData ? { [constants.Headers.TernSecureRequestData]: JSON.stringify(ternsecureRequestData) } : {})\r\n });\r\n res.headers.set(nextConstants.Headers.NextRewrite, rewriteURL.href);\r\n }\r\n\r\n return res;\r\n}\r\n\r\n\r\nexport const isPrerenderingBailout = (e: unknown) => {\r\n if (!(e instanceof Error) || !('message' in e)) {\r\n return false;\r\n }\r\n\r\n const { message } = e;\r\n\r\n const lowerCaseInput = message.toLowerCase();\r\n const dynamicServerUsage = lowerCaseInput.includes('dynamic server usage');\r\n const bailOutPrerendering = lowerCaseInput.includes('this page needs to bail out of prerendering');\r\n\r\n // note: new error message syntax introduced in next@14.1.1-canary.21\r\n // but we still want to support older versions.\r\n // https://github.com/vercel/next.js/pull/61332 (dynamic-rendering.ts:153)\r\n const routeRegex = /Route .*? needs to bail out of prerendering at this point because it used .*?./;\r\n\r\n return routeRegex.test(message) || dynamicServerUsage || bailOutPrerendering;\r\n};\r\n\r\nexport async function buildRequestLike(): Promise<NextRequest> {\r\n try {\r\n // Dynamically import next/headers, otherwise Next12 apps will break\r\n // @ts-expect-error: Cannot find module 'next/headers' or its corresponding type declarations.ts(2307)\r\n const { headers } = await import('next/headers');\r\n const resolvedHeaders = await headers();\r\n return new NextRequest('https://placeholder.com', { headers: resolvedHeaders });\r\n } catch (e: any) {\r\n // rethrow the error when react throws a prerendering bailout\r\n // https://nextjs.org/docs/messages/ppr-caught-error\r\n if (e && isPrerenderingBailout(e)) {\r\n throw e;\r\n }\r\n\r\n throw new Error(\r\n `TernSecure: auth(), currentUser() and ternSecureClient(), are only supported in App Router (/app directory).\\nIf you're using /pages, try getAuth() instead.\\nOriginal error: ${e}`,\r\n );\r\n }\r\n}\r\n\r\n// Original source: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/get-script-nonce-from-header.tsx\r\nexport function getScriptNonceFromHeader(cspHeaderValue: string): string | undefined {\r\n const directives = cspHeaderValue\r\n // Directives are split by ';'.\r\n .split(';')\r\n .map(directive => directive.trim());\r\n\r\n // First try to find the directive for the 'script-src', otherwise try to\r\n // fallback to the 'default-src'.\r\n const directive =\r\n directives.find(dir => dir.startsWith('script-src')) || directives.find(dir => dir.startsWith('default-src'));\r\n\r\n // If no directive could be found, then we're done.\r\n if (!directive) {\r\n return;\r\n }\r\n\r\n // Extract the nonce from the directive\r\n const nonce = directive\r\n .split(' ')\r\n // Remove the 'strict-src'/'default-src' string, this can't be the nonce.\r\n .slice(1)\r\n .map(source => source.trim())\r\n // Find the first source with the 'nonce-' prefix.\r\n .find(source => source.startsWith(\"'nonce-\") && source.length > 8 && source.endsWith(\"'\"))\r\n // Grab the nonce by trimming the 'nonce-' prefix.\r\n ?.slice(7, -1);\r\n\r\n // If we couldn't find the nonce, then we're done.\r\n if (!nonce) {\r\n return;\r\n }\r\n\r\n // Don't accept the nonce value if it contains HTML escape characters.\r\n // Technically, the spec requires a base64'd value, but this is just an\r\n // extra layer.\r\n if (/[&><\\u2028\\u2029]/g.test(nonce)) {\r\n throw new Error(\r\n 'Nonce value from Content-Security-Policy contained invalid HTML escape characters, which is disallowed for security reasons. Make sure that your nonce value does not contain the following characters: `<`, `>`, `&`',\r\n );\r\n }\r\n\r\n return nonce;\r\n}\r\n"],"mappings":"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","names":["nextConstants","directive"]}
@@ -1,7 +1,7 @@
1
1
  import { bench, vi } from "vitest";
2
2
  import { NextRequest, NextResponse } from "next/server";
3
3
  import { geminiCreateTernSecureNextJsHandlerFn } from "../../examples/gemini_fnTernSecureNextHandler";
4
- import { SessionEndpointHandler } from "../app-router/admin/sessionHandlers";
4
+ import { SessionEndpointHandler } from "../app-router/admin/handlers";
5
5
  vi.mock("../sessionHandlers", () => ({
6
6
  SessionEndpointHandler: {
7
7
  handle: vi.fn()
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/__tests__/gemini_fnTernSecureNextHandler.bench.ts"],"sourcesContent":["import { bench, vi } from 'vitest';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { geminiCreateTernSecureNextJsHandlerFn } from '../../examples/gemini_fnTernSecureNextHandler';\nimport { SessionEndpointHandler } from '../app-router/admin/sessionHandlers';\n\nvi.mock('../sessionHandlers', () => ({\n SessionEndpointHandler: {\n handle: vi.fn(),\n },\n}));\n\nconst authHandlerOptions = {\n cors: {\n allowedOrigins: ['http://localhost:3000', 'https://ternsecure.com'],\n allowedMethods: ['GET', 'POST'],\n },\n security: {\n requireCSRF: true,\n allowedReferers: ['http://localhost:3000', 'https://ternsecure.com'],\n },\n debug: false,\n};\n\nbench('handler performance for a valid request', async () => {\n const handler = geminiCreateTernSecureNextJsHandlerFn(authHandlerOptions);\n const request = new NextRequest('http://localhost/api/auth/sessions/verify', {\n method: 'GET',\n headers: { origin: 'http://localhost:3000' },\n });\n (SessionEndpointHandler.handle as any).mockResolvedValue(new NextResponse(null, { status: 200 }));\n\n await handler.GET(request);\n});\n"],"mappings":"AAAA,SAAS,OAAO,UAAU;AAC1B,SAAS,aAAa,oBAAoB;AAC1C,SAAS,6CAA6C;AACtD,SAAS,8BAA8B;AAEvC,GAAG,KAAK,sBAAsB,OAAO;AAAA,EACnC,wBAAwB;AAAA,IACtB,QAAQ,GAAG,GAAG;AAAA,EAChB;AACF,EAAE;AAEF,MAAM,qBAAqB;AAAA,EACzB,MAAM;AAAA,IACJ,gBAAgB,CAAC,yBAAyB,wBAAwB;AAAA,IAClE,gBAAgB,CAAC,OAAO,MAAM;AAAA,EAChC;AAAA,EACA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,iBAAiB,CAAC,yBAAyB,wBAAwB;AAAA,EACrE;AAAA,EACA,OAAO;AACT;AAEA,MAAM,2CAA2C,YAAY;AAC3D,QAAM,UAAU,sCAAsC,kBAAkB;AACxE,QAAM,UAAU,IAAI,YAAY,6CAA6C;AAAA,IAC3E,QAAQ;AAAA,IACR,SAAS,EAAE,QAAQ,wBAAwB;AAAA,EAC7C,CAAC;AACD,EAAC,uBAAuB,OAAe,kBAAkB,IAAI,aAAa,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC;AAEhG,QAAM,QAAQ,IAAI,OAAO;AAC3B,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/__tests__/gemini_fnTernSecureNextHandler.bench.ts"],"sourcesContent":["import { bench, vi } from 'vitest';\nimport { NextRequest, NextResponse } from 'next/server';\nimport { geminiCreateTernSecureNextJsHandlerFn } from '../../examples/gemini_fnTernSecureNextHandler';\nimport { SessionEndpointHandler } from '../app-router/admin/handlers';\n\nvi.mock('../sessionHandlers', () => ({\n SessionEndpointHandler: {\n handle: vi.fn(),\n },\n}));\n\nconst authHandlerOptions = {\n cors: {\n allowedOrigins: ['http://localhost:3000', 'https://ternsecure.com'],\n allowedMethods: ['GET', 'POST'],\n },\n security: {\n requireCSRF: true,\n allowedReferers: ['http://localhost:3000', 'https://ternsecure.com'],\n },\n debug: false,\n};\n\nbench('handler performance for a valid request', async () => {\n const handler = geminiCreateTernSecureNextJsHandlerFn(authHandlerOptions);\n const request = new NextRequest('http://localhost/api/auth/sessions/verify', {\n method: 'GET',\n headers: { origin: 'http://localhost:3000' },\n });\n (SessionEndpointHandler.handle as any).mockResolvedValue(new NextResponse(null, { status: 200 }));\n\n await handler.GET(request);\n});\n"],"mappings":"AAAA,SAAS,OAAO,UAAU;AAC1B,SAAS,aAAa,oBAAoB;AAC1C,SAAS,6CAA6C;AACtD,SAAS,8BAA8B;AAEvC,GAAG,KAAK,sBAAsB,OAAO;AAAA,EACnC,wBAAwB;AAAA,IACtB,QAAQ,GAAG,GAAG;AAAA,EAChB;AACF,EAAE;AAEF,MAAM,qBAAqB;AAAA,EACzB,MAAM;AAAA,IACJ,gBAAgB,CAAC,yBAAyB,wBAAwB;AAAA,IAClE,gBAAgB,CAAC,OAAO,MAAM;AAAA,EAChC;AAAA,EACA,UAAU;AAAA,IACR,aAAa;AAAA,IACb,iBAAiB,CAAC,yBAAyB,wBAAwB;AAAA,EACrE;AAAA,EACA,OAAO;AACT;AAEA,MAAM,2CAA2C,YAAY;AAC3D,QAAM,UAAU,sCAAsC,kBAAkB;AACxE,QAAM,UAAU,IAAI,YAAY,6CAA6C;AAAA,IAC3E,QAAQ;AAAA,IACR,SAAS,EAAE,QAAQ,wBAAwB;AAAA,EAC7C,CAAC;AACD,EAAC,uBAAuB,OAAe,kBAAkB,IAAI,aAAa,MAAM,EAAE,QAAQ,IAAI,CAAC,CAAC;AAEhG,QAAM,QAAQ,IAAI,OAAO;AAC3B,CAAC;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/actions.ts"],"sourcesContent":["'use server';\n\nimport {\n ClearNextSessionCookie,\n clearSessionCookie,\n CreateNextSessionCookie,\n createSessionCookie,\n RetrieveUser as RetrieveUserBackend,\n SetNextServerSession,\n SetNextServerToken,\n VerifyNextTernIdToken,\n} from '@tern-secure/backend/admin';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { TENANT_ID } from './constants';\nimport { getDeleteOptions } from './cookieOptionsHelper';\nimport type { TernSecureHandlerOptions } from './types';\n\nexport async function createSessionCookieServer(idToken: string) {\n const cookieStore = new NextCookieStore();\n return createSessionCookie(idToken, cookieStore);\n}\n\nexport async function clearSessionCookieServer() {\n const cookieStore = new NextCookieStore();\n return clearSessionCookie(cookieStore);\n}\n\nexport async function clearNextSessionCookie(options?: {\n cookies?: TernSecureHandlerOptions['cookies'];\n revokeRefreshTokensOnSignOut?: boolean;\n}) {\n const deleteOptions = getDeleteOptions(options);\n return ClearNextSessionCookie(TENANT_ID, deleteOptions);\n}\n\nexport async function setNextServerSession(idToken: string) {\n return SetNextServerSession(idToken);\n}\n\nexport async function setNextServerToken(token: string) {\n return SetNextServerToken(token);\n}\n\nexport async function createNextSessionCookie(idToken: string) {\n return CreateNextSessionCookie(idToken);\n}\n\nexport async function verifyNextTernIdToken(idToken: string) {\n return VerifyNextTernIdToken(idToken);\n}\n\nexport function RetrieveUser() {\n return RetrieveUserBackend(TENANT_ID);\n}\n"],"mappings":";AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AAGjC,eAAsB,0BAA0B,SAAiB;AAC/D,QAAM,cAAc,IAAI,gBAAgB;AACxC,SAAO,oBAAoB,SAAS,WAAW;AACjD;AAEA,eAAsB,2BAA2B;AAC/C,QAAM,cAAc,IAAI,gBAAgB;AACxC,SAAO,mBAAmB,WAAW;AACvC;AAEA,eAAsB,uBAAuB,SAG1C;AACD,QAAM,gBAAgB,iBAAiB,OAAO;AAC9C,SAAO,uBAAuB,WAAW,aAAa;AACxD;AAEA,eAAsB,qBAAqB,SAAiB;AAC1D,SAAO,qBAAqB,OAAO;AACrC;AAEA,eAAsB,mBAAmB,OAAe;AACtD,SAAO,mBAAmB,KAAK;AACjC;AAEA,eAAsB,wBAAwB,SAAiB;AAC7D,SAAO,wBAAwB,OAAO;AACxC;AAEA,eAAsB,sBAAsB,SAAiB;AAC3D,SAAO,sBAAsB,OAAO;AACtC;AAEO,SAAS,eAAe;AAC7B,SAAO,oBAAoB,SAAS;AACtC;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/actions.ts"],"sourcesContent":["'use server';\n\nimport {\n ClearNextSessionCookie,\n clearSessionCookie,\n CreateNextSessionCookie,\n createSessionCookie,\n RetrieveUser as RetrieveUserBackend,\n SetNextServerSession,\n SetNextServerToken,\n VerifyNextTernIdToken,\n} from '@tern-secure/backend/admin';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { TENANT_ID } from './constants';\nimport { getDeleteOptions } from './cookieOptionsHelper';\nimport type { ApiHandlerOptions } from './types';\n\nexport async function createSessionCookieServer(idToken: string) {\n const cookieStore = new NextCookieStore();\n return createSessionCookie(idToken, cookieStore);\n}\n\nexport async function clearSessionCookieServer() {\n const cookieStore = new NextCookieStore();\n return clearSessionCookie(cookieStore);\n}\n\nexport async function clearNextSessionCookie(options?: {\n cookies?: ApiHandlerOptions['cookies'];\n revokeRefreshTokensOnSignOut?: boolean;\n}) {\n const deleteOptions = getDeleteOptions(options);\n return ClearNextSessionCookie(TENANT_ID, deleteOptions);\n}\n\nexport async function setNextServerSession(idToken: string) {\n return SetNextServerSession(idToken);\n}\n\nexport async function setNextServerToken(token: string) {\n return SetNextServerToken(token);\n}\n\nexport async function createNextSessionCookie(idToken: string) {\n return CreateNextSessionCookie(idToken);\n}\n\nexport async function verifyNextTernIdToken(idToken: string) {\n return VerifyNextTernIdToken(idToken);\n}\n\nexport function RetrieveUser() {\n return RetrieveUserBackend(TENANT_ID);\n}\n"],"mappings":";AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AAGjC,eAAsB,0BAA0B,SAAiB;AAC/D,QAAM,cAAc,IAAI,gBAAgB;AACxC,SAAO,oBAAoB,SAAS,WAAW;AACjD;AAEA,eAAsB,2BAA2B;AAC/C,QAAM,cAAc,IAAI,gBAAgB;AACxC,SAAO,mBAAmB,WAAW;AACvC;AAEA,eAAsB,uBAAuB,SAG1C;AACD,QAAM,gBAAgB,iBAAiB,OAAO;AAC9C,SAAO,uBAAuB,WAAW,aAAa;AACxD;AAEA,eAAsB,qBAAqB,SAAiB;AAC1D,SAAO,qBAAqB,OAAO;AACrC;AAEA,eAAsB,mBAAmB,OAAe;AACtD,SAAO,mBAAmB,KAAK;AACjC;AAEA,eAAsB,wBAAwB,SAAiB;AAC7D,SAAO,wBAAwB,OAAO;AACxC;AAEA,eAAsB,sBAAsB,SAAiB;AAC3D,SAAO,sBAAsB,OAAO;AACtC;AAEO,SAAS,eAAe;AAC7B,SAAO,oBAAoB,SAAS;AACtC;","names":[]}
@@ -1,5 +1,5 @@
1
+ import { sessionEndpointHandler, signInEndpointHandler } from "./handlers";
1
2
  import { createApiErrorResponse } from "./responses";
2
- import { cookieEndpointHandler, sessionEndpointHandler, signInEndpointHandler } from "./sessionHandlers";
3
3
  class SessionsHandler {
4
4
  canHandle(endpoint) {
5
5
  return endpoint === "sessions";
@@ -18,27 +18,18 @@ class UsersHandler {
18
18
  );
19
19
  }
20
20
  }
21
- class CookieHandler {
22
- canHandle(endpoint) {
23
- return endpoint === "cookies";
24
- }
25
- async handle(context, config) {
26
- return await cookieEndpointHandler(context, config);
27
- }
28
- }
29
21
  class SignInsHandler {
30
22
  canHandle(endpoint) {
31
23
  return endpoint === "sign_ins";
32
24
  }
33
- async handle(context, config) {
34
- return await signInEndpointHandler(context, config);
25
+ async handle(context) {
26
+ return await signInEndpointHandler(context);
35
27
  }
36
28
  }
37
29
  class EndpointRouter {
38
30
  static handlers = [
39
31
  new SessionsHandler(),
40
32
  new UsersHandler(),
41
- new CookieHandler(),
42
33
  new SignInsHandler()
43
34
  ];
44
35
  static async route(context, config) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type { RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createApiErrorResponse } from './responses';\nimport { cookieEndpointHandler, sessionEndpointHandler, signInEndpointHandler } from './sessionHandlers';\nimport type { AuthEndpoint, TernSecureHandlerOptions } from './types';\n\nexport interface EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean;\n handle(context: RequestProcessorContext, config: TernSecureHandlerOptions): Promise<Response>;\n}\n\nclass SessionsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sessions';\n }\n\n async handle(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n return await sessionEndpointHandler(context, config);\n }\n}\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(_context: RequestProcessorContext, _config: TernSecureHandlerOptions): Promise<Response> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}\n\nclass CookieHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'cookies';\n }\n\n async handle(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n return await cookieEndpointHandler(context, config);\n }\n}\n\nclass SignInsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sign_ins';\n }\n\n async handle(context: RequestProcessorContext, config: TernSecureHandlerOptions): Promise<Response> {\n return await signInEndpointHandler(context, config);\n }\n}\n\nexport class EndpointRouter {\n private static readonly handlers: EndpointHandler[] = [\n new SessionsHandler(),\n new UsersHandler(),\n new CookieHandler(),\n new SignInsHandler(),\n ];\n\n static async route(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n const { endpoint } = context;\n\n if (!endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n const handler = this.handlers.find(h => h.canHandle(endpoint));\n\n if (!handler) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n return handler.handle(context, config);\n }\n\n static addHandler(handler: EndpointHandler): void {\n this.handlers.push(handler);\n }\n\n static removeHandler(predicate: (handler: EndpointHandler) => boolean): void {\n const index = this.handlers.findIndex(predicate);\n if (index > -1) {\n this.handlers.splice(index, 1);\n }\n }\n}\n"],"mappings":"AACA,SAAS,8BAA8B;AACvC,SAAS,uBAAuB,wBAAwB,6BAA6B;AAQrF,MAAM,gBAA2C;AAAA,EAC/C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,SACA,QACmB;AACnB,WAAO,MAAM,uBAAuB,SAAS,MAAM;AAAA,EACrD;AACF;AAEA,MAAM,aAAwC;AAAA,EAC5C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,OAAO,UAAmC,SAAsD;AAC9F,WAAO,QAAQ;AAAA,MACb,uBAAuB,4BAA4B,kCAAkC,GAAG;AAAA,IAC1F;AAAA,EACF;AACF;AAEA,MAAM,cAAyC;AAAA,EAC7C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,SACA,QACmB;AACnB,WAAO,MAAM,sBAAsB,SAAS,MAAM;AAAA,EACpD;AACF;AAEA,MAAM,eAA0C;AAAA,EAC9C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OAAO,SAAkC,QAAqD;AAClG,WAAO,MAAM,sBAAsB,SAAS,MAAM;AAAA,EACpD;AACF;AAEO,MAAM,eAAe;AAAA,EAC1B,OAAwB,WAA8B;AAAA,IACpD,IAAI,gBAAgB;AAAA,IACpB,IAAI,aAAa;AAAA,IACjB,IAAI,cAAc;AAAA,IAClB,IAAI,eAAe;AAAA,EACrB;AAAA,EAEA,aAAa,MACX,SACA,QACmB;AACnB,UAAM,EAAE,SAAS,IAAI;AAErB,QAAI,CAAC,UAAU;AACb,aAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,IAChF;AAEA,UAAM,UAAU,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAE7D,QAAI,CAAC,SAAS;AACZ,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO,QAAQ,OAAO,SAAS,MAAM;AAAA,EACvC;AAAA,EAEA,OAAO,WAAW,SAAgC;AAChD,SAAK,SAAS,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,OAAO,cAAc,WAAwD;AAC3E,UAAM,QAAQ,KAAK,SAAS,UAAU,SAAS;AAC/C,QAAI,QAAQ,IAAI;AACd,WAAK,SAAS,OAAO,OAAO,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type { AuthenticateRequestOptions, RequestProcessorContext } from '@tern-secure/backend';\nimport type { AuthEndpoint } from '@tern-secure/types';\n\nimport { sessionEndpointHandler, signInEndpointHandler } from './handlers';\nimport { createApiErrorResponse } from './responses';\n\nexport interface EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean;\n handle(context: RequestProcessorContext, config: AuthenticateRequestOptions): Promise<Response>;\n}\n\nclass SessionsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sessions';\n }\n\n async handle(\n context: RequestProcessorContext,\n config: AuthenticateRequestOptions,\n ): Promise<Response> {\n return await sessionEndpointHandler(context, config);\n }\n}\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(_context: RequestProcessorContext, _config: AuthenticateRequestOptions): Promise<Response> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}\n\n\nclass SignInsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sign_ins';\n }\n\n async handle(context: RequestProcessorContext): Promise<Response> {\n return await signInEndpointHandler(context);\n }\n}\n\nexport class EndpointRouter {\n private static readonly handlers: EndpointHandler[] = [\n new SessionsHandler(),\n new UsersHandler(),\n new SignInsHandler(),\n ];\n\n static async route(\n context: RequestProcessorContext,\n config: AuthenticateRequestOptions,\n ): Promise<Response> {\n const { endpoint } = context;\n\n if (!endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n const handler = this.handlers.find(h => h.canHandle(endpoint));\n\n if (!handler) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n return handler.handle(context, config);\n }\n\n static addHandler(handler: EndpointHandler): void {\n this.handlers.push(handler);\n }\n\n static removeHandler(predicate: (handler: EndpointHandler) => boolean): void {\n const index = this.handlers.findIndex(predicate);\n if (index > -1) {\n this.handlers.splice(index, 1);\n }\n }\n}\n"],"mappings":"AAGA,SAAS,wBAAwB,6BAA6B;AAC9D,SAAS,8BAA8B;AAOvC,MAAM,gBAA2C;AAAA,EAC/C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,SACA,QACmB;AACnB,WAAO,MAAM,uBAAuB,SAAS,MAAM;AAAA,EACrD;AACF;AAEA,MAAM,aAAwC;AAAA,EAC5C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,OAAO,UAAmC,SAAwD;AAChG,WAAO,QAAQ;AAAA,MACb,uBAAuB,4BAA4B,kCAAkC,GAAG;AAAA,IAC1F;AAAA,EACF;AACF;AAGA,MAAM,eAA0C;AAAA,EAC9C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OAAO,SAAqD;AAChE,WAAO,MAAM,sBAAsB,OAAO;AAAA,EAC5C;AACF;AAEO,MAAM,eAAe;AAAA,EAC1B,OAAwB,WAA8B;AAAA,IACpD,IAAI,gBAAgB;AAAA,IACpB,IAAI,aAAa;AAAA,IACjB,IAAI,eAAe;AAAA,EACrB;AAAA,EAEA,aAAa,MACX,SACA,QACmB;AACnB,UAAM,EAAE,SAAS,IAAI;AAErB,QAAI,CAAC,UAAU;AACb,aAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,IAChF;AAEA,UAAM,UAAU,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAE7D,QAAI,CAAC,SAAS;AACZ,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO,QAAQ,OAAO,SAAS,MAAM;AAAA,EACvC;AAAA,EAEA,OAAO,WAAW,SAAgC;AAChD,SAAK,SAAS,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,OAAO,cAAc,WAAwD;AAC3E,UAAM,QAAQ,KAAK,SAAS,UAAU,SAAS;AAC/C,QAAI,QAAQ,IAAI;AACd,WAAK,SAAS,OAAO,OAAO,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;","names":[]}
@@ -1,10 +1,8 @@
1
- import { constants } from "@tern-secure/backend";
2
1
  import { clearSessionCookie } from "@tern-secure/backend/admin";
3
2
  import { ternDecodeJwtUnguarded } from "@tern-secure/backend/jwt";
4
3
  import { ternSecureBackendClient } from "../../server/ternsecureClient";
5
4
  import { NextCookieStore } from "../../utils/NextCookieAdapter";
6
5
  import { FIREBASE_API_KEY } from "./constants";
7
- import { createValidators } from "./fnValidators";
8
6
  import { refreshCookieWithIdToken } from "./request";
9
7
  import {
10
8
  createApiErrorResponse,
@@ -13,25 +11,17 @@ import {
13
11
  SessionResponseHelper
14
12
  } from "./responses";
15
13
  import { processSignInCreate } from "./signInCreateHandler";
14
+ import {
15
+ extractSessionRequestData,
16
+ validateCsrfToken,
17
+ validateEmail,
18
+ validateIdToken,
19
+ validateSubEndpointPresent
20
+ } from "./validators";
16
21
  const sessionEndpointHandler = async (context, config) => {
17
22
  const { subEndpoint, method, referrer } = context;
18
- const validators = createValidators(context);
19
- const {
20
- validateSubEndpoint,
21
- validateSecurity,
22
- validateSessionRequest,
23
- validateCsrfToken,
24
- validateIdToken
25
- } = validators;
26
- if (!subEndpoint) {
27
- return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
28
- }
29
- const sessionsConfig = config.endpoints?.sessions;
30
- const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
31
- validateSubEndpoint(subEndpoint, subEndpointConfig);
32
- if (subEndpointConfig?.security) {
33
- await validateSecurity(subEndpointConfig.security);
34
- }
23
+ const subEndpointError = validateSubEndpointPresent(context, "Session");
24
+ if (subEndpointError) return subEndpointError;
35
25
  const SessionGetHandler = async (subEndpoint2) => {
36
26
  const handleSessionVerify = async () => {
37
27
  try {
@@ -57,10 +47,10 @@ const sessionEndpointHandler = async (context, config) => {
57
47
  };
58
48
  const SessionPostHandler = async (subEndpoint2) => {
59
49
  const cookieStore = new NextCookieStore();
60
- const { idToken, csrfToken, error } = await validateSessionRequest();
50
+ const { idToken, csrfToken, error } = await extractSessionRequestData(context.request);
61
51
  if (error) return error;
62
- const csrfCookieValue = await cookieStore.get(constants.Cookies.CsrfToken);
63
- validateCsrfToken(csrfToken || "", csrfCookieValue.value);
52
+ const csrfError = await validateCsrfToken(csrfToken);
53
+ if (csrfError) return csrfError;
64
54
  const handleCreateSession = async (cookieStore2, idToken2) => {
65
55
  try {
66
56
  await refreshCookieWithIdToken(idToken2, cookieStore2, config, referrer, context.appCheckToken);
@@ -120,90 +110,10 @@ const sessionEndpointHandler = async (context, config) => {
120
110
  return HttpResponseHelper.createMethodNotAllowedResponse();
121
111
  }
122
112
  };
123
- const cookieEndpointHandler = async (context, config) => {
124
- const { subEndpoint, method } = context;
125
- const validators = createValidators(context);
126
- const { validateSecurity } = validators;
127
- if (!subEndpoint) {
128
- return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Cookie sub-endpoint required", 400);
129
- }
130
- const cookiesConfig = config.endpoints?.cookies;
131
- const subEndpointConfig = cookiesConfig?.subEndpoints?.[subEndpoint];
132
- if (!subEndpointConfig || !subEndpointConfig.enabled) {
133
- return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Cookie endpoint not found or disabled", 404);
134
- }
135
- if (subEndpointConfig?.security) {
136
- await validateSecurity(subEndpointConfig.security);
137
- }
138
- const CookieGetHandler = async (subEndpoint2) => {
139
- const handleGetCookie = async () => {
140
- try {
141
- const url = new URL(context.ternUrl);
142
- const tokenName = url.searchParams.get("tokenName");
143
- if (!tokenName) {
144
- return createApiErrorResponse("TOKEN_NAME_REQUIRED", "tokenName query parameter is required", 400);
145
- }
146
- let cookieValue;
147
- switch (tokenName) {
148
- case "idToken":
149
- cookieValue = context.idTokenInCookie;
150
- break;
151
- case "sessionToken":
152
- cookieValue = context.sessionTokenInCookie;
153
- break;
154
- case "refreshToken":
155
- cookieValue = context.refreshTokenInCookie;
156
- break;
157
- case "customToken":
158
- cookieValue = context.customTokenInCookie;
159
- break;
160
- default:
161
- return createApiErrorResponse("INVALID_TOKEN_NAME", "Invalid token name. Must be one of: idToken, sessionToken, refreshToken, customToken", 400);
162
- }
163
- if (!cookieValue) {
164
- return createApiErrorResponse(
165
- "TOKEN_NOT_FOUND",
166
- `${tokenName} not found in httpOnly cookies`,
167
- 404
168
- );
169
- }
170
- return createApiSuccessResponse({
171
- token: cookieValue
172
- });
173
- } catch (error) {
174
- return createApiErrorResponse("COOKIE_RETRIEVAL_FAILED", "Failed to retrieve cookie", 500);
175
- }
176
- };
177
- switch (subEndpoint2) {
178
- case "get":
179
- return handleGetCookie();
180
- default:
181
- return HttpResponseHelper.createNotFoundResponse();
182
- }
183
- };
184
- switch (method) {
185
- case "GET":
186
- return CookieGetHandler(subEndpoint);
187
- default:
188
- return HttpResponseHelper.createMethodNotAllowedResponse();
189
- }
190
- };
191
- const signInEndpointHandler = async (context, config) => {
113
+ const signInEndpointHandler = async (context) => {
192
114
  const { subEndpoint, method } = context;
193
- const validators = createValidators(context);
194
- const {
195
- validateSubEndpoint,
196
- validateSecurity
197
- } = validators;
198
- if (!subEndpoint) {
199
- return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Sign_ins sub-endpoint required", 400);
200
- }
201
- const signInsConfig = config.endpoints?.signIns;
202
- const subEndpointConfig = signInsConfig?.subEndpoints?.[subEndpoint];
203
- validateSubEndpoint(subEndpoint, subEndpointConfig);
204
- if (subEndpointConfig?.security) {
205
- await validateSecurity(subEndpointConfig.security);
206
- }
115
+ const subEndpointError = validateSubEndpointPresent(context, "Sign_ins");
116
+ if (subEndpointError) return subEndpointError;
207
117
  const PostHandler = async (subEndpoint2) => {
208
118
  const create = async () => {
209
119
  return await processSignInCreate(context);
@@ -212,9 +122,8 @@ const signInEndpointHandler = async (context, config) => {
212
122
  try {
213
123
  const body = await context.request.json();
214
124
  const { email } = body;
215
- if (!email || typeof email !== "string") {
216
- return createApiErrorResponse("EMAIL_REQUIRED", "Email is required", 400);
217
- }
125
+ const emailError = validateEmail(email);
126
+ if (emailError) return emailError;
218
127
  const backendClient = await ternSecureBackendClient();
219
128
  const response = await backendClient.signIn.resetPasswordEmail(FIREBASE_API_KEY, {
220
129
  email,
@@ -255,8 +164,7 @@ const signInEndpointHandler = async (context, config) => {
255
164
  }
256
165
  };
257
166
  export {
258
- cookieEndpointHandler,
259
167
  sessionEndpointHandler,
260
168
  signInEndpointHandler
261
169
  };
262
- //# sourceMappingURL=sessionHandlers.js.map
170
+ //# sourceMappingURL=handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/handlers.ts"],"sourcesContent":["import type { AuthenticateRequestOptions, RequestProcessorContext } from '@tern-secure/backend';\nimport { clearSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\n\nimport { ternSecureBackendClient } from '../../server/ternsecureClient';\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { FIREBASE_API_KEY } from './constants';\nimport { refreshCookieWithIdToken } from './request';\nimport {\n createApiErrorResponse,\n createApiSuccessResponse,\n HttpResponseHelper,\n SessionResponseHelper,\n} from './responses';\nimport { processSignInCreate } from './signInCreateHandler';\nimport type { SessionSubEndpoint, SignInSubEndpoint, } from './types';\nimport {\n extractSessionRequestData,\n validateCsrfToken,\n validateEmail,\n validateIdToken,\n validateSubEndpointPresent,\n} from './validators';\n\nconst sessionEndpointHandler = async (\n context: RequestProcessorContext,\n config: AuthenticateRequestOptions,\n): Promise<Response> => {\n const { subEndpoint, method, referrer } = context;\n\n // Validate sub-endpoint exists\n const subEndpointError = validateSubEndpointPresent(context, 'Session');\n if (subEndpointError) return subEndpointError;\n\n const SessionGetHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const handleSessionVerify = async (): Promise<Response> => {\n try {\n const sessionCookie = context.sessionTokenInCookie;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);\n if (errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n };\n\n switch (subEndpoint) {\n case 'verify':\n return handleSessionVerify();\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n };\n\n const SessionPostHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await extractSessionRequestData(context.request);\n if (error) return error;\n\n const csrfError = await validateCsrfToken(csrfToken);\n if (csrfError) return csrfError;\n\n const handleCreateSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n await refreshCookieWithIdToken(idToken, cookieStore, config, referrer, context.appCheckToken);\n return SessionResponseHelper.createSessionCreationResponse({\n success: true,\n message: 'Session created successfully',\n });\n } catch (error) {\n console.error('[SessionHandler - createsession] Error:', error);\n const errorMessage = error instanceof Error ? error.message : 'Session creation failed';\n return createApiErrorResponse('SESSION_CREATION_FAILED', errorMessage, 500);\n }\n };\n\n const handleRefreshSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n const decodedSession = ternDecodeJwtUnguarded(idToken);\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await refreshCookieWithIdToken(\n idToken,\n cookieStore,\n config,\n undefined,\n context.appCheckToken,\n );\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'Session refresh failed';\n return createApiErrorResponse('REFRESH_FAILED', errorMessage, 500);\n }\n };\n\n const handleRevokeSession = async (cookieStore: NextCookieStore): Promise<Response> => {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n };\n\n switch (subEndpoint) {\n case 'createsession': {\n const idTokenError = validateIdToken(idToken);\n if (idTokenError) return idTokenError;\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleCreateSession(cookieStore, idToken!);\n }\n\n case 'refresh':\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleRefreshSession(cookieStore, idToken!);\n\n case 'revoke':\n return handleRevokeSession(cookieStore);\n\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n };\n\n switch (method) {\n case 'GET':\n return SessionGetHandler(subEndpoint as SessionSubEndpoint);\n\n case 'POST':\n return SessionPostHandler(subEndpoint as SessionSubEndpoint);\n\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n}\n\n\nconst signInEndpointHandler = async (\n context: RequestProcessorContext,\n): Promise<Response> => {\n const { subEndpoint, method } = context;\n\n // Validate sub-endpoint exists\n const subEndpointError = validateSubEndpointPresent(context, 'Sign_ins');\n if (subEndpointError) return subEndpointError;\n\n const PostHandler = async (subEndpoint: SignInSubEndpoint): Promise<Response> => {\n const create = async (): Promise<Response> => {\n return await processSignInCreate(context);\n };\n\n const passwordResetEmail = async (): Promise<Response> => {\n try {\n const body = await context.request.json();\n const { email } = body;\n\n const emailError = validateEmail(email);\n if (emailError) return emailError;\n\n const backendClient = await ternSecureBackendClient();\n\n const response = await backendClient.signIn.resetPasswordEmail(FIREBASE_API_KEY, {\n email,\n requestType: 'PASSWORD_RESET',\n });\n\n if (!response) {\n return createApiErrorResponse(\n 'PASSWORD_RESET_FAILED',\n 'Failed to send password reset email',\n 500,\n );\n }\n\n return createApiSuccessResponse({\n email,\n });\n } catch (error) {\n return createApiErrorResponse(\n 'PASSWORD_RESET_ERROR',\n error instanceof Error\n ? error.message\n : 'An error occurred while sending password reset email',\n 500,\n );\n }\n };\n\n switch (subEndpoint) {\n case 'create':\n return create();\n case 'resetPasswordEmail':\n return passwordResetEmail();\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n };\n\n switch (method) {\n case 'POST':\n return PostHandler(subEndpoint as SignInSubEndpoint);\n\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n\n}\n\nexport { sessionEndpointHandler, signInEndpointHandler };\n"],"mappings":"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","names":["subEndpoint","cookieStore","idToken","error"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createTernSecureNextJsHandler } from './ternsecureNextjsHandler'\n\nexport {\n clearSessionCookieServer,\n clearNextSessionCookie,\n createSessionCookieServer,\n createNextSessionCookie,\n setNextServerSession,\n setNextServerToken\n} from './actions'\n\nexport { EndpointRouter } from './endpointRouter'\n\nexport type { TernSecureHandlerOptions } from './types'"],"mappings":"AAAA,SAAS,qCAAqC;AAE9C;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAEP,SAAS,sBAAsB;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createTernSecureNextJsHandler } from './ternsecureNextjsHandler'\n\nexport {\n clearSessionCookieServer,\n clearNextSessionCookie,\n createSessionCookieServer,\n createNextSessionCookie,\n setNextServerSession,\n setNextServerToken\n} from './actions'\n\nexport { EndpointRouter } from './endpointRouter'\n\nexport type { ApiHandlerOptions, TernSecureHandlerOptions } from './types'"],"mappings":"AAAA,SAAS,qCAAqC;AAE9C;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAEP,SAAS,sBAAsB;","names":[]}
@@ -3,26 +3,14 @@ import { getAuth } from "@tern-secure/backend/auth";
3
3
  import { getCookieName, getCookiePrefix } from "@tern-secure/shared/cookie";
4
4
  import { ternSecureBackendClient } from "../../server/ternsecureClient";
5
5
  import {
6
- FIREBASE_API_KEY,
7
- FIREBASE_APP_ID,
8
- FIREBASE_AUTH_DOMAIN,
9
- FIREBASE_MESSAGING_SENDER_ID,
10
- FIREBASE_PROJECT_ID,
11
- FIREBASE_STORAGE_BUCKET
6
+ FIREBASE_API_KEY
12
7
  } from "./constants";
13
8
  import { getIdTokenCookieOptions } from "./cookieOptionsHelper";
14
9
  async function refreshCookieWithIdToken(idToken, cookieStore, config, referrer, appCheckToken) {
15
10
  const backendClient = await ternSecureBackendClient();
16
11
  const authOptions = {
17
12
  tenantId: config?.tenantId || void 0,
18
- firebaseConfig: {
19
- apiKey: FIREBASE_API_KEY,
20
- authDomain: FIREBASE_AUTH_DOMAIN,
21
- projectId: FIREBASE_PROJECT_ID,
22
- storageBucket: FIREBASE_STORAGE_BUCKET,
23
- messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,
24
- appId: FIREBASE_APP_ID
25
- },
13
+ apiKey: FIREBASE_API_KEY,
26
14
  apiClient: backendClient
27
15
  };
28
16
  const COOKIE_OPTIONS = getIdTokenCookieOptions();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/request.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\nimport { getAuth } from '@tern-secure/backend/auth';\nimport { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nimport { ternSecureBackendClient } from '../../server/ternsecureClient';\nimport type { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport {\n FIREBASE_API_KEY,\n FIREBASE_APP_ID,\n FIREBASE_AUTH_DOMAIN,\n FIREBASE_MESSAGING_SENDER_ID,\n FIREBASE_PROJECT_ID,\n FIREBASE_STORAGE_BUCKET,\n} from './constants';\nimport { getIdTokenCookieOptions } from './cookieOptionsHelper';\nimport type { TernSecureHandlerOptions } from './types';\n\nexport async function refreshCookieWithIdToken(\n idToken: string,\n cookieStore: NextCookieStore,\n config?: TernSecureHandlerOptions,\n referrer?: string,\n appCheckToken?: string,\n): Promise<void> {\n const backendClient = await ternSecureBackendClient();\n\n const authOptions: AuthenticateRequestOptions = {\n tenantId: config?.tenantId || undefined,\n firebaseConfig: {\n apiKey: FIREBASE_API_KEY,\n authDomain: FIREBASE_AUTH_DOMAIN,\n projectId: FIREBASE_PROJECT_ID,\n storageBucket: FIREBASE_STORAGE_BUCKET,\n messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,\n appId: FIREBASE_APP_ID,\n },\n apiClient: backendClient,\n };\n\n const COOKIE_OPTIONS = getIdTokenCookieOptions();\n\n const { createCustomIdAndRefreshToken } = getAuth(authOptions);\n\n\n const customTokens = await createCustomIdAndRefreshToken(idToken, {\n referer: referrer,\n appCheckToken,\n });\n\n\n const cookiePrefix = getCookiePrefix();\n\n const cookiePromises = [\n cookieStore.set(\n getCookieName(constants.Cookies.IdToken, cookiePrefix),\n customTokens.idToken,\n COOKIE_OPTIONS,\n ),\n cookieStore.set(\n getCookieName(constants.Cookies.Refresh, cookiePrefix),\n customTokens.refreshToken,\n COOKIE_OPTIONS,\n ),\n\n cookieStore.set(\n constants.Cookies.TernAut,\n customTokens.auth_time.toString(),\n { secure: true, maxAge: 365 * 24 * 60 * 60 }\n ),\n ];\n\n if (config?.enableCustomToken) {\n cookiePromises.push(\n cookieStore.set(constants.Cookies.Custom, customTokens.customToken, COOKIE_OPTIONS),\n );\n }\n\n await Promise.all(cookiePromises);\n}\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,eAAe,uBAAuB;AAE/C,SAAS,+BAA+B;AAExC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,+BAA+B;AAGxC,eAAsB,yBACpB,SACA,aACA,QACA,UACA,eACe;AACf,QAAM,gBAAgB,MAAM,wBAAwB;AAEpD,QAAM,cAA0C;AAAA,IAC9C,UAAU,QAAQ,YAAY;AAAA,IAC9B,gBAAgB;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,eAAe;AAAA,MACf,mBAAmB;AAAA,MACnB,OAAO;AAAA,IACT;AAAA,IACA,WAAW;AAAA,EACb;AAEA,QAAM,iBAAiB,wBAAwB;AAE/C,QAAM,EAAE,8BAA8B,IAAI,QAAQ,WAAW;AAG7D,QAAM,eAAe,MAAM,8BAA8B,SAAS;AAAA,IAChE,SAAS;AAAA,IACT;AAAA,EACF,CAAC;AAGD,QAAM,eAAe,gBAAgB;AAErC,QAAM,iBAAiB;AAAA,IACrB,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IAEA,YAAY;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,aAAa,UAAU,SAAS;AAAA,MAChC,EAAE,QAAQ,MAAM,QAAQ,MAAM,KAAK,KAAK,GAAG;AAAA,IAC7C;AAAA,EACF;AAEA,MAAI,QAAQ,mBAAmB;AAC7B,mBAAe;AAAA,MACb,YAAY,IAAI,UAAU,QAAQ,QAAQ,aAAa,aAAa,cAAc;AAAA,IACpF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,cAAc;AAClC;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/request.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\nimport { getAuth } from '@tern-secure/backend/auth';\nimport { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nimport { ternSecureBackendClient } from '../../server/ternsecureClient';\nimport type { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport {\n FIREBASE_API_KEY,\n} from './constants';\nimport { getIdTokenCookieOptions } from './cookieOptionsHelper';\nimport type { ApiHandlerOptions } from './types';\n\nexport async function refreshCookieWithIdToken(\n idToken: string,\n cookieStore: NextCookieStore,\n config: ApiHandlerOptions,\n referrer?: string,\n appCheckToken?: string,\n): Promise<void> {\n const backendClient = await ternSecureBackendClient();\n\n const authOptions: AuthenticateRequestOptions = {\n tenantId: config?.tenantId || undefined,\n apiKey: FIREBASE_API_KEY,\n apiClient: backendClient,\n };\n\n const COOKIE_OPTIONS = getIdTokenCookieOptions();\n\n const { createCustomIdAndRefreshToken } = getAuth(authOptions);\n\n const customTokens = await createCustomIdAndRefreshToken(idToken, {\n referer: referrer,\n appCheckToken,\n });\n\n\n const cookiePrefix = getCookiePrefix();\n\n const cookiePromises = [\n cookieStore.set(\n getCookieName(constants.Cookies.IdToken, cookiePrefix),\n customTokens.idToken,\n COOKIE_OPTIONS,\n ),\n cookieStore.set(\n getCookieName(constants.Cookies.Refresh, cookiePrefix),\n customTokens.refreshToken,\n COOKIE_OPTIONS,\n ),\n\n cookieStore.set(\n constants.Cookies.TernAut,\n customTokens.auth_time.toString(),\n { secure: true, maxAge: 365 * 24 * 60 * 60 }\n ),\n ];\n\n if (config?.enableCustomToken) {\n cookiePromises.push(\n cookieStore.set(constants.Cookies.Custom, customTokens.customToken, COOKIE_OPTIONS),\n );\n }\n\n await Promise.all(cookiePromises);\n}\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,eAAe,uBAAuB;AAE/C,SAAS,+BAA+B;AAExC;AAAA,EACE;AAAA,OACK;AACP,SAAS,+BAA+B;AAGxC,eAAsB,yBACpB,SACA,aACA,QACA,UACA,eACe;AACf,QAAM,gBAAgB,MAAM,wBAAwB;AAEpD,QAAM,cAA0C;AAAA,IAC9C,UAAU,QAAQ,YAAY;AAAA,IAC9B,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAEA,QAAM,iBAAiB,wBAAwB;AAE/C,QAAM,EAAE,8BAA8B,IAAI,QAAQ,WAAW;AAE7D,QAAM,eAAe,MAAM,8BAA8B,SAAS;AAAA,IAChE,SAAS;AAAA,IACT;AAAA,EACF,CAAC;AAGD,QAAM,eAAe,gBAAgB;AAErC,QAAM,iBAAiB;AAAA,IACrB,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IAEA,YAAY;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,aAAa,UAAU,SAAS;AAAA,MAChC,EAAE,QAAQ,MAAM,QAAQ,MAAM,KAAK,KAAK,GAAG;AAAA,IAC7C;AAAA,EACF;AAEA,MAAI,QAAQ,mBAAmB;AAC7B,mBAAe;AAAA,MACb,YAAY,IAAI,UAAU,QAAQ,QAAQ,aAAa,aAAa,cAAc;AAAA,IACpF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,cAAc;AAClC;","names":[]}