@tern-secure/nextjs 5.2.0-canary.v20250916132854 → 5.2.0-canary.v20250919131424

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 (76) hide show
  1. package/dist/cjs/app-router/admin/api/endpoints/abstract.js +39 -0
  2. package/dist/cjs/app-router/admin/api/endpoints/abstract.js.map +1 -0
  3. package/dist/cjs/app-router/admin/api/endpoints/sessions.js +2 -0
  4. package/dist/cjs/app-router/admin/api/endpoints/sessions.js.map +1 -0
  5. package/dist/cjs/app-router/admin/api/endpoints/users.js +4 -0
  6. package/dist/cjs/app-router/admin/api/endpoints/users.js.map +1 -0
  7. package/dist/cjs/app-router/admin/claude-authenticateRequestProcessor.js +79 -0
  8. package/dist/cjs/app-router/admin/claude-authenticateRequestProcessor.js.map +1 -0
  9. package/dist/cjs/app-router/admin/endpointRouter.js +72 -0
  10. package/dist/cjs/app-router/admin/endpointRouter.js.map +1 -0
  11. package/dist/cjs/app-router/admin/fnValidators.js +4 -3
  12. package/dist/cjs/app-router/admin/fnValidators.js.map +1 -1
  13. package/dist/cjs/app-router/admin/handlerUtils.js +63 -0
  14. package/dist/cjs/app-router/admin/handlerUtils.js.map +1 -0
  15. package/dist/cjs/app-router/admin/index.js +8 -0
  16. package/dist/cjs/app-router/admin/index.js.map +1 -1
  17. package/dist/cjs/app-router/admin/sessionHandlers.js +15 -13
  18. package/dist/cjs/app-router/admin/sessionHandlers.js.map +1 -1
  19. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js +31 -36
  20. package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
  21. package/dist/cjs/app-router/admin/types.js +0 -1
  22. package/dist/cjs/app-router/admin/types.js.map +1 -1
  23. package/dist/cjs/app-router/admin/validators.js +1 -2
  24. package/dist/cjs/app-router/admin/validators.js.map +1 -1
  25. package/dist/cjs/utils/NextCookieAdapter.js.map +1 -1
  26. package/dist/esm/app-router/admin/api/endpoints/abstract.js +15 -0
  27. package/dist/esm/app-router/admin/api/endpoints/abstract.js.map +1 -0
  28. package/dist/esm/app-router/admin/api/endpoints/sessions.js +1 -0
  29. package/dist/esm/app-router/admin/api/endpoints/sessions.js.map +1 -0
  30. package/dist/esm/app-router/admin/api/endpoints/users.js +3 -0
  31. package/dist/esm/app-router/admin/api/endpoints/users.js.map +1 -0
  32. package/dist/esm/app-router/admin/claude-authenticateRequestProcessor.js +55 -0
  33. package/dist/esm/app-router/admin/claude-authenticateRequestProcessor.js.map +1 -0
  34. package/dist/esm/app-router/admin/endpointRouter.js +48 -0
  35. package/dist/esm/app-router/admin/endpointRouter.js.map +1 -0
  36. package/dist/esm/app-router/admin/fnValidators.js +4 -3
  37. package/dist/esm/app-router/admin/fnValidators.js.map +1 -1
  38. package/dist/esm/app-router/admin/handlerUtils.js +38 -0
  39. package/dist/esm/app-router/admin/handlerUtils.js.map +1 -0
  40. package/dist/esm/app-router/admin/index.js +5 -0
  41. package/dist/esm/app-router/admin/index.js.map +1 -1
  42. package/dist/esm/app-router/admin/sessionHandlers.js +15 -13
  43. package/dist/esm/app-router/admin/sessionHandlers.js.map +1 -1
  44. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js +34 -41
  45. package/dist/esm/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
  46. package/dist/esm/app-router/admin/types.js +0 -1
  47. package/dist/esm/app-router/admin/types.js.map +1 -1
  48. package/dist/esm/app-router/admin/validators.js +1 -2
  49. package/dist/esm/app-router/admin/validators.js.map +1 -1
  50. package/dist/esm/utils/NextCookieAdapter.js.map +1 -1
  51. package/dist/types/app-router/admin/api/endpoints/abstract.d.ts +19 -0
  52. package/dist/types/app-router/admin/api/endpoints/abstract.d.ts.map +1 -0
  53. package/dist/types/app-router/admin/api/endpoints/sessions.d.ts +2 -0
  54. package/dist/types/app-router/admin/api/endpoints/sessions.d.ts.map +1 -0
  55. package/dist/types/app-router/admin/api/endpoints/users.d.ts +2 -0
  56. package/dist/types/app-router/admin/api/endpoints/users.d.ts.map +1 -0
  57. package/dist/types/app-router/admin/claude-authenticateRequestProcessor.d.ts +37 -0
  58. package/dist/types/app-router/admin/claude-authenticateRequestProcessor.d.ts.map +1 -0
  59. package/dist/types/app-router/admin/endpointRouter.d.ts +10 -0
  60. package/dist/types/app-router/admin/endpointRouter.d.ts.map +1 -0
  61. package/dist/types/app-router/admin/fnValidators.d.ts +11 -12
  62. package/dist/types/app-router/admin/fnValidators.d.ts.map +1 -1
  63. package/dist/types/app-router/admin/handlerUtils.d.ts +19 -0
  64. package/dist/types/app-router/admin/handlerUtils.d.ts.map +1 -0
  65. package/dist/types/app-router/admin/index.d.ts +4 -1
  66. package/dist/types/app-router/admin/index.d.ts.map +1 -1
  67. package/dist/types/app-router/admin/sessionHandlers.d.ts +3 -4
  68. package/dist/types/app-router/admin/sessionHandlers.d.ts.map +1 -1
  69. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts +3 -4
  70. package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts.map +1 -1
  71. package/dist/types/app-router/admin/types.d.ts +2 -3
  72. package/dist/types/app-router/admin/types.d.ts.map +1 -1
  73. package/dist/types/app-router/admin/validators.d.ts +10 -12
  74. package/dist/types/app-router/admin/validators.d.ts.map +1 -1
  75. package/dist/types/utils/NextCookieAdapter.d.ts.map +1 -1
  76. package/package.json +5 -5
