@tern-secure/nextjs 5.2.0-canary.v20250919134427 → 5.2.0-canary.v20251002175916
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/app-router/admin/api/endpoints/abstract.js.map +1 -1
- package/dist/cjs/app-router/admin/{claude-authenticateRequestProcessor.js → c-authenticateRequestProcessor.js} +21 -7
- package/dist/cjs/app-router/admin/c-authenticateRequestProcessor.js.map +1 -0
- package/dist/cjs/app-router/admin/constants.js +18 -0
- package/dist/cjs/app-router/admin/constants.js.map +1 -1
- package/dist/cjs/app-router/admin/endpointRouter.js +10 -11
- package/dist/cjs/app-router/admin/endpointRouter.js.map +1 -1
- package/dist/cjs/app-router/admin/fnValidators.js +10 -24
- package/dist/cjs/app-router/admin/fnValidators.js.map +1 -1
- package/dist/cjs/app-router/admin/index.js +0 -5
- package/dist/cjs/app-router/admin/index.js.map +1 -1
- package/dist/cjs/app-router/admin/request.js +73 -0
- package/dist/cjs/app-router/admin/request.js.map +1 -0
- package/dist/cjs/app-router/admin/sessionHandlers.js +84 -123
- package/dist/cjs/app-router/admin/sessionHandlers.js.map +1 -1
- package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js +21 -34
- package/dist/cjs/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
- package/dist/cjs/app-router/admin/types.js +83 -6
- package/dist/cjs/app-router/admin/types.js.map +1 -1
- package/dist/cjs/server/constant.js +4 -1
- package/dist/cjs/server/constant.js.map +1 -1
- package/dist/cjs/server/ternSecureEdgeMiddleware.js +3 -23
- package/dist/cjs/server/ternSecureEdgeMiddleware.js.map +1 -1
- package/dist/cjs/server/ternsecureClient.js +44 -0
- package/dist/cjs/server/ternsecureClient.js.map +1 -0
- package/dist/esm/app-router/admin/api/endpoints/abstract.js.map +1 -1
- package/dist/esm/app-router/admin/{claude-authenticateRequestProcessor.js → c-authenticateRequestProcessor.js} +18 -4
- package/dist/esm/app-router/admin/c-authenticateRequestProcessor.js.map +1 -0
- package/dist/esm/app-router/admin/constants.js +12 -0
- package/dist/esm/app-router/admin/constants.js.map +1 -1
- package/dist/esm/app-router/admin/endpointRouter.js +11 -12
- package/dist/esm/app-router/admin/endpointRouter.js.map +1 -1
- package/dist/esm/app-router/admin/fnValidators.js +10 -23
- package/dist/esm/app-router/admin/fnValidators.js.map +1 -1
- package/dist/esm/app-router/admin/index.js +0 -3
- package/dist/esm/app-router/admin/index.js.map +1 -1
- package/dist/esm/app-router/admin/request.js +56 -0
- package/dist/esm/app-router/admin/request.js.map +1 -0
- package/dist/esm/app-router/admin/sessionHandlers.js +84 -111
- package/dist/esm/app-router/admin/sessionHandlers.js.map +1 -1
- package/dist/esm/app-router/admin/ternsecureNextjsHandler.js +22 -35
- package/dist/esm/app-router/admin/ternsecureNextjsHandler.js.map +1 -1
- package/dist/esm/app-router/admin/types.js +80 -5
- package/dist/esm/app-router/admin/types.js.map +1 -1
- package/dist/esm/server/constant.js +3 -1
- package/dist/esm/server/constant.js.map +1 -1
- package/dist/esm/server/ternSecureEdgeMiddleware.js +3 -24
- package/dist/esm/server/ternSecureEdgeMiddleware.js.map +1 -1
- package/dist/esm/server/ternsecureClient.js +22 -0
- package/dist/esm/server/ternsecureClient.js.map +1 -0
- package/dist/types/app-router/admin/api/endpoints/abstract.d.ts +6 -4
- package/dist/types/app-router/admin/api/endpoints/abstract.d.ts.map +1 -1
- package/dist/types/app-router/admin/{claude-authenticateRequestProcessor.d.ts → c-authenticateRequestProcessor.d.ts} +13 -5
- package/dist/types/app-router/admin/c-authenticateRequestProcessor.d.ts.map +1 -0
- package/dist/types/app-router/admin/constants.d.ts +6 -0
- package/dist/types/app-router/admin/constants.d.ts.map +1 -1
- package/dist/types/app-router/admin/endpointRouter.d.ts +7 -4
- package/dist/types/app-router/admin/endpointRouter.d.ts.map +1 -1
- package/dist/types/app-router/admin/fnValidators.d.ts +2 -11
- package/dist/types/app-router/admin/fnValidators.d.ts.map +1 -1
- package/dist/types/app-router/admin/index.d.ts +1 -3
- package/dist/types/app-router/admin/index.d.ts.map +1 -1
- package/dist/types/app-router/admin/request.d.ts +4 -0
- package/dist/types/app-router/admin/request.d.ts.map +1 -0
- package/dist/types/app-router/admin/sessionHandlers.d.ts +3 -24
- package/dist/types/app-router/admin/sessionHandlers.d.ts.map +1 -1
- package/dist/types/app-router/admin/ternsecureNextjsHandler.d.ts.map +1 -1
- package/dist/types/app-router/admin/types.d.ts +40 -64
- package/dist/types/app-router/admin/types.d.ts.map +1 -1
- package/dist/types/server/constant.d.ts +2 -1
- package/dist/types/server/constant.d.ts.map +1 -1
- package/dist/types/server/ternSecureEdgeMiddleware.d.ts.map +1 -1
- package/dist/types/server/ternsecureClient.d.ts +3 -0
- package/dist/types/server/ternsecureClient.d.ts.map +1 -0
- package/package.json +5 -5
- package/dist/cjs/app-router/admin/claude-authenticateRequestProcessor.js.map +0 -1
- package/dist/cjs/app-router/admin/handlerUtils.js +0 -63
- package/dist/cjs/app-router/admin/handlerUtils.js.map +0 -1
- package/dist/cjs/server/ternSecureFireMiddleware.js +0 -192
- package/dist/cjs/server/ternSecureFireMiddleware.js.map +0 -1
- package/dist/esm/app-router/admin/claude-authenticateRequestProcessor.js.map +0 -1
- package/dist/esm/app-router/admin/handlerUtils.js +0 -38
- package/dist/esm/app-router/admin/handlerUtils.js.map +0 -1
- package/dist/esm/server/ternSecureFireMiddleware.js +0 -179
- package/dist/esm/server/ternSecureFireMiddleware.js.map +0 -1
- package/dist/types/app-router/admin/claude-authenticateRequestProcessor.d.ts.map +0 -1
- package/dist/types/app-router/admin/handlerUtils.d.ts +0 -19
- package/dist/types/app-router/admin/handlerUtils.d.ts.map +0 -1
- package/dist/types/server/ternSecureFireMiddleware.d.ts +0 -47
- package/dist/types/server/ternSecureFireMiddleware.d.ts.map +0 -1
|
@@ -1,133 +1,106 @@
|
|
|
1
|
-
import { clearSessionCookie
|
|
1
|
+
import { clearSessionCookie } from "@tern-secure/backend/admin";
|
|
2
2
|
import { ternDecodeJwtUnguarded } from "@tern-secure/backend/jwt";
|
|
3
3
|
import { cookies } from "next/headers";
|
|
4
4
|
import { NextCookieStore } from "../../utils/NextCookieAdapter";
|
|
5
|
+
import { createValidators } from "./fnValidators";
|
|
6
|
+
import { refreshCookieWithIdToken } from "./request";
|
|
5
7
|
import { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from "./responses";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
async function sessionEndpointHandler(context, options) {
|
|
9
|
+
const { subEndpoint, method } = context;
|
|
10
|
+
const validators = createValidators(context);
|
|
11
|
+
const {
|
|
12
|
+
validateSubEndpoint,
|
|
13
|
+
validateSecurity,
|
|
14
|
+
validateSessionRequest,
|
|
15
|
+
validateCsrfToken,
|
|
16
|
+
validateIdToken
|
|
17
|
+
} = validators;
|
|
18
|
+
if (!subEndpoint) {
|
|
19
|
+
return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
|
|
15
20
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const sessionsConfig = options.endpoints?.sessions;
|
|
22
|
+
const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
|
|
23
|
+
validateSubEndpoint(subEndpoint, subEndpointConfig);
|
|
24
|
+
if (subEndpointConfig?.security) {
|
|
25
|
+
await validateSecurity(subEndpointConfig.security);
|
|
26
|
+
}
|
|
27
|
+
const SessionGetHandler = async (subEndpoint2) => {
|
|
28
|
+
const handleSessionVerify = async () => {
|
|
29
|
+
try {
|
|
30
|
+
const cookieStore = await cookies();
|
|
31
|
+
const sessionCookie = cookieStore.get("_session_cookie")?.value;
|
|
32
|
+
if (!sessionCookie) {
|
|
33
|
+
return SessionResponseHelper.createUnauthorizedResponse();
|
|
34
|
+
}
|
|
35
|
+
const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);
|
|
36
|
+
if (errors) {
|
|
37
|
+
return SessionResponseHelper.createUnauthorizedResponse();
|
|
38
|
+
}
|
|
39
|
+
return SessionResponseHelper.createVerificationResponse(decodedSession);
|
|
40
|
+
} catch (error) {
|
|
25
41
|
return SessionResponseHelper.createUnauthorizedResponse();
|
|
26
42
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
};
|
|
44
|
+
switch (subEndpoint2) {
|
|
45
|
+
case "verify":
|
|
46
|
+
return handleSessionVerify();
|
|
47
|
+
default:
|
|
48
|
+
return HttpResponseHelper.createNotFoundResponse();
|
|
30
49
|
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
class SessionPostHandler {
|
|
34
|
-
static async handle(request, subEndpoint, _config) {
|
|
50
|
+
};
|
|
51
|
+
const SessionPostHandler = async (subEndpoint2) => {
|
|
35
52
|
const cookieStore = new NextCookieStore();
|
|
36
|
-
const { idToken, csrfToken, error } = await
|
|
53
|
+
const { idToken, csrfToken, error } = await validateSessionRequest();
|
|
37
54
|
if (error) return error;
|
|
38
55
|
const csrfCookieValue = await cookieStore.get("_session_terncf");
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
validateCsrfToken(csrfToken || "", csrfCookieValue.value);
|
|
57
|
+
const handleCreateSession = async (cookieStore2, idToken2) => {
|
|
58
|
+
try {
|
|
59
|
+
const res = await refreshCookieWithIdToken(idToken2, cookieStore2, options);
|
|
60
|
+
return SessionResponseHelper.createSessionCreationResponse(res);
|
|
61
|
+
} catch (error2) {
|
|
62
|
+
return createApiErrorResponse("SESSION_CREATION_FAILED", "Session creation failed", 500);
|
|
63
|
+
}
|
|
43
64
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
65
|
+
const handleRefreshSession = async (cookieStore2, idToken2) => {
|
|
66
|
+
try {
|
|
67
|
+
const decodedSession = ternDecodeJwtUnguarded(idToken2);
|
|
68
|
+
if (decodedSession.errors) {
|
|
69
|
+
return createApiErrorResponse("INVALID_SESSION", "Invalid session for refresh", 401);
|
|
70
|
+
}
|
|
71
|
+
const refreshRes = await refreshCookieWithIdToken(idToken2, cookieStore2, options);
|
|
72
|
+
return SessionResponseHelper.createRefreshResponse(refreshRes);
|
|
73
|
+
} catch (error2) {
|
|
74
|
+
return createApiErrorResponse("REFRESH_FAILED", "Session refresh failed", 500);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const handleRevokeSession = async (cookieStore2) => {
|
|
78
|
+
const res = await clearSessionCookie(cookieStore2);
|
|
79
|
+
return SessionResponseHelper.createRevokeResponse(res);
|
|
80
|
+
};
|
|
81
|
+
switch (subEndpoint2) {
|
|
82
|
+
case "createsession": {
|
|
83
|
+
validateIdToken(idToken);
|
|
84
|
+
return handleCreateSession(cookieStore, idToken);
|
|
85
|
+
}
|
|
47
86
|
case "refresh":
|
|
48
|
-
return
|
|
87
|
+
return handleRefreshSession(cookieStore, idToken);
|
|
49
88
|
case "revoke":
|
|
50
|
-
return
|
|
89
|
+
return handleRevokeSession(cookieStore);
|
|
51
90
|
default:
|
|
52
91
|
return HttpResponseHelper.createSubEndpointNotSupportedResponse();
|
|
53
92
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const res = await createSessionCookie(idToken, cookieStore, options);
|
|
63
|
-
return SessionResponseHelper.createSessionCreationResponse(res);
|
|
64
|
-
} catch (error) {
|
|
65
|
-
return createApiErrorResponse("SESSION_CREATION_FAILED", "Session creation failed", 500);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
static async handleRefreshSession(cookieStore) {
|
|
69
|
-
const currentSessionCookie = await cookieStore.get("__session");
|
|
70
|
-
if (!currentSessionCookie) {
|
|
71
|
-
return createApiErrorResponse("NO_SESSION", "No session to refresh", 401);
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
const decodedSession = ternDecodeJwtUnguarded(currentSessionCookie.value || "");
|
|
75
|
-
if (decodedSession.errors) {
|
|
76
|
-
return createApiErrorResponse("INVALID_SESSION", "Invalid session for refresh", 401);
|
|
77
|
-
}
|
|
78
|
-
const refreshRes = await createSessionCookie(
|
|
79
|
-
decodedSession.data?.payload?.sub || "",
|
|
80
|
-
cookieStore
|
|
81
|
-
);
|
|
82
|
-
return SessionResponseHelper.createRefreshResponse(refreshRes);
|
|
83
|
-
} catch (error) {
|
|
84
|
-
return createApiErrorResponse("REFRESH_FAILED", "Session refresh failed", 500);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
static async handleRevokeSession(cookieStore) {
|
|
88
|
-
const res = await clearSessionCookie(cookieStore);
|
|
89
|
-
return SessionResponseHelper.createRevokeResponse(res);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
class SessionEndpointHandler {
|
|
93
|
-
static async handle(request, method, subEndpoint, config) {
|
|
94
|
-
const sessionsConfig = config.endpoints.sessions;
|
|
95
|
-
if (!subEndpoint) {
|
|
96
|
-
return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
|
|
97
|
-
}
|
|
98
|
-
const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
|
|
99
|
-
const subEndpointValidation = this.validateSubEndpoint(subEndpoint, subEndpointConfig, method);
|
|
100
|
-
if (subEndpointValidation) return subEndpointValidation;
|
|
101
|
-
if (subEndpointConfig?.security) {
|
|
102
|
-
const { SecurityValidator } = await import("./validators.js");
|
|
103
|
-
const securityResult = await SecurityValidator.validate(request, subEndpointConfig.security);
|
|
104
|
-
if (securityResult) return securityResult;
|
|
105
|
-
}
|
|
106
|
-
switch (method) {
|
|
107
|
-
case "GET":
|
|
108
|
-
return SessionGetHandler.handle(subEndpoint, config);
|
|
109
|
-
case "POST":
|
|
110
|
-
return SessionPostHandler.handle(request, subEndpoint, config);
|
|
111
|
-
default:
|
|
112
|
-
return HttpResponseHelper.createMethodNotAllowedResponse();
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
static validateSubEndpoint(subEndpoint, subEndpointConfig, method) {
|
|
116
|
-
if (!subEndpoint) {
|
|
117
|
-
return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
|
|
118
|
-
}
|
|
119
|
-
if (!subEndpointConfig || !subEndpointConfig.enabled) {
|
|
120
|
-
return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
|
|
121
|
-
}
|
|
122
|
-
if (!subEndpointConfig.methods?.includes(method)) {
|
|
123
|
-
return createApiErrorResponse("METHOD_NOT_ALLOWED", "Method not allowed", 405);
|
|
124
|
-
}
|
|
125
|
-
return null;
|
|
93
|
+
};
|
|
94
|
+
switch (method) {
|
|
95
|
+
case "GET":
|
|
96
|
+
return SessionGetHandler(subEndpoint);
|
|
97
|
+
case "POST":
|
|
98
|
+
return SessionPostHandler(subEndpoint);
|
|
99
|
+
default:
|
|
100
|
+
return HttpResponseHelper.createMethodNotAllowedResponse();
|
|
126
101
|
}
|
|
127
102
|
}
|
|
128
103
|
export {
|
|
129
|
-
|
|
130
|
-
SessionGetHandler,
|
|
131
|
-
SessionPostHandler
|
|
104
|
+
sessionEndpointHandler
|
|
132
105
|
};
|
|
133
106
|
//# sourceMappingURL=sessionHandlers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import { clearSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { type RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createValidators } from './fnValidators';\nimport { refreshCookieWithIdToken } from './request';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type { SessionSubEndpoint, TernSecureHandlerOptions } from './types';\n\nexport async function sessionEndpointHandler(\n context: RequestProcessorContext,\n options: TernSecureHandlerOptions,\n): Promise<Response> {\n const { subEndpoint, method } = context;\n \n const validators = createValidators(context);\n\n const {\n validateSubEndpoint,\n validateSecurity,\n validateSessionRequest,\n validateCsrfToken,\n validateIdToken,\n } = validators;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const sessionsConfig = options.endpoints?.sessions;\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n validateSubEndpoint(subEndpoint, subEndpointConfig);\n\n if (subEndpointConfig?.security) {\n await validateSecurity(subEndpointConfig.security);\n }\n\n const SessionGetHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const handleSessionVerify = async (): 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 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 validateSessionRequest();\n if (error) return error;\n\n const csrfCookieValue = await cookieStore.get('_session_terncf');\n validateCsrfToken(csrfToken || '', csrfCookieValue.value);\n\n const handleCreateSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n const res = await refreshCookieWithIdToken(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 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(idToken, cookieStore, options);\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 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 validateIdToken(idToken);\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);\n\n case 'POST':\n return SessionPostHandler(subEndpoint);\n\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n}\n"],"mappings":"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","names":["subEndpoint","cookieStore","idToken","error"]}
|
|
@@ -1,49 +1,36 @@
|
|
|
1
|
+
import { createTernSecureRequest } from "@tern-secure/backend";
|
|
2
|
+
import { createRequestProcessor } from "./c-authenticateRequestProcessor";
|
|
1
3
|
import { TENANT_ID } from "./constants";
|
|
2
4
|
import { EndpointRouter } from "./endpointRouter";
|
|
3
|
-
import {
|
|
4
|
-
import { RequestContextBuilder, ValidationPipeline } from "./handlerUtils";
|
|
5
|
+
import { createValidators } from "./fnValidators";
|
|
5
6
|
import { createApiErrorResponse } from "./responses";
|
|
6
7
|
import { DEFAULT_HANDLER_OPTIONS } from "./types";
|
|
7
8
|
import { ConfigUtils } from "./utils";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
-
}
|
|
9
|
+
function createHandlerConfig(options) {
|
|
10
|
+
const baseConfig = ConfigUtils.mergeWithDefaults(
|
|
11
|
+
DEFAULT_HANDLER_OPTIONS,
|
|
12
|
+
options
|
|
13
|
+
);
|
|
14
|
+
return {
|
|
15
|
+
...baseConfig,
|
|
16
|
+
tenantId: TENANT_ID
|
|
17
|
+
};
|
|
19
18
|
}
|
|
20
|
-
|
|
21
|
-
config;
|
|
22
|
-
|
|
23
|
-
this.config = config;
|
|
24
|
-
}
|
|
25
|
-
async handle(request) {
|
|
26
|
-
const handlerContext = RequestContextBuilder.create(request);
|
|
27
|
-
const validationContext = createRequestContext(request);
|
|
19
|
+
function createTernSecureNextJsHandler(options) {
|
|
20
|
+
const config = createHandlerConfig(options);
|
|
21
|
+
const handler = async (request) => {
|
|
28
22
|
try {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
const context = createRequestProcessor(createTernSecureRequest(request), options);
|
|
24
|
+
const { validateSecurity } = createValidators(context);
|
|
25
|
+
await validateSecurity(options.security || {});
|
|
26
|
+
if (!context.endpoint) {
|
|
27
|
+
return createApiErrorResponse("ENDPOINT_REQUIRED", "Endpoint is required", 400);
|
|
32
28
|
}
|
|
33
|
-
return await EndpointRouter.route(
|
|
29
|
+
return await EndpointRouter.route(context, config);
|
|
34
30
|
} catch (error) {
|
|
35
31
|
return createApiErrorResponse("INTERNAL_SERVER_ERROR", "Internal server error", 500);
|
|
36
32
|
}
|
|
37
|
-
}
|
|
38
|
-
async executeValidation(validationContext) {
|
|
39
|
-
const validationPipeline = new ValidationPipeline(this.config, validationContext);
|
|
40
|
-
return validationPipeline.execute();
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
function createTernSecureNextJsHandler(options) {
|
|
44
|
-
const config = HandlerConfigFactory.create(options);
|
|
45
|
-
const requestHandler = new TernSecureRequestHandler(config);
|
|
46
|
-
const handler = async (request) => await requestHandler.handle(request);
|
|
33
|
+
};
|
|
47
34
|
return {
|
|
48
35
|
GET: handler,
|
|
49
36
|
POST: handler
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/ternsecureNextjsHandler.ts"],"sourcesContent":["\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/ternsecureNextjsHandler.ts"],"sourcesContent":["import { createTernSecureRequest } from '@tern-secure/backend';\n\nimport { createRequestProcessor } from './c-authenticateRequestProcessor';\nimport { TENANT_ID } from './constants';\nimport { EndpointRouter } from './endpointRouter';\nimport { createValidators } from './fnValidators';\nimport { createApiErrorResponse } from './responses';\nimport type { TernSecureHandlerOptions } from './types';\nimport { DEFAULT_HANDLER_OPTIONS } from './types';\nimport { ConfigUtils } from './utils';\n\nfunction createHandlerConfig(options?: TernSecureHandlerOptions): TernSecureHandlerOptions {\n const baseConfig: Required<TernSecureHandlerOptions> = ConfigUtils.mergeWithDefaults(\n DEFAULT_HANDLER_OPTIONS,\n options,\n );\n\n return {\n ...baseConfig,\n tenantId: TENANT_ID,\n };\n}\n\nexport function createTernSecureNextJsHandler(options: TernSecureHandlerOptions) {\n const config = createHandlerConfig(options);\n\n const handler = async (request: Request): Promise<Response> => {\n try {\n const context = createRequestProcessor(createTernSecureRequest(request), options);\n\n const { validateSecurity } = createValidators(context);\n await validateSecurity(options.security || {});\n\n if (!context.endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n return await EndpointRouter.route(context, config);\n } catch (error) {\n return createApiErrorResponse('INTERNAL_SERVER_ERROR', 'Internal server error', 500);\n }\n };\n\n return {\n GET: handler,\n POST: handler,\n } as const;\n}\n"],"mappings":"AAAA,SAAS,+BAA+B;AAExC,SAAS,8BAA8B;AACvC,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,wBAAwB;AACjC,SAAS,8BAA8B;AAEvC,SAAS,+BAA+B;AACxC,SAAS,mBAAmB;AAE5B,SAAS,oBAAoB,SAA8D;AACzF,QAAM,aAAiD,YAAY;AAAA,IACjE;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU;AAAA,EACZ;AACF;AAEO,SAAS,8BAA8B,SAAmC;AAC/E,QAAM,SAAS,oBAAoB,OAAO;AAE1C,QAAM,UAAU,OAAO,YAAwC;AAC7D,QAAI;AACF,YAAM,UAAU,uBAAuB,wBAAwB,OAAO,GAAG,OAAO;AAEhF,YAAM,EAAE,iBAAiB,IAAI,iBAAiB,OAAO;AACrD,YAAM,iBAAiB,QAAQ,YAAY,CAAC,CAAC;AAE7C,UAAI,CAAC,QAAQ,UAAU;AACrB,eAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,MAChF;AAEA,aAAO,MAAM,eAAe,MAAM,SAAS,MAAM;AAAA,IACnD,SAAS,OAAO;AACd,aAAO,uBAAuB,yBAAyB,yBAAyB,GAAG;AAAA,IACrF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AACF;","names":[]}
|
|
@@ -7,12 +7,43 @@ const DEFAULT_CORS_OPTIONS = {
|
|
|
7
7
|
// 24 hours
|
|
8
8
|
};
|
|
9
9
|
const DEFAULT_COOKIE_OPTIONS = {
|
|
10
|
-
|
|
10
|
+
//namePrefix: '__session',
|
|
11
11
|
path: "/",
|
|
12
12
|
httpOnly: true,
|
|
13
|
-
sameSite: "lax"
|
|
14
|
-
|
|
15
|
-
// 7
|
|
13
|
+
sameSite: "lax"
|
|
14
|
+
//session: {
|
|
15
|
+
// maxAge: 3600 * 24 * 7, // Default: 1 week (consumer can set 5 mins to 2 weeks)
|
|
16
|
+
//},
|
|
17
|
+
};
|
|
18
|
+
const FIXED_TOKEN_CONFIGS = {
|
|
19
|
+
id: {
|
|
20
|
+
path: "/",
|
|
21
|
+
httpOnly: true,
|
|
22
|
+
sameSite: "lax",
|
|
23
|
+
maxAge: 3600
|
|
24
|
+
// 1 hour
|
|
25
|
+
},
|
|
26
|
+
refresh: {
|
|
27
|
+
path: "/",
|
|
28
|
+
httpOnly: true,
|
|
29
|
+
sameSite: "lax",
|
|
30
|
+
maxAge: 3600 * 24 * 30
|
|
31
|
+
// 30 days (changes when user events occur)
|
|
32
|
+
},
|
|
33
|
+
signature: {
|
|
34
|
+
path: "/",
|
|
35
|
+
httpOnly: true,
|
|
36
|
+
sameSite: "lax",
|
|
37
|
+
maxAge: 3600 * 24 * 7
|
|
38
|
+
// 1 week (as needed)
|
|
39
|
+
},
|
|
40
|
+
custom: {
|
|
41
|
+
path: "/",
|
|
42
|
+
httpOnly: true,
|
|
43
|
+
sameSite: "lax",
|
|
44
|
+
maxAge: 3600 * 24 * 7
|
|
45
|
+
// 1 week (as needed)
|
|
46
|
+
}
|
|
16
47
|
};
|
|
17
48
|
const DEFAULT_SECURITY_OPTIONS = {
|
|
18
49
|
requireCSRF: true,
|
|
@@ -82,16 +113,60 @@ const DEFAULT_HANDLER_OPTIONS = {
|
|
|
82
113
|
endpoints: {
|
|
83
114
|
sessions: DEFAULT_SESSIONS_CONFIG
|
|
84
115
|
},
|
|
116
|
+
tenantId: "",
|
|
117
|
+
enableCustomToken: false,
|
|
85
118
|
debug: false,
|
|
86
119
|
environment: "production",
|
|
87
120
|
basePath: "/api/auth"
|
|
88
121
|
};
|
|
122
|
+
class CookieUtils {
|
|
123
|
+
static getCookieName(namePrefix, tokenType) {
|
|
124
|
+
return `${namePrefix}.${tokenType}`;
|
|
125
|
+
}
|
|
126
|
+
static getCookieNames(namePrefix) {
|
|
127
|
+
return {
|
|
128
|
+
session: this.getCookieName(namePrefix, "session"),
|
|
129
|
+
id: this.getCookieName(namePrefix, "id"),
|
|
130
|
+
refresh: this.getCookieName(namePrefix, "refresh"),
|
|
131
|
+
signature: this.getCookieName(namePrefix, "signature"),
|
|
132
|
+
custom: this.getCookieName(namePrefix, "custom")
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
static getSessionConfig(cookieOptions) {
|
|
136
|
+
const sessionConfig = cookieOptions.session || {};
|
|
137
|
+
const defaultSession = DEFAULT_COOKIE_OPTIONS.session || {};
|
|
138
|
+
return {
|
|
139
|
+
domain: sessionConfig.domain ?? cookieOptions.domain,
|
|
140
|
+
path: sessionConfig.path ?? cookieOptions.path ?? "/",
|
|
141
|
+
httpOnly: sessionConfig.httpOnly ?? cookieOptions.httpOnly ?? true,
|
|
142
|
+
sameSite: sessionConfig.sameSite ?? cookieOptions.sameSite ?? "lax",
|
|
143
|
+
maxAge: sessionConfig.maxAge ?? defaultSession.maxAge ?? 3600 * 24 * 7
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
static getFixedTokenConfig(cookieOptions, tokenType) {
|
|
147
|
+
const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];
|
|
148
|
+
return {
|
|
149
|
+
domain: cookieOptions.domain,
|
|
150
|
+
path: fixedConfig.path,
|
|
151
|
+
httpOnly: fixedConfig.httpOnly,
|
|
152
|
+
sameSite: fixedConfig.sameSite,
|
|
153
|
+
maxAge: fixedConfig.maxAge
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
static validateSessionMaxAge(maxAge) {
|
|
157
|
+
const minAge = 300;
|
|
158
|
+
const maxAgeLimit = 3600 * 24 * 14;
|
|
159
|
+
return maxAge >= minAge && maxAge <= maxAgeLimit;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
89
162
|
export {
|
|
163
|
+
CookieUtils,
|
|
90
164
|
DEFAULT_COOKIE_OPTIONS,
|
|
91
165
|
DEFAULT_CORS_OPTIONS,
|
|
92
166
|
DEFAULT_ENDPOINT_CONFIG,
|
|
93
167
|
DEFAULT_HANDLER_OPTIONS,
|
|
94
168
|
DEFAULT_SECURITY_OPTIONS,
|
|
95
|
-
DEFAULT_SESSIONS_CONFIG
|
|
169
|
+
DEFAULT_SESSIONS_CONFIG,
|
|
170
|
+
FIXED_TOKEN_CONFIGS
|
|
96
171
|
};
|
|
97
172
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import { type NextResponse } from 'next/server';\n\nexport
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig,\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_COOKIE_OPTIONS: CookieOptions = {\n //namePrefix: '__session',\n path: '/',\n httpOnly: true,\n sameSite: 'lax',\n //session: {\n // maxAge: 3600 * 24 * 7, // Default: 1 week (consumer can set 5 mins to 2 weeks)\n //},\n};\n\nexport const FIXED_TOKEN_CONFIGS = {\n id: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600, // 1 hour\n },\n refresh: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 30, // 30 days (changes when user events occur)\n },\n signature: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n custom: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n} as const;\n\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n requireCSRF: true,\n allowedReferers: [],\n requiredHeaders: {},\n ipWhitelist: [],\n userAgent: {\n block: [],\n allow: [],\n },\n};\n\nexport const DEFAULT_ENDPOINT_CONFIG: EndpointConfig = {\n enabled: true,\n methods: ['GET', 'POST'],\n requireAuth: false,\n security: DEFAULT_SECURITY_OPTIONS,\n};\n\nexport const DEFAULT_SESSIONS_CONFIG: SessionEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n verify: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n createsession: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n },\n },\n refresh: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n revoke: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n },\n};\n\nexport const DEFAULT_HANDLER_OPTIONS: Required<TernSecureHandlerOptions> & {\n endpoints: Required<NonNullable<TernSecureHandlerOptions['endpoints']>>;\n} = {\n cors: DEFAULT_CORS_OPTIONS,\n cookies: DEFAULT_COOKIE_OPTIONS,\n rateLimit: {\n windowMs: 15 * 60 * 1000, // 15 minutes\n maxRequests: 100,\n skipSuccessful: false,\n skipFailedRequests: false,\n },\n security: DEFAULT_SECURITY_OPTIONS,\n endpoints: {\n sessions: DEFAULT_SESSIONS_CONFIG,\n },\n tenantId: '',\n enableCustomToken: false,\n debug: false,\n environment: 'production',\n basePath: '/api/auth',\n};\n\nexport interface ValidationResult {\n error?: NextResponse;\n data?: any;\n}\n\nexport interface ValidationConfig {\n cors?: CorsOptions;\n security?: SecurityOptions;\n endpoint?: {\n name: AuthEndpoint;\n config: EndpointConfig;\n };\n subEndpoint?: {\n name: SessionSubEndpoint;\n config: EndpointConfig;\n };\n requireIdToken?: boolean;\n requireCsrfToken?: boolean;\n}\n\nexport interface ComprehensiveValidationResult {\n isValid: boolean;\n error?: Response;\n corsResponse?: Response;\n sessionData?: {\n body: any;\n idToken?: string;\n csrfToken?: string;\n };\n}\n\nexport type suffix = 'session' | 'id' | 'refresh' | 'signature' | 'custom';\n\nexport class CookieUtils {\n static getCookieName(namePrefix: string, tokenType: suffix): string {\n return `${namePrefix}.${tokenType}`;\n }\n\n static getCookieNames(namePrefix: string) {\n return {\n session: this.getCookieName(namePrefix, 'session'),\n id: this.getCookieName(namePrefix, 'id'),\n refresh: this.getCookieName(namePrefix, 'refresh'),\n signature: this.getCookieName(namePrefix, 'signature'),\n custom: this.getCookieName(namePrefix, 'custom'),\n };\n }\n\n static getSessionConfig(cookieOptions: CookieOptions): TokenCookieConfig {\n const sessionConfig = cookieOptions.session || {};\n const defaultSession = DEFAULT_COOKIE_OPTIONS.session || {};\n\n return {\n domain: sessionConfig.domain ?? cookieOptions.domain,\n path: sessionConfig.path ?? cookieOptions.path ?? '/',\n httpOnly: sessionConfig.httpOnly ?? cookieOptions.httpOnly ?? true,\n sameSite: sessionConfig.sameSite ?? cookieOptions.sameSite ?? 'lax',\n maxAge: sessionConfig.maxAge ?? defaultSession.maxAge ?? 3600 * 24 * 7,\n };\n }\n\n static getFixedTokenConfig(\n cookieOptions: CookieOptions,\n tokenType: Exclude<suffix, 'session'>,\n ): TokenCookieConfig {\n const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];\n\n return {\n domain: cookieOptions.domain,\n path: fixedConfig.path,\n httpOnly: fixedConfig.httpOnly,\n sameSite: fixedConfig.sameSite,\n maxAge: fixedConfig.maxAge,\n };\n }\n\n static validateSessionMaxAge(maxAge: number): boolean {\n const minAge = 300; // 5 minutes\n const maxAgeLimit = 3600 * 24 * 14; // 2 weeks\n return maxAge >= minAge && maxAge <= maxAgeLimit;\n }\n}\n\nexport {\n AuthEndpoint,\n CookieOptions,\n CorsOptions,\n SecurityOptions,\n SessionSubEndpoint,\n EndpointConfig,\n SessionEndpointConfig,\n TernSecureHandlerOptions,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
const
|
|
1
|
+
const API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || "";
|
|
2
|
+
const API_URL = process.env.TERNSECURE_API_URL || "";
|
|
2
3
|
const API_VERSION = process.env.TERNSECURE_API_VERSION || "v1";
|
|
3
4
|
const SIGN_IN_URL = process.env.NEXT_PUBLIC_SIGN_IN_URL || "";
|
|
4
5
|
const SIGN_UP_URL = process.env.NEXT_PUBLIC_SIGN_UP_URL || "";
|
|
5
6
|
export {
|
|
7
|
+
API_KEY,
|
|
6
8
|
API_URL,
|
|
7
9
|
API_VERSION,
|
|
8
10
|
SIGN_IN_URL,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/constant.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/server/constant.ts"],"sourcesContent":["export const API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '';\nexport const API_URL = process.env.TERNSECURE_API_URL || '';\nexport const API_VERSION = process.env.TERNSECURE_API_VERSION || 'v1';\nexport const SIGN_IN_URL = process.env.NEXT_PUBLIC_SIGN_IN_URL || '';\nexport const SIGN_UP_URL = process.env.NEXT_PUBLIC_SIGN_UP_URL || '';"],"mappings":"AAAO,MAAM,UAAU,QAAQ,IAAI,gCAAgC;AAC5D,MAAM,UAAU,QAAQ,IAAI,sBAAsB;AAClD,MAAM,cAAc,QAAQ,IAAI,0BAA0B;AAC1D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;AAC3D,MAAM,cAAc,QAAQ,IAAI,2BAA2B;","names":[]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
constants,
|
|
3
|
-
createBackendInstanceClient,
|
|
4
3
|
createTernSecureRequest,
|
|
5
4
|
enableDebugLogging
|
|
6
5
|
} from "@tern-secure/backend";
|
|
@@ -9,7 +8,7 @@ import { NextResponse } from "next/server";
|
|
|
9
8
|
import { isRedirect, setHeader } from "../utils/response";
|
|
10
9
|
import { serverRedirectWithAuth } from "../utils/serverRedirectAuth";
|
|
11
10
|
import { createEdgeCompatibleLogger } from "../utils/withLogger";
|
|
12
|
-
import {
|
|
11
|
+
import { SIGN_IN_URL, SIGN_UP_URL } from "./constant";
|
|
13
12
|
import {
|
|
14
13
|
isNextjsNotFoundError,
|
|
15
14
|
isNextjsRedirectError,
|
|
@@ -21,20 +20,8 @@ import {
|
|
|
21
20
|
} from "./nextErrors";
|
|
22
21
|
import { createProtect } from "./protect";
|
|
23
22
|
import { createRedirect } from "./redirect";
|
|
23
|
+
import { ternSecureBackendClient } from "./ternsecureClient";
|
|
24
24
|
import { decorateRequest } from "./utils";
|
|
25
|
-
const backendClientDefaultOptions = {
|
|
26
|
-
apiUrl: API_URL,
|
|
27
|
-
apiVersion: API_VERSION
|
|
28
|
-
};
|
|
29
|
-
const ternSecureBackendClient = async () => {
|
|
30
|
-
return createBackendClientWithOptions({});
|
|
31
|
-
};
|
|
32
|
-
const createBackendClientWithOptions = (options) => {
|
|
33
|
-
return createBackendInstanceClient({
|
|
34
|
-
...backendClientDefaultOptions,
|
|
35
|
-
...options
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
25
|
const ternSecureMiddleware = (...args) => {
|
|
39
26
|
const [request, event] = parseRequestAndEvent(args);
|
|
40
27
|
const [handler, params] = parseHandlerAndOptions(args);
|
|
@@ -90,17 +77,9 @@ const ternSecureMiddleware = (...args) => {
|
|
|
90
77
|
decorateRequest(ternSecureRequest, handlerResult, requestStateClient);
|
|
91
78
|
return handlerResult;
|
|
92
79
|
};
|
|
93
|
-
const fireNextMiddleware = async (request2) => {
|
|
94
|
-
console.log("[TernSecureMiddleware] Firebase Request URL:", request2.url);
|
|
95
|
-
if (isFirebaseCookieRequest(request2)) {
|
|
96
|
-
const options = typeof params === "function" ? await params(request2) : params;
|
|
97
|
-
rewriteFirebaseRequest(options, request2);
|
|
98
|
-
return handleFirebaseAuthRequest(request2);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
80
|
const nextMiddleware = async (request2, event2) => {
|
|
102
81
|
if (isFirebaseCookieRequest(request2)) {
|
|
103
|
-
return
|
|
82
|
+
return handleFirebaseAuthRequest(request2);
|
|
104
83
|
}
|
|
105
84
|
return withAuthNextMiddleware(request2, event2);
|
|
106
85
|
};
|