@@ -0,0 +1,39 @@
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 abstract_exports = {};
20
+ __export(abstract_exports, {
21
+ BaseEndpointHandler: () => BaseEndpointHandler
22
+ });
23
+ module.exports = __toCommonJS(abstract_exports);
24
+ class BaseEndpointHandler {
25
+ validateMethod(allowedMethods, method) {
26
+ return allowedMethods.includes(method);
27
+ }
28
+ validateSubEndpoint(subEndpoint, requiredSubEndpoint) {
29
+ if (requiredSubEndpoint) {
30
+ return subEndpoint !== void 0;
31
+ }
32
+ return true;
33
+ }
34
+ }
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ BaseEndpointHandler
38
+ });
39
+ //# sourceMappingURL=abstract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/app-router/admin/api/endpoints/abstract.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n SessionSubEndpoint,\n TernSecureInternalHandlerConfig,\n} from '../../types';\n\nexport interface HandlerContext {\n request: Request;\n pathSegments: string[];\n endpoint: AuthEndpoint;\n subEndpoint: SessionSubEndpoint | undefined;\n method: string;\n}\n\nexport interface EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean;\n handle(\n handlerContext: HandlerContext,\n config: TernSecureInternalHandlerConfig,\n ): Promise<Response>;\n}\n\nexport abstract class BaseEndpointHandler implements EndpointHandler {\n abstract canHandle(endpoint: AuthEndpoint): boolean;\n abstract handle(\n handlerContext: HandlerContext,\n config: TernSecureInternalHandlerConfig,\n ): Promise<Response>;\n\n protected validateMethod(allowedMethods: string[], method: string): boolean {\n return allowedMethods.includes(method);\n }\n\n protected validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n requiredSubEndpoint?: boolean,\n ): boolean {\n if (requiredSubEndpoint) {\n return subEndpoint !== undefined;\n }\n return true;\n }\n}"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBO,MAAe,oBAA+C;AAAA,EAOzD,eAAe,gBAA0B,QAAyB;AAC1E,WAAO,eAAe,SAAS,MAAM;AAAA,EACvC;AAAA,EAEU,oBACR,aACA,qBACS;AACT,QAAI,qBAAqB;AACvB,aAAO,gBAAgB;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ {
3
+ }
4
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../src/app-router/admin/api/endpoints/users.ts"],"sourcesContent":["{/*import type { NextResponse } from 'next/server';\n\nimport type { AuthEndpoint, TernSecureInternalHandlerConfig } from '../../types';\nimport type { EndpointHandler, HandlerContext } from './abstract';\nimport { createApiErrorResponse } from './responses';\nimport { SessionEndpointHandler } from './sessionHandlers';\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(\n _handlerContext: HandlerContext,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<NextResponse> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}*/}"],"mappings":";AAAA;AAoBG;","names":[]}
@@ -0,0 +1,79 @@
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 claude_authenticateRequestProcessor_exports = {};
20
+ __export(claude_authenticateRequestProcessor_exports, {
21
+ createRequestProcessor: () => createRequestProcessor
22
+ });
23
+ module.exports = __toCommonJS(claude_authenticateRequestProcessor_exports);
24
+ var import_backend = require("@tern-secure/backend");
25
+ class RequestProcessorContext {
26
+ constructor(ternSecureRequest, options) {
27
+ this.ternSecureRequest = ternSecureRequest;
28
+ this.options = options;
29
+ this.initHeaderValues();
30
+ this.initCookieValues();
31
+ this.ternUrl = this.ternSecureRequest.ternUrl;
32
+ }
33
+ initHeaderValues() {
34
+ this.sessionTokenInHeader = this.parseAuthorizationHeader(
35
+ this.getHeader(import_backend.constants.Headers.Authorization)
36
+ );
37
+ this.origin = this.getHeader(import_backend.constants.Headers.Origin);
38
+ this.host = this.getHeader(import_backend.constants.Headers.Host);
39
+ this.forwardedHost = this.getHeader(import_backend.constants.Headers.ForwardedHost);
40
+ this.forwardedProto = this.getHeader(import_backend.constants.Headers.CloudFrontForwardedProto) || this.getHeader(import_backend.constants.Headers.ForwardedProto);
41
+ this.referrer = this.getHeader(import_backend.constants.Headers.Referrer);
42
+ this.userAgent = this.getHeader(import_backend.constants.Headers.UserAgent);
43
+ this.secFetchDest = this.getHeader(import_backend.constants.Headers.SecFetchDest);
44
+ this.accept = this.getHeader(import_backend.constants.Headers.Accept);
45
+ }
46
+ initCookieValues() {
47
+ this.csrfTokenInCookie = this.getCookie(import_backend.constants.Cookies.CsrfToken);
48
+ }
49
+ getQueryParam(name) {
50
+ return this.ternSecureRequest.ternUrl.searchParams.get(name);
51
+ }
52
+ getHeader(name) {
53
+ return this.ternSecureRequest.headers.get(name) || void 0;
54
+ }
55
+ getCookie(name) {
56
+ return this.ternSecureRequest.cookies.get(name) || void 0;
57
+ }
58
+ parseAuthorizationHeader(authorizationHeader) {
59
+ if (!authorizationHeader) {
60
+ return void 0;
61
+ }
62
+ const [scheme, token] = authorizationHeader.split(" ", 2);
63
+ if (!token) {
64
+ return scheme;
65
+ }
66
+ if (scheme === "Bearer") {
67
+ return token;
68
+ }
69
+ return void 0;
70
+ }
71
+ }
72
+ const createRequestProcessor = async (ternSecureRequest, options) => {
73
+ return new RequestProcessorContext(ternSecureRequest, options);
74
+ };
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ createRequestProcessor
78
+ });
79
+ //# sourceMappingURL=claude-authenticateRequestProcessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/claude-authenticateRequestProcessor.ts"],"sourcesContent":["import type { TernSecureRequest } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\n\nimport type { TernSecureHandlerOptions} from './types';\n\n/**\n * Request context for better type safety and clarity\n */\ninterface RequestProcessorContext extends TernSecureHandlerOptions {\n // header-based values\n sessionTokenInHeader: string | undefined;\n origin: string | undefined;\n host: string | undefined;\n forwardedHost: string | undefined;\n forwardedProto: string | undefined;\n referrer: string | undefined;\n userAgent: string | undefined;\n secFetchDest: string | undefined;\n accept: string | undefined;\n\n // cookie-based values\n sessionTokenInCookie: string | undefined;\n refreshTokenInCookie: string | undefined;\n csrfTokenInCookie: string | undefined;\n\n ternUrl: URL;\n}\n\n/**\n * Request processor utility class for common operations\n */\nclass RequestProcessorContext implements RequestProcessorContext {\n public constructor(\n private ternSecureRequest: TernSecureRequest,\n private options: TernSecureHandlerOptions,\n ) {\n this.initHeaderValues();\n this.initCookieValues();\n this.ternUrl = this.ternSecureRequest.ternUrl;\n }\n\n private initHeaderValues() {\n this.sessionTokenInHeader = this.parseAuthorizationHeader(\n this.getHeader(constants.Headers.Authorization),\n );\n this.origin = this.getHeader(constants.Headers.Origin);\n this.host = this.getHeader(constants.Headers.Host);\n this.forwardedHost = this.getHeader(constants.Headers.ForwardedHost);\n this.forwardedProto =\n this.getHeader(constants.Headers.CloudFrontForwardedProto) ||\n this.getHeader(constants.Headers.ForwardedProto);\n this.referrer = this.getHeader(constants.Headers.Referrer);\n this.userAgent = this.getHeader(constants.Headers.UserAgent);\n this.secFetchDest = this.getHeader(constants.Headers.SecFetchDest);\n this.accept = this.getHeader(constants.Headers.Accept);\n }\n\n private initCookieValues() {\n //this.sessionTokenInCookie = this.getCookie(this.options.cookies.name);\n this.csrfTokenInCookie = this.getCookie(constants.Cookies.CsrfToken);\n }\n\n private getQueryParam(name: string) {\n return this.ternSecureRequest.ternUrl.searchParams.get(name);\n }\n\n private getHeader(name: string) {\n return this.ternSecureRequest.headers.get(name) || undefined;\n }\n\n private getCookie(name: string) {\n return this.ternSecureRequest.cookies.get(name) || undefined;\n }\n\n private parseAuthorizationHeader(\n authorizationHeader: string | undefined | null,\n ): string | undefined {\n if (!authorizationHeader) {\n return undefined;\n }\n\n const [scheme, token] = authorizationHeader.split(' ', 2);\n\n if (!token) {\n // No scheme specified, treat the entire value as the token\n return scheme;\n }\n\n if (scheme === 'Bearer') {\n return token;\n }\n\n // Skip all other schemes\n return undefined;\n }\n}\n\nexport type { RequestProcessorContext };\n\nexport const createRequestProcessor = async (\n ternSecureRequest: TernSecureRequest,\n options: TernSecureHandlerOptions,\n): Promise<RequestProcessorContext> => {\n return new RequestProcessorContext(ternSecureRequest, options);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAA0B;AA8B1B,MAAM,wBAA2D;AAAA,EACxD,YACG,mBACA,SACR;AAFQ;AACA;AAER,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AACtB,SAAK,UAAU,KAAK,kBAAkB;AAAA,EACxC;AAAA,EAEQ,mBAAmB;AACzB,SAAK,uBAAuB,KAAK;AAAA,MAC/B,KAAK,UAAU,yBAAU,QAAQ,aAAa;AAAA,IAChD;AACA,SAAK,SAAS,KAAK,UAAU,yBAAU,QAAQ,MAAM;AACrD,SAAK,OAAO,KAAK,UAAU,yBAAU,QAAQ,IAAI;AACjD,SAAK,gBAAgB,KAAK,UAAU,yBAAU,QAAQ,aAAa;AACnE,SAAK,iBACH,KAAK,UAAU,yBAAU,QAAQ,wBAAwB,KACzD,KAAK,UAAU,yBAAU,QAAQ,cAAc;AACjD,SAAK,WAAW,KAAK,UAAU,yBAAU,QAAQ,QAAQ;AACzD,SAAK,YAAY,KAAK,UAAU,yBAAU,QAAQ,SAAS;AAC3D,SAAK,eAAe,KAAK,UAAU,yBAAU,QAAQ,YAAY;AACjE,SAAK,SAAS,KAAK,UAAU,yBAAU,QAAQ,MAAM;AAAA,EACvD;AAAA,EAEQ,mBAAmB;AAEzB,SAAK,oBAAoB,KAAK,UAAU,yBAAU,QAAQ,SAAS;AAAA,EACrE;AAAA,EAEQ,cAAc,MAAc;AAClC,WAAO,KAAK,kBAAkB,QAAQ,aAAa,IAAI,IAAI;AAAA,EAC7D;AAAA,EAEQ,UAAU,MAAc;AAC9B,WAAO,KAAK,kBAAkB,QAAQ,IAAI,IAAI,KAAK;AAAA,EACrD;AAAA,EAEQ,UAAU,MAAc;AAC9B,WAAO,KAAK,kBAAkB,QAAQ,IAAI,IAAI,KAAK;AAAA,EACrD;AAAA,EAEQ,yBACN,qBACoB;AACpB,QAAI,CAAC,qBAAqB;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,CAAC,QAAQ,KAAK,IAAI,oBAAoB,MAAM,KAAK,CAAC;AAExD,QAAI,CAAC,OAAO;AAEV,aAAO;AAAA,IACT;AAEA,QAAI,WAAW,UAAU;AACvB,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,EACT;AACF;AAIO,MAAM,yBAAyB,OACpC,mBACA,YACqC;AACrC,SAAO,IAAI,wBAAwB,mBAAmB,OAAO;AAC/D;","names":[]}
@@ -0,0 +1,72 @@
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 endpointRouter_exports = {};
20
+ __export(endpointRouter_exports, {
21
+ EndpointRouter: () => EndpointRouter
22
+ });
23
+ module.exports = __toCommonJS(endpointRouter_exports);
24
+ var import_responses = require("./responses");
25
+ var import_sessionHandlers = require("./sessionHandlers");
26
+ class SessionsHandler {
27
+ canHandle(endpoint) {
28
+ return endpoint === "sessions";
29
+ }
30
+ async handle(handlerContext, config) {
31
+ const { request, subEndpoint, method } = handlerContext;
32
+ return await import_sessionHandlers.SessionEndpointHandler.handle(request, method, subEndpoint, config);
33
+ }
34
+ }
35
+ class UsersHandler {
36
+ canHandle(endpoint) {
37
+ return endpoint === "users";
38
+ }
39
+ handle(_handlerContext, _config) {
40
+ return Promise.resolve(
41
+ (0, import_responses.createApiErrorResponse)("ENDPOINT_NOT_IMPLEMENTED", "Users endpoint not implemented", 501)
42
+ );
43
+ }
44
+ }
45
+ class EndpointRouter {
46
+ static handlers = [
47
+ new SessionsHandler(),
48
+ new UsersHandler()
49
+ ];
50
+ static async route(handlerContext, config) {
51
+ const { endpoint } = handlerContext;
52
+ const handler = this.handlers.find((h) => h.canHandle(endpoint));
53
+ if (!handler) {
54
+ return (0, import_responses.createApiErrorResponse)("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
55
+ }
56
+ return handler.handle(handlerContext, config);
57
+ }
58
+ static addHandler(handler) {
59
+ this.handlers.push(handler);
60
+ }
61
+ static removeHandler(predicate) {
62
+ const index = this.handlers.findIndex(predicate);
63
+ if (index > -1) {
64
+ this.handlers.splice(index, 1);
65
+ }
66
+ }
67
+ }
68
+ // Annotate the CommonJS export names for ESM import in node:
69
+ 0 && (module.exports = {
70
+ EndpointRouter
71
+ });
72
+ //# sourceMappingURL=endpointRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type { EndpointHandler} from './api/endpoints/abstract';\nimport type { HandlerContext } from './handlerUtils';\nimport { createApiErrorResponse } from './responses';\nimport { SessionEndpointHandler } from './sessionHandlers';\nimport type { AuthEndpoint, TernSecureInternalHandlerConfig } from './types';\n\nclass SessionsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sessions';\n }\n\n async handle(\n handlerContext: HandlerContext,\n config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n const { request, subEndpoint, method } = handlerContext;\n return await SessionEndpointHandler.handle(request, method, subEndpoint, config);\n }\n}\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(\n _handlerContext: HandlerContext,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}\n\nexport class EndpointRouter {\n private static readonly handlers: EndpointHandler[] = [\n new SessionsHandler(),\n new UsersHandler(),\n ];\n\n static async route(\n handlerContext: HandlerContext,\n config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n const { endpoint } = handlerContext;\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(handlerContext, 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}"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,uBAAuC;AACvC,6BAAuC;AAGvC,MAAM,gBAA2C;AAAA,EAC/C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,gBACA,QACmB;AACnB,UAAM,EAAE,SAAS,aAAa,OAAO,IAAI;AACzC,WAAO,MAAM,8CAAuB,OAAO,SAAS,QAAQ,aAAa,MAAM;AAAA,EACjF;AACF;AAEA,MAAM,aAAwC;AAAA,EAC5C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,OACE,iBACA,SACmB;AACnB,WAAO,QAAQ;AAAA,UACb,yCAAuB,4BAA4B,kCAAkC,GAAG;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,MAAM,eAAe;AAAA,EAC1B,OAAwB,WAA8B;AAAA,IACpD,IAAI,gBAAgB;AAAA,IACpB,IAAI,aAAa;AAAA,EACnB;AAAA,EAEA,aAAa,MACX,gBACA,QACmB;AACnB,UAAM,EAAE,SAAS,IAAI;AAErB,UAAM,UAAU,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAE7D,QAAI,CAAC,SAAS;AACZ,iBAAO,yCAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO,QAAQ,OAAO,gBAAgB,MAAM;AAAA,EAC9C;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":[]}
@@ -22,7 +22,7 @@ __export(fnValidators_exports, {
22
22
  createValidators: () => createValidators
23
23
  });
24
24
  module.exports = __toCommonJS(fnValidators_exports);
25
- var import_server = require("next/server");
25
+ var import_headers = require("next/headers");
26
26
  var import_responses = require("./responses");
27
27
  function createRequestContext(request) {
28
28
  const url = new URL(request.url);
@@ -60,7 +60,7 @@ function createValidators(context) {
60
60
  return null;
61
61
  }
62
62
  function createCorsOptionsResponse(corsOptions) {
63
- const response = new import_server.NextResponse(null, { status: 204 });
63
+ const response = new Response(null, { status: 204 });
64
64
  if (corsOptions.allowedOrigins === "*") {
65
65
  response.headers.set("Access-Control-Allow-Origin", "*");
66
66
  } else {
@@ -256,7 +256,8 @@ function createValidators(context) {
256
256
  }
257
257
  }
258
258
  if (config.requireCsrfToken && sessionData.csrfToken) {
259
- const csrfCookieValue = request.cookies.get("csrfToken")?.value;
259
+ const cookieStore = await (0, import_headers.cookies)();
260
+ const csrfCookieValue = cookieStore.get("csrfToken")?.value;
260
261
  const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);
261
262
  if (csrfError) {
262
263
  return { isValid: false, error: csrfError };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/fnValidators.ts"],"sourcesContent":["import { type NextRequest, NextResponse } from 'next/server';\n\nimport { createApiErrorResponse } from './responses';\nimport type {\n AuthEndpoint,\n ComprehensiveValidationResult,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionSubEndpoint,\n ValidationConfig,\n} from './types';\n\nexport interface RequestContext {\n request: NextRequest;\n origin: string | null;\n host: string | null;\n referer: string | null;\n userAgent: string;\n method: string;\n pathSegments: string[];\n}\n\nexport function createRequestContext(request: NextRequest): RequestContext {\n const url = new URL(request.url);\n const pathSegments = url.pathname.split('/').filter(Boolean);\n\n return {\n request,\n origin: request.headers.get('origin'),\n host: request.headers.get('host'),\n referer: request.headers.get('referer'),\n userAgent: request.headers.get('user-agent') || '',\n method: request.method,\n pathSegments,\n };\n}\n\n/**\n * Main validators factory function\n * Returns an object containing all validator functions and utilities\n */\nexport function createValidators(context: RequestContext) {\n const { request, origin, host, referer, userAgent, method, pathSegments } = context;\n\n async function validateCors(corsOptions: CorsOptions): Promise<NextResponse | null> {\n if (corsOptions.skipSameOrigin) {\n if (!origin || (host && origin.includes(host))) {\n return null;\n }\n }\n\n if (corsOptions.allowedOrigins !== '*') {\n const isAllowed = corsOptions.allowedOrigins.some(allowedOrigin => {\n if (allowedOrigin.startsWith('*')) {\n const domain = allowedOrigin.slice(1);\n return origin?.endsWith(domain);\n }\n return origin === allowedOrigin;\n });\n\n if (!isAllowed) {\n return createApiErrorResponse('CORS_ORIGIN_NOT_ALLOWED', 'Origin not allowed', 403);\n }\n }\n\n return null;\n }\n\n function createCorsOptionsResponse(corsOptions: CorsOptions): NextResponse {\n const response = new NextResponse(null, { status: 204 });\n\n if (corsOptions.allowedOrigins === '*') {\n response.headers.set('Access-Control-Allow-Origin', '*');\n } else {\n response.headers.set('Access-Control-Allow-Origin', corsOptions.allowedOrigins.join(','));\n }\n\n response.headers.set(\n 'Access-Control-Allow-Methods',\n corsOptions.allowedMethods?.join(',') || 'GET,POST',\n );\n response.headers.set(\n 'Access-Control-Allow-Headers',\n corsOptions.allowedHeaders?.join(',') || 'Content-Type,Authorization',\n );\n\n if (corsOptions.allowCredentials) {\n response.headers.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (corsOptions.maxAge) {\n response.headers.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n\n return response;\n }\n\n async function validateSecurity(securityOptions: SecurityOptions): Promise<NextResponse | null> {\n const csrfResult = validateCsrf(securityOptions);\n if (csrfResult) return csrfResult;\n\n const headersResult = validateRequiredHeaders(securityOptions);\n if (headersResult) return headersResult;\n\n const userAgentResult = validateUserAgent(securityOptions);\n if (userAgentResult) return userAgentResult;\n\n return null;\n }\n\n function validateCsrf(securityOptions: SecurityOptions): NextResponse | null {\n if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {\n const hasCSRFHeader = request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referer && host && referer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referer?.includes(allowedRef),\n );\n\n if (!isAllowedReferer) {\n return createApiErrorResponse('CSRF_PROTECTION', 'Access denied', 403);\n }\n }\n }\n return null;\n }\n\n function validateRequiredHeaders(securityOptions: SecurityOptions): NextResponse | null {\n if (securityOptions.requiredHeaders) {\n for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {\n const actualValue = request.headers.get(headerName);\n if (actualValue !== expectedValue) {\n return createApiErrorResponse(\n 'INVALID_HEADERS',\n 'Required header missing or invalid',\n 400,\n );\n }\n }\n }\n return null;\n }\n\n function validateUserAgent(securityOptions: SecurityOptions): NextResponse | null {\n if (securityOptions.userAgent?.block?.length) {\n const isBlocked = securityOptions.userAgent.block.some((blocked: string) =>\n userAgent.toLowerCase().includes(blocked.toLowerCase()),\n );\n\n if (isBlocked) {\n return createApiErrorResponse('USER_AGENT_BLOCKED', 'Access denied', 403);\n }\n }\n\n if (securityOptions.userAgent?.allow?.length) {\n const isAllowed = securityOptions.userAgent.allow.some((allowed: string) =>\n userAgent.toLowerCase().includes(allowed.toLowerCase()),\n );\n\n if (!isAllowed) {\n return createApiErrorResponse('USER_AGENT_NOT_ALLOWED', 'Access denied', 403);\n }\n }\n\n return null;\n }\n\n function validateCsrfToken(\n csrfToken: string,\n csrfCookieValue: string | undefined,\n ): NextResponse | null {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_COOKIE_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n }\n\n function validatePathStructure(): NextResponse | null {\n if (pathSegments.length < 3) {\n return createApiErrorResponse(\n 'INVALID_ROUTE',\n 'Invalid route structure. Expected: /api/auth/{endpoint}',\n 404,\n );\n }\n return null;\n }\n\n function validateEndpoint(\n _endpoint: AuthEndpoint,\n endpointConfig: EndpointConfig,\n ): NextResponse | null {\n if (!endpointConfig || !endpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (method !== 'OPTIONS' && !endpointConfig.methods.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n function validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n ): NextResponse | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n async function validateSessionRequest(): Promise<{\n body: any;\n idToken?: string;\n csrfToken?: string;\n error?: NextResponse;\n }> {\n try {\n const body = await request.json();\n return { body, idToken: body.idToken, csrfToken: body.csrfToken };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid request format', 400),\n };\n }\n }\n\n function validateIdToken(idToken: string | undefined): NextResponse | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required for creating session',\n 400,\n );\n }\n return null;\n }\n\n /**\n * Main validation orchestrator function\n * Runs all configured validations in the correct order\n */\n async function validateRequest(config: ValidationConfig): Promise<ComprehensiveValidationResult> {\n if (method === 'OPTIONS' && config.cors) {\n return {\n isValid: true,\n corsResponse: createCorsOptionsResponse(config.cors),\n };\n }\n const pathError = validatePathStructure();\n if (pathError) {\n return { isValid: false, error: pathError };\n }\n\n if (config.cors) {\n const corsError = await validateCors(config.cors);\n if (corsError) {\n return { isValid: false, error: corsError };\n }\n }\n\n if (config.security) {\n const securityError = await validateSecurity(config.security);\n if (securityError) {\n return { isValid: false, error: securityError };\n }\n }\n\n if (config.endpoint) {\n const endpointError = validateEndpoint(config.endpoint.name, config.endpoint.config);\n if (endpointError) {\n return { isValid: false, error: endpointError };\n }\n }\n\n if (config.subEndpoint) {\n const subEndpointError = validateSubEndpoint(\n config.subEndpoint.name,\n config.subEndpoint.config,\n );\n if (subEndpointError) {\n return { isValid: false, error: subEndpointError };\n }\n }\n\n let sessionData;\n if (method === 'POST' && (config.requireIdToken || config.requireCsrfToken)) {\n const sessionResult = await validateSessionRequest();\n if (sessionResult.error) {\n return { isValid: false, error: sessionResult.error };\n }\n\n sessionData = sessionResult;\n\n if (config.requireIdToken) {\n const idTokenError = validateIdToken(sessionData.idToken);\n if (idTokenError) {\n return { isValid: false, error: idTokenError };\n }\n }\n\n if (config.requireCsrfToken && sessionData.csrfToken) {\n const csrfCookieValue = request.cookies.get('csrfToken')?.value;\n const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);\n if (csrfError) {\n return { isValid: false, error: csrfError };\n }\n }\n }\n\n return {\n isValid: true,\n sessionData,\n };\n }\n\n /**\n * Convenience function for quick validation setup\n */\n function createValidationConfig(overrides: Partial<ValidationConfig> = {}): ValidationConfig {\n return {\n ...overrides,\n };\n }\n\n return {\n createValidationConfig,\n\n validateRequest,\n\n validateCors,\n validateSecurity,\n validatePathStructure,\n validateEndpoint,\n validateSubEndpoint,\n validateSessionRequest,\n validateIdToken,\n validateCsrfToken,\n\n createCorsOptionsResponse,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA+C;AAE/C,uBAAuC;AAqBhC,SAAS,qBAAqB,SAAsC;AACzE,QAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,QAAM,eAAe,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AAE3D,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,QAAQ,QAAQ,IAAI,QAAQ;AAAA,IACpC,MAAM,QAAQ,QAAQ,IAAI,MAAM;AAAA,IAChC,SAAS,QAAQ,QAAQ,IAAI,SAAS;AAAA,IACtC,WAAW,QAAQ,QAAQ,IAAI,YAAY,KAAK;AAAA,IAChD,QAAQ,QAAQ;AAAA,IAChB;AAAA,EACF;AACF;AAMO,SAAS,iBAAiB,SAAyB;AACxD,QAAM,EAAE,SAAS,QAAQ,MAAM,SAAS,WAAW,QAAQ,aAAa,IAAI;AAE5E,iBAAe,aAAa,aAAwD;AAClF,QAAI,YAAY,gBAAgB;AAC9B,UAAI,CAAC,UAAW,QAAQ,OAAO,SAAS,IAAI,GAAI;AAC9C,eAAO;AAAA,MACT;AAAA,IACF;AAEA,QAAI,YAAY,mBAAmB,KAAK;AACtC,YAAM,YAAY,YAAY,eAAe,KAAK,mBAAiB;AACjE,YAAI,cAAc,WAAW,GAAG,GAAG;AACjC,gBAAM,SAAS,cAAc,MAAM,CAAC;AACpC,iBAAO,QAAQ,SAAS,MAAM;AAAA,QAChC;AACA,eAAO,WAAW;AAAA,MACpB,CAAC;AAED,UAAI,CAAC,WAAW;AACd,mBAAO,yCAAuB,2BAA2B,sBAAsB,GAAG;AAAA,MACpF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,0BAA0B,aAAwC;AACzE,UAAM,WAAW,IAAI,2BAAa,MAAM,EAAE,QAAQ,IAAI,CAAC;AAEvD,QAAI,YAAY,mBAAmB,KAAK;AACtC,eAAS,QAAQ,IAAI,+BAA+B,GAAG;AAAA,IACzD,OAAO;AACL,eAAS,QAAQ,IAAI,+BAA+B,YAAY,eAAe,KAAK,GAAG,CAAC;AAAA,IAC1F;AAEA,aAAS,QAAQ;AAAA,MACf;AAAA,MACA,YAAY,gBAAgB,KAAK,GAAG,KAAK;AAAA,IAC3C;AACA,aAAS,QAAQ;AAAA,MACf;AAAA,MACA,YAAY,gBAAgB,KAAK,GAAG,KAAK;AAAA,IAC3C;AAEA,QAAI,YAAY,kBAAkB;AAChC,eAAS,QAAQ,IAAI,oCAAoC,MAAM;AAAA,IACjE;AAEA,QAAI,YAAY,QAAQ;AACtB,eAAS,QAAQ,IAAI,0BAA0B,YAAY,OAAO,SAAS,CAAC;AAAA,IAC9E;AAEA,WAAO;AAAA,EACT;AAEA,iBAAe,iBAAiB,iBAAgE;AAC9F,UAAM,aAAa,aAAa,eAAe;AAC/C,QAAI,WAAY,QAAO;AAEvB,UAAM,gBAAgB,wBAAwB,eAAe;AAC7D,QAAI,cAAe,QAAO;AAE1B,UAAM,kBAAkB,kBAAkB,eAAe;AACzD,QAAI,gBAAiB,QAAO;AAE5B,WAAO;AAAA,EACT;AAEA,WAAS,aAAa,iBAAuD;AAC3E,QAAI,gBAAgB,eAAe,UAAU,QAAQ,CAAC,OAAO,SAAS,IAAI,GAAG;AAC3E,YAAM,gBAAgB,QAAQ,QAAQ,IAAI,kBAAkB,MAAM;AAClE,YAAM,kBAAkB,WAAW,QAAQ,QAAQ,SAAS,IAAI;AAEhE,UAAI,CAAC,iBAAiB,CAAC,iBAAiB;AACtC,cAAM,mBAAmB,gBAAgB,iBAAiB;AAAA,UAAK,CAAC,eAC9D,SAAS,SAAS,UAAU;AAAA,QAC9B;AAEA,YAAI,CAAC,kBAAkB;AACrB,qBAAO,yCAAuB,mBAAmB,iBAAiB,GAAG;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,wBAAwB,iBAAuD;AACtF,QAAI,gBAAgB,iBAAiB;AACnC,iBAAW,CAAC,YAAY,aAAa,KAAK,OAAO,QAAQ,gBAAgB,eAAe,GAAG;AACzF,cAAM,cAAc,QAAQ,QAAQ,IAAI,UAAU;AAClD,YAAI,gBAAgB,eAAe;AACjC,qBAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,kBAAkB,iBAAuD;AAChF,QAAI,gBAAgB,WAAW,OAAO,QAAQ;AAC5C,YAAM,YAAY,gBAAgB,UAAU,MAAM;AAAA,QAAK,CAAC,YACtD,UAAU,YAAY,EAAE,SAAS,QAAQ,YAAY,CAAC;AAAA,MACxD;AAEA,UAAI,WAAW;AACb,mBAAO,yCAAuB,sBAAsB,iBAAiB,GAAG;AAAA,MAC1E;AAAA,IACF;AAEA,QAAI,gBAAgB,WAAW,OAAO,QAAQ;AAC5C,YAAM,YAAY,gBAAgB,UAAU,MAAM;AAAA,QAAK,CAAC,YACtD,UAAU,YAAY,EAAE,SAAS,QAAQ,YAAY,CAAC;AAAA,MACxD;AAEA,UAAI,CAAC,WAAW;AACd,mBAAO,yCAAuB,0BAA0B,iBAAiB,GAAG;AAAA,MAC9E;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,kBACP,WACA,iBACqB;AACrB,QAAI,CAAC,WAAW;AACd,iBAAO,yCAAuB,sBAAsB,0BAA0B,GAAG;AAAA,IACnF;AAEA,QAAI,CAAC,iBAAiB;AACpB,iBAAO,yCAAuB,uBAAuB,+BAA+B,GAAG;AAAA,IACzF;AAEA,QAAI,cAAc,iBAAiB;AACjC,iBAAO,yCAAuB,uBAAuB,uBAAuB,GAAG;AAAA,IACjF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,wBAA6C;AACpD,QAAI,aAAa,SAAS,GAAG;AAC3B,iBAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,iBACP,WACA,gBACqB;AACrB,QAAI,CAAC,kBAAkB,CAAC,eAAe,SAAS;AAC9C,iBAAO,yCAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,QAAI,WAAW,aAAa,CAAC,eAAe,QAAQ,SAAS,MAAa,GAAG;AAC3E,iBAAO,yCAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,oBACP,aACA,mBACqB;AACrB,QAAI,CAAC,aAAa;AAChB,iBAAO,yCAAuB,yBAAyB,iCAAiC,GAAG;AAAA,IAC7F;AAEA,QAAI,CAAC,qBAAqB,CAAC,kBAAkB,SAAS;AACpD,iBAAO,yCAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,QAAI,CAAC,kBAAkB,SAAS,SAAS,MAAa,GAAG;AACvD,iBAAO,yCAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO;AAAA,EACT;AAEA,iBAAe,yBAKZ;AACD,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,aAAO,EAAE,MAAM,SAAS,KAAK,SAAS,WAAW,KAAK,UAAU;AAAA,IAClE,SAAS,OAAO;AACd,aAAO;AAAA,QACL,MAAM;AAAA,QACN,WAAO,yCAAuB,0BAA0B,0BAA0B,GAAG;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AAEA,WAAS,gBAAgB,SAAkD;AACzE,QAAI,CAAC,SAAS;AACZ,iBAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAMA,iBAAe,gBAAgB,QAAkE;AAC/F,QAAI,WAAW,aAAa,OAAO,MAAM;AACvC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,cAAc,0BAA0B,OAAO,IAAI;AAAA,MACrD;AAAA,IACF;AACA,UAAM,YAAY,sBAAsB;AACxC,QAAI,WAAW;AACb,aAAO,EAAE,SAAS,OAAO,OAAO,UAAU;AAAA,IAC5C;AAEA,QAAI,OAAO,MAAM;AACf,YAAM,YAAY,MAAM,aAAa,OAAO,IAAI;AAChD,UAAI,WAAW;AACb,eAAO,EAAE,SAAS,OAAO,OAAO,UAAU;AAAA,MAC5C;AAAA,IACF;AAEA,QAAI,OAAO,UAAU;AACnB,YAAM,gBAAgB,MAAM,iBAAiB,OAAO,QAAQ;AAC5D,UAAI,eAAe;AACjB,eAAO,EAAE,SAAS,OAAO,OAAO,cAAc;AAAA,MAChD;AAAA,IACF;AAEA,QAAI,OAAO,UAAU;AACnB,YAAM,gBAAgB,iBAAiB,OAAO,SAAS,MAAM,OAAO,SAAS,MAAM;AACnF,UAAI,eAAe;AACjB,eAAO,EAAE,SAAS,OAAO,OAAO,cAAc;AAAA,MAChD;AAAA,IACF;AAEA,QAAI,OAAO,aAAa;AACtB,YAAM,mBAAmB;AAAA,QACvB,OAAO,YAAY;AAAA,QACnB,OAAO,YAAY;AAAA,MACrB;AACA,UAAI,kBAAkB;AACpB,eAAO,EAAE,SAAS,OAAO,OAAO,iBAAiB;AAAA,MACnD;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,WAAW,WAAW,OAAO,kBAAkB,OAAO,mBAAmB;AAC3E,YAAM,gBAAgB,MAAM,uBAAuB;AACnD,UAAI,cAAc,OAAO;AACvB,eAAO,EAAE,SAAS,OAAO,OAAO,cAAc,MAAM;AAAA,MACtD;AAEA,oBAAc;AAEd,UAAI,OAAO,gBAAgB;AACzB,cAAM,eAAe,gBAAgB,YAAY,OAAO;AACxD,YAAI,cAAc;AAChB,iBAAO,EAAE,SAAS,OAAO,OAAO,aAAa;AAAA,QAC/C;AAAA,MACF;AAEA,UAAI,OAAO,oBAAoB,YAAY,WAAW;AACpD,cAAM,kBAAkB,QAAQ,QAAQ,IAAI,WAAW,GAAG;AAC1D,cAAM,YAAY,kBAAkB,YAAY,WAAW,eAAe;AAC1E,YAAI,WAAW;AACb,iBAAO,EAAE,SAAS,OAAO,OAAO,UAAU;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAKA,WAAS,uBAAuB,YAAuC,CAAC,GAAqB;AAC3F,WAAO;AAAA,MACL,GAAG;AAAA,IACL;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IAEA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IAEA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/fnValidators.ts"],"sourcesContent":["import { cookies } from 'next/headers';\n\nimport { createApiErrorResponse } from './responses';\nimport type {\n AuthEndpoint,\n ComprehensiveValidationResult,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionSubEndpoint,\n ValidationConfig,\n} from './types';\n//import type { RequestProcessorContext } from './claude-authenticateRequestProcessor';\n\nexport interface RequestContext {\n request: Request;\n origin: string | null;\n host: string | null;\n referer: string | null;\n userAgent: string;\n method: string;\n pathSegments: string[];\n}\n\nexport function createRequestContext(request: Request): RequestContext {\n const url = new URL(request.url);\n const pathSegments = url.pathname.split('/').filter(Boolean);\n\n return {\n request,\n origin: request.headers.get('origin'),\n host: request.headers.get('host'),\n referer: request.headers.get('referer'),\n userAgent: request.headers.get('user-agent') || '',\n method: request.method,\n pathSegments,\n };\n}\n\n/**\n * Main validators factory function\n * Returns an object containing all validator functions and utilities\n */\nexport function createValidators(context: RequestContext) {\n const { request, origin, host, referer, userAgent, method, pathSegments } = context;\n\n async function validateCors(corsOptions: CorsOptions): Promise<Response | null> {\n if (corsOptions.skipSameOrigin) {\n if (!origin || (host && origin.includes(host))) {\n return null;\n }\n }\n\n if (corsOptions.allowedOrigins !== '*') {\n const isAllowed = corsOptions.allowedOrigins.some(allowedOrigin => {\n if (allowedOrigin.startsWith('*')) {\n const domain = allowedOrigin.slice(1);\n return origin?.endsWith(domain);\n }\n return origin === allowedOrigin;\n });\n\n if (!isAllowed) {\n return createApiErrorResponse('CORS_ORIGIN_NOT_ALLOWED', 'Origin not allowed', 403);\n }\n }\n\n return null;\n }\n\n function createCorsOptionsResponse(corsOptions: CorsOptions): Response {\n const response = new Response(null, { status: 204 });\n\n if (corsOptions.allowedOrigins === '*') {\n response.headers.set('Access-Control-Allow-Origin', '*');\n } else {\n response.headers.set('Access-Control-Allow-Origin', corsOptions.allowedOrigins.join(','));\n }\n\n response.headers.set(\n 'Access-Control-Allow-Methods',\n corsOptions.allowedMethods?.join(',') || 'GET,POST',\n );\n response.headers.set(\n 'Access-Control-Allow-Headers',\n corsOptions.allowedHeaders?.join(',') || 'Content-Type,Authorization',\n );\n\n if (corsOptions.allowCredentials) {\n response.headers.set('Access-Control-Allow-Credentials', 'true');\n }\n\n if (corsOptions.maxAge) {\n response.headers.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n\n return response;\n }\n\n async function validateSecurity(securityOptions: SecurityOptions): Promise<Response | null> {\n const csrfResult = validateCsrf(securityOptions);\n if (csrfResult) return csrfResult;\n\n const headersResult = validateRequiredHeaders(securityOptions);\n if (headersResult) return headersResult;\n\n const userAgentResult = validateUserAgent(securityOptions);\n if (userAgentResult) return userAgentResult;\n\n return null;\n }\n\n function validateCsrf(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {\n const hasCSRFHeader = request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referer && host && referer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referer?.includes(allowedRef),\n );\n\n if (!isAllowedReferer) {\n return createApiErrorResponse('CSRF_PROTECTION', 'Access denied', 403);\n }\n }\n }\n return null;\n }\n\n function validateRequiredHeaders(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.requiredHeaders) {\n for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {\n const actualValue = request.headers.get(headerName);\n if (actualValue !== expectedValue) {\n return createApiErrorResponse(\n 'INVALID_HEADERS',\n 'Required header missing or invalid',\n 400,\n );\n }\n }\n }\n return null;\n }\n\n function validateUserAgent(securityOptions: SecurityOptions): Response | null {\n if (securityOptions.userAgent?.block?.length) {\n const isBlocked = securityOptions.userAgent.block.some((blocked: string) =>\n userAgent.toLowerCase().includes(blocked.toLowerCase()),\n );\n\n if (isBlocked) {\n return createApiErrorResponse('USER_AGENT_BLOCKED', 'Access denied', 403);\n }\n }\n\n if (securityOptions.userAgent?.allow?.length) {\n const isAllowed = securityOptions.userAgent.allow.some((allowed: string) =>\n userAgent.toLowerCase().includes(allowed.toLowerCase()),\n );\n\n if (!isAllowed) {\n return createApiErrorResponse('USER_AGENT_NOT_ALLOWED', 'Access denied', 403);\n }\n }\n\n return null;\n }\n\n function validateCsrfToken(\n csrfToken: string,\n csrfCookieValue: string | undefined,\n ): Response | null {\n if (!csrfToken) {\n return createApiErrorResponse('INVALID_CSRF_TOKEN', 'CSRF token is required', 400);\n }\n\n if (!csrfCookieValue) {\n return createApiErrorResponse('CSRF_COOKIE_MISSING', 'CSRF token cookie not found', 403);\n }\n\n if (csrfToken !== csrfCookieValue) {\n return createApiErrorResponse('CSRF_TOKEN_MISMATCH', 'CSRF token mismatch', 403);\n }\n\n return null;\n }\n\n function validatePathStructure(): Response | null {\n if (pathSegments.length < 3) {\n return createApiErrorResponse(\n 'INVALID_ROUTE',\n 'Invalid route structure. Expected: /api/auth/{endpoint}',\n 404,\n );\n }\n return null;\n }\n\n function validateEndpoint(\n _endpoint: AuthEndpoint,\n endpointConfig: EndpointConfig,\n ): Response | null {\n if (!endpointConfig || !endpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (method !== 'OPTIONS' && !endpointConfig.methods.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n function validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n ): Response | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n\n async function validateSessionRequest(): Promise<{\n body: any;\n idToken?: string;\n csrfToken?: string;\n error?: Response;\n }> {\n try {\n const body = await request.json();\n return { body, idToken: body.idToken, csrfToken: body.csrfToken };\n } catch (error) {\n return {\n body: null,\n error: createApiErrorResponse('INVALID_REQUEST_FORMAT', 'Invalid request format', 400),\n };\n }\n }\n\n function validateIdToken(idToken: string | undefined): Response | null {\n if (!idToken) {\n return createApiErrorResponse(\n 'INVALID_TOKEN',\n 'ID token is required for creating session',\n 400,\n );\n }\n return null;\n }\n\n /**\n * Main validation orchestrator function\n * Runs all configured validations in the correct order\n */\n async function validateRequest(config: ValidationConfig): Promise<ComprehensiveValidationResult> {\n if (method === 'OPTIONS' && config.cors) {\n return {\n isValid: true,\n corsResponse: createCorsOptionsResponse(config.cors),\n };\n }\n const pathError = validatePathStructure();\n if (pathError) {\n return { isValid: false, error: pathError };\n }\n\n if (config.cors) {\n const corsError = await validateCors(config.cors);\n if (corsError) {\n return { isValid: false, error: corsError };\n }\n }\n\n if (config.security) {\n const securityError = await validateSecurity(config.security);\n if (securityError) {\n return { isValid: false, error: securityError };\n }\n }\n\n if (config.endpoint) {\n const endpointError = validateEndpoint(config.endpoint.name, config.endpoint.config);\n if (endpointError) {\n return { isValid: false, error: endpointError };\n }\n }\n\n if (config.subEndpoint) {\n const subEndpointError = validateSubEndpoint(\n config.subEndpoint.name,\n config.subEndpoint.config,\n );\n if (subEndpointError) {\n return { isValid: false, error: subEndpointError };\n }\n }\n\n let sessionData;\n if (method === 'POST' && (config.requireIdToken || config.requireCsrfToken)) {\n const sessionResult = await validateSessionRequest();\n if (sessionResult.error) {\n return { isValid: false, error: sessionResult.error };\n }\n\n sessionData = sessionResult;\n\n if (config.requireIdToken) {\n const idTokenError = validateIdToken(sessionData.idToken);\n if (idTokenError) {\n return { isValid: false, error: idTokenError };\n }\n }\n\n if (config.requireCsrfToken && sessionData.csrfToken) {\n const cookieStore = await cookies();\n const csrfCookieValue = cookieStore.get('csrfToken')?.value;\n const csrfError = validateCsrfToken(sessionData.csrfToken, csrfCookieValue);\n if (csrfError) {\n return { isValid: false, error: csrfError };\n }\n }\n }\n\n return {\n isValid: true,\n sessionData,\n };\n }\n\n /**\n * Convenience function for quick validation setup\n */\n function createValidationConfig(overrides: Partial<ValidationConfig> = {}): ValidationConfig {\n return {\n ...overrides,\n };\n }\n\n return {\n createValidationConfig,\n\n validateRequest,\n\n validateCors,\n validateSecurity,\n validatePathStructure,\n validateEndpoint,\n validateSubEndpoint,\n validateSessionRequest,\n validateIdToken,\n validateCsrfToken,\n\n createCorsOptionsResponse,\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,63 @@
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 handlerUtils_exports = {};
20
+ __export(handlerUtils_exports, {
21
+ RequestContextBuilder: () => RequestContextBuilder,
22
+ ValidationPipeline: () => ValidationPipeline
23
+ });
24
+ module.exports = __toCommonJS(handlerUtils_exports);
25
+ var import_fnValidators = require("./fnValidators");
26
+ class RequestContextBuilder {
27
+ static create(request) {
28
+ const context = (0, import_fnValidators.createRequestContext)(request);
29
+ const { pathSegments } = context;
30
+ return {
31
+ request,
32
+ pathSegments,
33
+ endpoint: pathSegments[2],
34
+ subEndpoint: pathSegments[3],
35
+ method: request.method
36
+ };
37
+ }
38
+ }
39
+ class ValidationPipeline {
40
+ config;
41
+ context;
42
+ constructor(config, context) {
43
+ this.config = config;
44
+ this.context = context;
45
+ }
46
+ async execute() {
47
+ const validators = (0, import_fnValidators.createValidators)(this.context);
48
+ const corsError = await validators.validateCors(this.config.cors);
49
+ if (corsError) return corsError;
50
+ if (this.context.method === "OPTIONS") {
51
+ return validators.createCorsOptionsResponse(this.config.cors);
52
+ }
53
+ const securityError = await validators.validateSecurity(this.config.security);
54
+ if (securityError) return securityError;
55
+ return null;
56
+ }
57
+ }
58
+ // Annotate the CommonJS export names for ESM import in node:
59
+ 0 && (module.exports = {
60
+ RequestContextBuilder,
61
+ ValidationPipeline
62
+ });
63
+ //# sourceMappingURL=handlerUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/handlerUtils.ts"],"sourcesContent":["import type { RequestContext } from './fnValidators';\nimport { createRequestContext, createValidators } from './fnValidators';\nimport type {\n AuthEndpoint,\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n} from './types';\n\nexport interface HandlerContext {\n request: Request;\n pathSegments: string[];\n endpoint: AuthEndpoint;\n subEndpoint: SessionSubEndpoint | undefined;\n method: string;\n}\n\nexport class RequestContextBuilder {\n static create(request: Request): HandlerContext {\n const context = createRequestContext(request);\n const { pathSegments } = context;\n\n return {\n request,\n pathSegments,\n endpoint: pathSegments[2] as AuthEndpoint,\n subEndpoint: pathSegments[3] as SessionSubEndpoint | undefined,\n method: request.method,\n };\n }\n}\n\nexport class ValidationPipeline {\n private readonly config: Required<TernSecureHandlerOptions>;\n private readonly context: RequestContext;\n\n constructor(\n config: Required<TernSecureHandlerOptions>,\n context: RequestContext,\n ) {\n this.config = config;\n this.context = context;\n }\n\n async execute(): Promise<Response | null> {\n const validators = createValidators(this.context);\n\n const corsError = await validators.validateCors(this.config.cors);\n if (corsError) return corsError;\n\n if (this.context.method === 'OPTIONS') {\n return validators.createCorsOptionsResponse(this.config.cors);\n }\n\n const securityError = await validators.validateSecurity(this.config.security);\n if (securityError) return securityError;\n\n return null;\n }\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAuD;AAehD,MAAM,sBAAsB;AAAA,EACjC,OAAO,OAAO,SAAkC;AAC9C,UAAM,cAAU,0CAAqB,OAAO;AAC5C,UAAM,EAAE,aAAa,IAAI;AAEzB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,aAAa,CAAC;AAAA,MACxB,aAAa,aAAa,CAAC;AAAA,MAC3B,QAAQ,QAAQ;AAAA,IAClB;AAAA,EACF;AACF;AAEO,MAAM,mBAAmB;AAAA,EACb;AAAA,EACA;AAAA,EAEjB,YACE,QACA,SACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAM,UAAoC;AACxC,UAAM,iBAAa,sCAAiB,KAAK,OAAO;AAEhD,UAAM,YAAY,MAAM,WAAW,aAAa,KAAK,OAAO,IAAI;AAChE,QAAI,UAAW,QAAO;AAEtB,QAAI,KAAK,QAAQ,WAAW,WAAW;AACrC,aAAO,WAAW,0BAA0B,KAAK,OAAO,IAAI;AAAA,IAC9D;AAEA,UAAM,gBAAgB,MAAM,WAAW,iBAAiB,KAAK,OAAO,QAAQ;AAC5E,QAAI,cAAe,QAAO;AAE1B,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -18,6 +18,9 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var admin_exports = {};
20
20
  __export(admin_exports, {
21
+ EndpointRouter: () => import_endpointRouter.EndpointRouter,
22
+ RequestContextBuilder: () => import_handlerUtils.RequestContextBuilder,
23
+ ValidationPipeline: () => import_handlerUtils.ValidationPipeline,
21
24
  clearNextSessionCookie: () => import_actions.clearNextSessionCookie,
22
25
  clearSessionCookieServer: () => import_actions.clearSessionCookieServer,
23
26
  createNextSessionCookie: () => import_actions.createNextSessionCookie,
@@ -29,8 +32,13 @@ __export(admin_exports, {
29
32
  module.exports = __toCommonJS(admin_exports);
30
33
  var import_ternsecureNextjsHandler = require("./ternsecureNextjsHandler");
31
34
  var import_actions = require("./actions");
35
+ var import_endpointRouter = require("./endpointRouter");
36
+ var import_handlerUtils = require("./handlerUtils");
32
37
  // Annotate the CommonJS export names for ESM import in node:
33
38
  0 && (module.exports = {
39
+ EndpointRouter,
40
+ RequestContextBuilder,
41
+ ValidationPipeline,
34
42
  clearNextSessionCookie,
35
43
  clearSessionCookieServer,
36
44
  createNextSessionCookie,
@@ -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 type { TernSecureHandlerOptions } from './types'"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAA8C;AAE9C,qBAOO;","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'\nexport { RequestContextBuilder, ValidationPipeline } from './handlerUtils'\nexport type { HandlerContext } from './handlerUtils'\n\nexport type { TernSecureHandlerOptions, TernSecureInternalHandlerConfig } from './types'"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qCAA8C;AAE9C,qBAOO;AAEP,4BAA+B;AAC/B,0BAA0D;","names":[]}
@@ -35,26 +35,28 @@ __export(sessionHandlers_exports, {
35
35
  module.exports = __toCommonJS(sessionHandlers_exports);
36
36
  var import_admin = require("@tern-secure/backend/admin");
37
37
  var import_jwt = require("@tern-secure/backend/jwt");
38
+ var import_headers = require("next/headers");
38
39
  var import_NextCookieAdapter = require("../../utils/NextCookieAdapter");
39
40
  var import_responses = require("./responses");
40
41
  var import_validators = require("./validators");
41
42
  class SessionGetHandler {
42
- static async handle(request, subEndpoint, _config) {
43
+ static async handle(subEndpoint, _config) {
43
44
  switch (subEndpoint) {
44
45
  case "verify":
45
- return this.handleVerify(request);
46
+ return this.handleVerify();
46
47
  default:
47
48
  return import_responses.HttpResponseHelper.createNotFoundResponse();
48
49
  }
49
50
  }
50
- static async handleVerify(request) {
51
+ static async handleVerify() {
51
52
  try {
52
- const sessionCookie = request.cookies.get("_session_cookie")?.value;
53
+ const cookieStore = await (0, import_headers.cookies)();
54
+ const sessionCookie = cookieStore.get("_session_cookie")?.value;
53
55
  if (!sessionCookie) {
54
56
  return import_responses.SessionResponseHelper.createUnauthorizedResponse();
55
57
  }
56
- const decodedSession = (0, import_jwt.ternDecodeJwtUnguarded)(sessionCookie);
57
- if (decodedSession.errors) {
58
+ const { data: decodedSession, errors } = (0, import_jwt.ternDecodeJwtUnguarded)(sessionCookie);
59
+ if (errors) {
58
60
  return import_responses.SessionResponseHelper.createUnauthorizedResponse();
59
61
  }
60
62
  return import_responses.SessionResponseHelper.createVerificationResponse(decodedSession);
@@ -68,8 +70,8 @@ class SessionPostHandler {
68
70
  const cookieStore = new import_NextCookieAdapter.NextCookieStore();
69
71
  const { idToken, csrfToken, error } = await import_validators.RequestValidator.validateSessionRequest(request);
70
72
  if (error) return error;
71
- const csrfCookieValue = request.cookies.get("_session_terncf")?.value;
72
- const csrfValidationError = import_validators.CsrfValidator.validate(csrfToken || "", csrfCookieValue);
73
+ const csrfCookieValue = await cookieStore.get("_session_terncf");
74
+ const csrfValidationError = import_validators.CsrfValidator.validate(csrfToken || "", csrfCookieValue.value);
73
75
  if (csrfValidationError) return csrfValidationError;
74
76
  const options = {
75
77
  tenantId: _config.tenantId
@@ -78,7 +80,7 @@ class SessionPostHandler {
78
80
  case "createsession":
79
81
  return this.handleCreateSession(options, idToken, cookieStore);
80
82
  case "refresh":
81
- return this.handleRefreshSession(request, cookieStore);
83
+ return this.handleRefreshSession(cookieStore);
82
84
  case "revoke":
83
85
  return this.handleRevokeSession(cookieStore);
84
86
  default:
@@ -98,13 +100,13 @@ class SessionPostHandler {
98
100
  return (0, import_responses.createApiErrorResponse)("SESSION_CREATION_FAILED", "Session creation failed", 500);
99
101
  }
100
102
  }
101
- static async handleRefreshSession(request, cookieStore) {
102
- const currentSessionCookie = request.cookies.get("__session")?.value;
103
+ static async handleRefreshSession(cookieStore) {
104
+ const currentSessionCookie = await cookieStore.get("__session");
103
105
  if (!currentSessionCookie) {
104
106
  return (0, import_responses.createApiErrorResponse)("NO_SESSION", "No session to refresh", 401);
105
107
  }
106
108
  try {
107
- const decodedSession = (0, import_jwt.ternDecodeJwtUnguarded)(currentSessionCookie);
109
+ const decodedSession = (0, import_jwt.ternDecodeJwtUnguarded)(currentSessionCookie.value || "");
108
110
  if (decodedSession.errors) {
109
111
  return (0, import_responses.createApiErrorResponse)("INVALID_SESSION", "Invalid session for refresh", 401);
110
112
  }
@@ -138,7 +140,7 @@ class SessionEndpointHandler {
138
140
  }
139
141
  switch (method) {
140
142
  case "GET":
141
- return SessionGetHandler.handle(request, subEndpoint, config);
143
+ return SessionGetHandler.handle(subEndpoint, config);
142
144
  case "POST":
143
145
  return SessionPostHandler.handle(request, subEndpoint, config);
144
146
  default:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import type { RequestOptions } from '@tern-secure/backend';\nimport { clearSessionCookie, createSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport type { NextRequest, NextResponse } from 'next/server';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type {\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TernSecureInternalHandlerConfig,\n} from './types';\nimport { CsrfValidator, RequestValidator } from './validators';\n\n/**\n * Session GET request handlers\n */\nexport class SessionGetHandler {\n static async handle(\n request: NextRequest,\n subEndpoint: SessionSubEndpoint,\n _config: Required<TernSecureHandlerOptions>,\n ): Promise<NextResponse> {\n switch (subEndpoint) {\n case 'verify':\n return this.handleVerify(request);\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n }\n\n private static async handleVerify(request: NextRequest): Promise<NextResponse> {\n try {\n const sessionCookie = request.cookies.get('_session_cookie')?.value;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const decodedSession = ternDecodeJwtUnguarded(sessionCookie);\n if (decodedSession.errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n }\n}\n\n/**\n * Session POST request handlers\n */\nexport class SessionPostHandler {\n static async handle(\n request: NextRequest,\n subEndpoint: SessionSubEndpoint,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<NextResponse> {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await RequestValidator.validateSessionRequest(request);\n if (error) return error;\n\n const csrfCookieValue = request.cookies.get('_session_terncf')?.value;\n const csrfValidationError = CsrfValidator.validate(csrfToken || '', csrfCookieValue);\n if (csrfValidationError) return csrfValidationError;\n\n const options = {\n tenantId: _config.tenantId,\n };\n\n switch (subEndpoint) {\n case 'createsession':\n return this.handleCreateSession(options, idToken, cookieStore);\n case 'refresh':\n return this.handleRefreshSession(request, cookieStore);\n case 'revoke':\n return this.handleRevokeSession(cookieStore);\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n }\n\n private static async handleCreateSession(\n options: RequestOptions,\n idToken: string | undefined,\n cookieStore: NextCookieStore,\n ): Promise<NextResponse> {\n const validationError = RequestValidator.validateIdToken(idToken);\n if (validationError) return validationError;\n if (!idToken) {\n return createApiErrorResponse('ID_TOKEN_REQUIRED', 'ID token is required', 400);\n }\n\n try {\n const res = await createSessionCookie(idToken, cookieStore, options);\n return SessionResponseHelper.createSessionCreationResponse(res);\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n }\n\n private static async handleRefreshSession(\n request: NextRequest,\n cookieStore: NextCookieStore,\n ): Promise<NextResponse> {\n const currentSessionCookie = request.cookies.get('__session')?.value;\n if (!currentSessionCookie) {\n return createApiErrorResponse('NO_SESSION', 'No session to refresh', 401);\n }\n\n try {\n const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie);\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await createSessionCookie(\n decodedSession.data?.payload?.sub || '',\n cookieStore,\n );\n\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n }\n\n private static async handleRevokeSession(cookieStore: NextCookieStore): Promise<NextResponse> {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n }\n}\n\n/**\n * Main session endpoint orchestrator\n */\nexport class SessionEndpointHandler {\n static async handle(\n request: NextRequest,\n method: string,\n subEndpoint: SessionSubEndpoint | undefined,\n config: Required<TernSecureHandlerOptions>,\n ): Promise<NextResponse> {\n const sessionsConfig = config.endpoints.sessions;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);\n if (subEndpointValidation) return subEndpointValidation;\n\n if (subEndpointConfig?.security) {\n const { SecurityValidator } = await import('./validators.js');\n const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);\n if (securityResult) return securityResult;\n }\n\n switch (method) {\n case 'GET':\n return SessionGetHandler.handle(request, subEndpoint, config);\n case 'POST':\n return SessionPostHandler.handle(request, subEndpoint, config);\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n }\n\n private static validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n method: string,\n ): NextResponse | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import type { RequestOptions } from '@tern-secure/backend';\nimport { clearSessionCookie, createSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded} from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type {\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TernSecureInternalHandlerConfig,\n} from './types';\nimport { CsrfValidator, RequestValidator } from './validators';\n\n/**\n * Session GET request handlers\n */\nexport class SessionGetHandler {\n static async handle(\n subEndpoint: SessionSubEndpoint,\n _config: Required<TernSecureHandlerOptions>,\n ): Promise<Response> {\n switch (subEndpoint) {\n case 'verify':\n return this.handleVerify();\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n }\n\n private static async handleVerify(): Promise<Response> {\n try {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\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\n/**\n * Session POST request handlers\n */\nexport class SessionPostHandler {\n static async handle(\n request: Request,\n subEndpoint: SessionSubEndpoint,\n _config: TernSecureInternalHandlerConfig,\n ): Promise<Response> {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await RequestValidator.validateSessionRequest(request);\n if (error) return error;\n\n const csrfCookieValue = await cookieStore.get('_session_terncf');\n const csrfValidationError = CsrfValidator.validate(csrfToken || '', csrfCookieValue.value);\n if (csrfValidationError) return csrfValidationError;\n\n const options = {\n tenantId: _config.tenantId,\n };\n\n switch (subEndpoint) {\n case 'createsession':\n return this.handleCreateSession(options, idToken, cookieStore);\n case 'refresh':\n return this.handleRefreshSession(cookieStore);\n case 'revoke':\n return this.handleRevokeSession(cookieStore);\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n }\n\n private static async handleCreateSession(\n options: RequestOptions,\n idToken: string | undefined,\n cookieStore: NextCookieStore,\n ): Promise<Response> {\n const validationError = RequestValidator.validateIdToken(idToken);\n if (validationError) return validationError;\n if (!idToken) {\n return createApiErrorResponse('ID_TOKEN_REQUIRED', 'ID token is required', 400);\n }\n\n try {\n const res = await createSessionCookie(idToken, cookieStore, options);\n return SessionResponseHelper.createSessionCreationResponse(res);\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n }\n\n private static async handleRefreshSession(\n cookieStore: NextCookieStore,\n ): Promise<Response> {\n const currentSessionCookie = await cookieStore.get('__session');\n if (!currentSessionCookie) {\n return createApiErrorResponse('NO_SESSION', 'No session to refresh', 401);\n }\n\n try {\n const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie.value || '');\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await createSessionCookie(\n decodedSession.data?.payload?.sub || '',\n cookieStore,\n );\n\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n }\n\n private static async handleRevokeSession(cookieStore: NextCookieStore): Promise<Response> {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n }\n}\n\n/**\n * Main session endpoint orchestrator\n */\nexport class SessionEndpointHandler {\n static async handle(\n request: Request,\n method: string,\n subEndpoint: SessionSubEndpoint | undefined,\n config: Required<TernSecureHandlerOptions>,\n ): Promise<Response> {\n const sessionsConfig = config.endpoints.sessions;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);\n if (subEndpointValidation) return subEndpointValidation;\n\n if (subEndpointConfig?.security) {\n const { SecurityValidator } = await import('./validators.js');\n const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);\n if (securityResult) return securityResult;\n }\n\n switch (method) {\n case 'GET':\n return SessionGetHandler.handle(subEndpoint, config);\n case 'POST':\n return SessionPostHandler.handle(request, subEndpoint, config);\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n }\n\n private static validateSubEndpoint(\n subEndpoint: SessionSubEndpoint | undefined,\n subEndpointConfig: any,\n method: string,\n ): Response | null {\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n if (!subEndpointConfig || !subEndpointConfig.enabled) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n if (!subEndpointConfig.methods?.includes(method as any)) {\n return createApiErrorResponse('METHOD_NOT_ALLOWED', 'Method not allowed', 405);\n }\n\n return null;\n }\n}\n"],"mappings":"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","names":[]}