@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
|
@@ -32,20 +32,8 @@ var import_constant = require("./constant");
|
|
|
32
32
|
var import_nextErrors = require("./nextErrors");
|
|
33
33
|
var import_protect = require("./protect");
|
|
34
34
|
var import_redirect = require("./redirect");
|
|
35
|
+
var import_ternsecureClient = require("./ternsecureClient");
|
|
35
36
|
var import_utils = require("./utils");
|
|
36
|
-
const backendClientDefaultOptions = {
|
|
37
|
-
apiUrl: import_constant.API_URL,
|
|
38
|
-
apiVersion: import_constant.API_VERSION
|
|
39
|
-
};
|
|
40
|
-
const ternSecureBackendClient = async () => {
|
|
41
|
-
return createBackendClientWithOptions({});
|
|
42
|
-
};
|
|
43
|
-
const createBackendClientWithOptions = (options) => {
|
|
44
|
-
return (0, import_backend.createBackendInstanceClient)({
|
|
45
|
-
...backendClientDefaultOptions,
|
|
46
|
-
...options
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
37
|
const ternSecureMiddleware = (...args) => {
|
|
50
38
|
const [request, event] = parseRequestAndEvent(args);
|
|
51
39
|
const [handler, params] = parseHandlerAndOptions(args);
|
|
@@ -63,7 +51,7 @@ const ternSecureMiddleware = (...args) => {
|
|
|
63
51
|
if (options.debug) {
|
|
64
52
|
(0, import_backend.enableDebugLogging)();
|
|
65
53
|
}
|
|
66
|
-
const reqBackendClient = await ternSecureBackendClient();
|
|
54
|
+
const reqBackendClient = await (0, import_ternsecureClient.ternSecureBackendClient)();
|
|
67
55
|
const ternSecureRequest = (0, import_backend.createTernSecureRequest)(request2);
|
|
68
56
|
const requestStateClient = await reqBackendClient.authenticateRequest(
|
|
69
57
|
ternSecureRequest,
|
|
@@ -101,17 +89,9 @@ const ternSecureMiddleware = (...args) => {
|
|
|
101
89
|
(0, import_utils.decorateRequest)(ternSecureRequest, handlerResult, requestStateClient);
|
|
102
90
|
return handlerResult;
|
|
103
91
|
};
|
|
104
|
-
const fireNextMiddleware = async (request2) => {
|
|
105
|
-
console.log("[TernSecureMiddleware] Firebase Request URL:", request2.url);
|
|
106
|
-
if (isFirebaseCookieRequest(request2)) {
|
|
107
|
-
const options = typeof params === "function" ? await params(request2) : params;
|
|
108
|
-
rewriteFirebaseRequest(options, request2);
|
|
109
|
-
return handleFirebaseAuthRequest(request2);
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
92
|
const nextMiddleware = async (request2, event2) => {
|
|
113
93
|
if (isFirebaseCookieRequest(request2)) {
|
|
114
|
-
return
|
|
94
|
+
return handleFirebaseAuthRequest(request2);
|
|
115
95
|
}
|
|
116
96
|
return withAuthNextMiddleware(request2, event2);
|
|
117
97
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/ternSecureEdgeMiddleware.ts"],"sourcesContent":["import type {\r\n AuthObject,\r\n RequestOptions,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport {\r\n constants,\r\n createBackendInstanceClient,\r\n createTernSecureRequest,\r\n enableDebugLogging,\r\n} from '@tern-secure/backend';\r\nimport type {\r\n TernSecureConfig,\r\n} from '@tern-secure/types';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware,NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { createEdgeCompatibleLogger } from '../utils/withLogger';\r\nimport { API_URL, API_VERSION,SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect,createProtect } from './protect';\r\nimport { createRedirect, type RedirectFun } from './redirect';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends RequestOptions {\r\n debug?: boolean;\r\n firebaseOptions?: TernSecureConfig;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nconst backendClientDefaultOptions = {\r\n apiUrl: API_URL,\r\n apiVersion: API_VERSION,\r\n};\r\n\r\nconst ternSecureBackendClient = async () => {\r\n return createBackendClientWithOptions({});\r\n};\r\n\r\nconst createBackendClientWithOptions: typeof createBackendInstanceClient = options => {\r\n return createBackendInstanceClient({\r\n ...backendClientDefaultOptions,\r\n ...options,\r\n });\r\n};\r\n\r\nexport const ternSecureMiddleware = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n ...resolvedParams,\r\n };\r\n\r\n const logger = createEdgeCompatibleLogger(options.debug);\r\n\r\n if (options.debug) {\r\n enableDebugLogging();\r\n }\r\n\r\n //const { authObject, headers: authHeaders } =\r\n // await authenticateMiddlewareRequest(request, checkRevoked, logger);\r\n\r\n //const reqBackend = await createBackendInstanceEdge(request, checkRevoked);\r\n const reqBackendClient = await ternSecureBackendClient();\r\n //const requestState = reqBackend.requestState;\r\n //const authObject = requestState.auth();\r\n //const authHeaders = requestState.headers;\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const { redirectToSignIn } = createMiddlewareRedirects(ternSecureRequest);\r\n\r\n const { redirectToSignUp } = createMiddlewareRedirects(ternSecureRequest);\r\n\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient);\r\n return handlerResult;\r\n };\r\n\r\n const fireNextMiddleware: NextMiddleware = async (request) => {\r\n console.log('[TernSecureMiddleware] Firebase Request URL:', request.url);\r\n if (isFirebaseCookieRequest(request)) {\r\n const options = typeof params === 'function' ? await params(request) : params;\r\n rewriteFirebaseRequest(options, request);\r\n return handleFirebaseAuthRequest(request);\r\n }\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n if (isFirebaseCookieRequest(request)) {\r\n return fireNextMiddleware(request, event);\r\n }\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\nconst isFirebaseRequest = (request: NextMiddlewareRequestParam) =>\r\n request.nextUrl.pathname.startsWith('/__/');\r\n\r\nconst rewriteFirebaseRequest = (options: MiddlewareOptions, request: NextMiddlewareRequestParam) => {\r\n const newUrl = new URL(request.url);\r\n newUrl.host = options.firebaseOptions?.authDomain || '';\r\n newUrl.port = '';\r\n return NextResponse.rewrite(newUrl);\r\n}\r\n\r\nconst finalTarget = (request: NextMiddlewareRequestParam) => {\r\n const finalTargetUrl = request.nextUrl.searchParams.get('finalTarget');\r\n return finalTargetUrl ? new URL(finalTargetUrl, request.url) : undefined;\r\n};\r\n\r\nconst isFirebaseCookieRequest = (request: NextMiddlewareRequestParam) =>\r\n request.nextUrl.pathname === '/__cookies__';\r\n\r\n/**\r\n * Create middleware redirect functions\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: SIGN_IN_URL,\r\n signUpUrl: SIGN_UP_URL,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n\r\nconst handleFirebaseAuthRequest = async (\r\n request: NextRequest,\r\n): Promise<NextResponse | null> => {\r\n\r\n console.log('Checking for __cookies__ path');\r\n\r\n const isDevMode = process.env.NODE_ENV === 'development';\r\n const ID_TOKEN_COOKIE_NAME = isDevMode ? `__dev_FIREBASE_[DEFAULT]` : `__HOST-FIREBASE_[DEFAULT]`;\r\n const REFRESH_TOKEN_COOKIE_NAME = isDevMode\r\n ? '__dev_FIREBASEID_[DEFAULT]'\r\n : `__HOST-FIREBASEID_[DEFAULT]`;\r\n const ID_TOKEN_COOKIE = {\r\n path: '/',\r\n secure: !isDevMode,\r\n sameSite: 'strict',\r\n partitioned: true,\r\n name: ID_TOKEN_COOKIE_NAME,\r\n maxAge: 34560000,\r\n priority: 'high',\r\n } as const;\r\n const REFRESH_TOKEN_COOKIE = {\r\n ...ID_TOKEN_COOKIE,\r\n httpOnly: true,\r\n name: REFRESH_TOKEN_COOKIE_NAME,\r\n } as const;\r\n\r\n if (request.nextUrl.pathname === '/__cookies__') {\r\n console.log('Handling /__cookies__ request');\r\n const method = request.method;\r\n if (method === 'DELETE') {\r\n const response = new NextResponse('');\r\n response.cookies.delete({ ...ID_TOKEN_COOKIE, maxAge: 0 });\r\n response.cookies.delete({ ...REFRESH_TOKEN_COOKIE, maxAge: 0 });\r\n return response;\r\n }\r\n\r\n const headers: Record<string, string> = {};\r\n const headerNames = [\r\n 'content-type',\r\n 'X-Firebase-Client',\r\n 'X-Firebase-gmpid',\r\n 'X-Firebase-AppCheck',\r\n 'X-Client-Version',\r\n ];\r\n\r\n headerNames.forEach(headerName => {\r\n const headerValue = request.headers.get(headerName);\r\n if (headerValue) {\r\n headers[headerName] = headerValue;\r\n }\r\n });\r\n\r\n const finalTargetParam = request.nextUrl.searchParams.get('finalTarget');\r\n\r\n const url = new URL(finalTargetParam || '');\r\n let body: ReadableStream<any> | string | null = request.body;\r\n\r\n const isTokenRequest = !!url.pathname.match(/^(\\/securetoken\\.googleapis\\.com)?\\/v1\\/token/);\r\n const isSignInRequest = !!url.pathname.match(\r\n /^(\\/identitytoolkit\\.googleapis\\.com)?\\/v1\\/accounts:signInWith/,\r\n );\r\n\r\n if (!isTokenRequest && !isSignInRequest)\r\n throw new Error('Could not determine the request type to proxy');\r\n\r\n if (isTokenRequest) {\r\n body = await request.text();\r\n const bodyParams = new URLSearchParams(body.trim());\r\n if (bodyParams.has('refresh_token')) {\r\n const refreshToken = request.cookies.get(REFRESH_TOKEN_COOKIE.name)?.value;\r\n if (refreshToken) {\r\n bodyParams.set('refresh_token', refreshToken);\r\n body = bodyParams.toString();\r\n }\r\n }\r\n }\r\n\r\n const response = await fetch(url, { method, body, headers });\r\n const json = await response.json();\r\n\r\n if (!response.ok) {\r\n return NextResponse.json(json, { status: response.status, statusText: response.statusText });\r\n }\r\n\r\n let refreshToken, idToken, maxAge;\r\n if (isSignInRequest) {\r\n refreshToken = json.refreshToken;\r\n idToken = json.idToken;\r\n maxAge = json.expiresIn;\r\n json.refreshToken = 'REDACTED';\r\n } else {\r\n refreshToken = json.refresh_token;\r\n idToken = json.id_token;\r\n maxAge = json.expires_in;\r\n json.refresh_token = 'REDACTED';\r\n }\r\n\r\n const nextResponse = NextResponse.json(json);\r\n if (idToken) nextResponse.cookies.set({ ...ID_TOKEN_COOKIE, maxAge, value: idToken });\r\n if (refreshToken) nextResponse.cookies.set({ ...REFRESH_TOKEN_COOKIE, value: refreshToken });\r\n return nextResponse;\r\n }\r\n return null;\r\n};\r\n"],"mappings":"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","names":["request","event","nextjsNotFound","response","refreshToken"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ternSecureEdgeMiddleware.ts"],"sourcesContent":["import type {\r\n AuthObject,\r\n RequestOptions,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport {\r\n constants,\r\n createTernSecureRequest,\r\n enableDebugLogging,\r\n} from '@tern-secure/backend';\r\nimport type {\r\n TernSecureConfig,\r\n} from '@tern-secure/types';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware,NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { createEdgeCompatibleLogger } from '../utils/withLogger';\r\nimport { SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect,createProtect } from './protect';\r\nimport { createRedirect, type RedirectFun } from './redirect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends RequestOptions {\r\n debug?: boolean;\r\n firebaseOptions?: TernSecureConfig;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureMiddleware = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n ...resolvedParams,\r\n };\r\n\r\n const logger = createEdgeCompatibleLogger(options.debug);\r\n\r\n if (options.debug) {\r\n enableDebugLogging();\r\n }\r\n\r\n //const { authObject, headers: authHeaders } =\r\n // await authenticateMiddlewareRequest(request, checkRevoked, logger);\r\n\r\n //const reqBackend = await createBackendInstanceEdge(request, checkRevoked);\r\n const reqBackendClient = await ternSecureBackendClient();\r\n //const requestState = reqBackend.requestState;\r\n //const authObject = requestState.auth();\r\n //const authHeaders = requestState.headers;\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const { redirectToSignIn } = createMiddlewareRedirects(ternSecureRequest);\r\n\r\n const { redirectToSignUp } = createMiddlewareRedirects(ternSecureRequest);\r\n\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient);\r\n return handlerResult;\r\n };\r\n\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n if(isFirebaseCookieRequest(request)) {\r\n return handleFirebaseAuthRequest(request);\r\n }\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\nconst isFirebaseRequest = (request: NextMiddlewareRequestParam) =>\r\n request.nextUrl.pathname.startsWith('/__/');\r\n\r\nconst rewriteFirebaseRequest = (options: MiddlewareOptions, request: NextMiddlewareRequestParam) => {\r\n const newUrl = new URL(request.url);\r\n newUrl.host = options.firebaseOptions?.authDomain || '';\r\n newUrl.port = '';\r\n return NextResponse.rewrite(newUrl);\r\n}\r\n\r\nconst finalTarget = (request: NextMiddlewareRequestParam) => {\r\n const finalTargetUrl = request.nextUrl.searchParams.get('finalTarget');\r\n return finalTargetUrl ? new URL(finalTargetUrl, request.url) : undefined;\r\n};\r\n\r\nconst isFirebaseCookieRequest = (request: NextMiddlewareRequestParam) =>\r\n request.nextUrl.pathname === '/__cookies__';\r\n\r\n/**\r\n * Create middleware redirect functions\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: SIGN_IN_URL,\r\n signUpUrl: SIGN_UP_URL,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n\r\nconst handleFirebaseAuthRequest = async (\r\n request: NextRequest,\r\n): Promise<NextResponse | null> => {\r\n\r\n console.log('Checking for __cookies__ path');\r\n\r\n const isDevMode = process.env.NODE_ENV === 'development';\r\n const ID_TOKEN_COOKIE_NAME = isDevMode ? `__dev_FIREBASE_[DEFAULT]` : `__HOST-FIREBASE_[DEFAULT]`;\r\n const REFRESH_TOKEN_COOKIE_NAME = isDevMode\r\n ? '__dev_FIREBASEID_[DEFAULT]'\r\n : `__HOST-FIREBASEID_[DEFAULT]`;\r\n const ID_TOKEN_COOKIE = {\r\n path: '/',\r\n secure: !isDevMode,\r\n sameSite: 'strict',\r\n partitioned: true,\r\n name: ID_TOKEN_COOKIE_NAME,\r\n maxAge: 34560000,\r\n priority: 'high',\r\n } as const;\r\n const REFRESH_TOKEN_COOKIE = {\r\n ...ID_TOKEN_COOKIE,\r\n httpOnly: true,\r\n name: REFRESH_TOKEN_COOKIE_NAME,\r\n } as const;\r\n\r\n if (request.nextUrl.pathname === '/__cookies__') {\r\n console.log('Handling /__cookies__ request');\r\n const method = request.method;\r\n if (method === 'DELETE') {\r\n const response = new NextResponse('');\r\n response.cookies.delete({ ...ID_TOKEN_COOKIE, maxAge: 0 });\r\n response.cookies.delete({ ...REFRESH_TOKEN_COOKIE, maxAge: 0 });\r\n return response;\r\n }\r\n\r\n const headers: Record<string, string> = {};\r\n const headerNames = [\r\n 'content-type',\r\n 'X-Firebase-Client',\r\n 'X-Firebase-gmpid',\r\n 'X-Firebase-AppCheck',\r\n 'X-Client-Version',\r\n ];\r\n\r\n headerNames.forEach(headerName => {\r\n const headerValue = request.headers.get(headerName);\r\n if (headerValue) {\r\n headers[headerName] = headerValue;\r\n }\r\n });\r\n\r\n const finalTargetParam = request.nextUrl.searchParams.get('finalTarget');\r\n\r\n const url = new URL(finalTargetParam || '');\r\n let body: ReadableStream<any> | string | null = request.body;\r\n\r\n const isTokenRequest = !!url.pathname.match(/^(\\/securetoken\\.googleapis\\.com)?\\/v1\\/token/);\r\n const isSignInRequest = !!url.pathname.match(\r\n /^(\\/identitytoolkit\\.googleapis\\.com)?\\/v1\\/accounts:signInWith/,\r\n );\r\n\r\n if (!isTokenRequest && !isSignInRequest)\r\n throw new Error('Could not determine the request type to proxy');\r\n\r\n if (isTokenRequest) {\r\n body = await request.text();\r\n const bodyParams = new URLSearchParams(body.trim());\r\n if (bodyParams.has('refresh_token')) {\r\n const refreshToken = request.cookies.get(REFRESH_TOKEN_COOKIE.name)?.value;\r\n if (refreshToken) {\r\n bodyParams.set('refresh_token', refreshToken);\r\n body = bodyParams.toString();\r\n }\r\n }\r\n }\r\n\r\n const response = await fetch(url, { method, body, headers });\r\n const json = await response.json();\r\n\r\n if (!response.ok) {\r\n return NextResponse.json(json, { status: response.status, statusText: response.statusText });\r\n }\r\n\r\n let refreshToken, idToken, maxAge;\r\n if (isSignInRequest) {\r\n refreshToken = json.refreshToken;\r\n idToken = json.idToken;\r\n maxAge = json.expiresIn;\r\n json.refreshToken = 'REDACTED';\r\n } else {\r\n refreshToken = json.refresh_token;\r\n idToken = json.id_token;\r\n maxAge = json.expires_in;\r\n json.refresh_token = 'REDACTED';\r\n }\r\n\r\n const nextResponse = NextResponse.json(json);\r\n if (idToken) nextResponse.cookies.set({ ...ID_TOKEN_COOKIE, maxAge, value: idToken });\r\n if (refreshToken) nextResponse.cookies.set({ ...REFRESH_TOKEN_COOKIE, value: refreshToken });\r\n return nextResponse;\r\n }\r\n return null;\r\n};\r\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,qBAIO;AAIP,wBAA2C;AAE3C,oBAA6B;AAE7B,sBAAsC;AACtC,gCAAuC;AACvC,wBAA2C;AAC3C,sBAAyC;AACzC,wBAQO;AACP,qBAA+C;AAC/C,sBAAiD;AACjD,8BAAwC;AAMxC,mBAAgC;AAoDzB,MAAM,uBAAwB,IAChC,SACuC;AAC1C,QAAM,CAAC,SAAS,KAAK,IAAI,qBAAqB,IAAI;AAClD,QAAM,CAAC,SAAS,MAAM,IAAI,uBAAuB,IAAI;AAErD,QAAM,aAAa,MAAM;AACvB,UAAM,yBAAyC,OAAOA,UAASC,WAAU;AACvE,YAAM,iBAAiB,OAAO,WAAW,aAAa,MAAM,OAAOD,QAAO,IAAI;AAC9E,YAAM,YAAY,eAAe,aAAa;AAC9C,YAAM,YAAY,eAAe,aAAa;AAE9C,YAAM,UAAU;AAAA,QACd;AAAA,QACA;AAAA,QACA,GAAG;AAAA,MACL;AAEA,YAAM,aAAS,8CAA2B,QAAQ,KAAK;AAEvD,UAAI,QAAQ,OAAO;AACjB,+CAAmB;AAAA,MACrB;AAMA,YAAM,mBAAmB,UAAM,iDAAwB;AAKvD,YAAM,wBAAoB,wCAAwBA,QAAO;AAEzD,YAAM,qBAAqB,MAAM,iBAAiB;AAAA,QAChD;AAAA,QACA;AAAA,MACF;AAEA,YAAM,mBAAmB,mBAAmB,KAAK;AAEjD,YAAM,EAAE,iBAAiB,IAAI,0BAA0B,iBAAiB;AAExE,YAAM,EAAE,iBAAiB,IAAI,0BAA0B,iBAAiB;AAExE,YAAM,UAAU,MAAM;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,UAAgC,OAAO,OAAO,kBAAkB;AAAA,QACpE;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,cAAc,MAAM,QAAQ,QAAQ,OAAO;AACjD,kBAAY,UAAU;AAEtB,UAAI,gBAA0B,2BAAa,KAAK;AAEhD,UAAI;AACF,cAAM,oBAAoB,MAAM,UAAU,aAAaA,UAASC,MAAK;AACrE,wBAAgB,qBAAqB;AAAA,MACvC,SAAS,OAAY;AACnB,wBAAgB,mBAAmB,OAAO,mBAAmBD,QAAO;AAAA,MACtE;AAEA,UAAI,mBAAmB,SAAS;AAC9B,2BAAmB,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACjD,wBAAc,QAAQ,OAAO,KAAK,KAAK;AAAA,QACzC,CAAC;AAAA,MACH;AAEA,cAAI,4BAAW,aAAa,GAAG;AAC7B,mBAAO,kDAAuB,mBAAmB,aAAa;AAAA,MAChE;AAEA,wCAAgB,mBAAmB,eAAe,kBAAkB;AACpE,aAAO;AAAA,IACT;AAGA,UAAM,iBAAiC,OAAOA,UAASC,WAAU;AAC/D,UAAG,wBAAwBD,QAAO,GAAG;AACnC,eAAO,0BAA0BA,QAAO;AAAA,MAC1C;AACA,aAAO,uBAAuBA,UAASC,MAAK;AAAA,IAC9C;AAEA,QAAI,WAAW,OAAO;AACpB,aAAO,eAAe,SAAS,KAAK;AAAA,IACtC;AAEA,WAAO;AAAA,EACT;AACA,SAAO,WAAW;AACpB;AAEA,MAAM,uBAAuB,CAAC,SAAoB;AAChD,SAAO;AAAA,IACL,KAAK,CAAC,aAAa,UAAU,KAAK,CAAC,IAAI;AAAA,IACvC,KAAK,CAAC,aAAa,UAAU,KAAK,CAAC,IAAI;AAAA,EACzC;AACF;AAEA,MAAM,yBAAyB,CAAC,SAAoB;AAClD,SAAO;AAAA,IACL,OAAO,KAAK,CAAC,MAAM,aAAa,KAAK,CAAC,IAAI;AAAA,KACzC,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC;AAAA,EACnF;AACF;AAEA,MAAM,oBAAoB,CAAC,YACzB,QAAQ,QAAQ,SAAS,WAAW,MAAM;AAE5C,MAAM,yBAAyB,CAAC,SAA4B,YAAwC;AAClG,QAAM,SAAS,IAAI,IAAI,QAAQ,GAAG;AAClC,SAAO,OAAO,QAAQ,iBAAiB,cAAc;AACrD,SAAO,OAAO;AACd,SAAO,2BAAa,QAAQ,MAAM;AACpC;AAEA,MAAM,cAAc,CAAC,YAAwC;AAC3D,QAAM,iBAAiB,QAAQ,QAAQ,aAAa,IAAI,aAAa;AACrE,SAAO,iBAAiB,IAAI,IAAI,gBAAgB,QAAQ,GAAG,IAAI;AACjE;AAEA,MAAM,0BAA0B,CAAC,YAC/B,QAAQ,QAAQ,aAAa;AAK/B,MAAM,4BAA4B,CAAC,sBAAyC;AAC1E,QAAM,mBAA6D,CAAC,OAAO,CAAC,MAAM;AAChF,UAAM,MAAM,kBAAkB,QAAQ,SAAS;AAC/C,iDAAsB,KAAK,KAAK,aAAa;AAAA,EAC/C;AAEA,QAAM,mBAA6D,CAAC,OAAO,CAAC,MAAM;AAChF,UAAM,MAAM,kBAAkB,QAAQ,SAAS;AAC/C,iDAAsB,KAAK,KAAK,aAAa;AAAA,EAC/C;AAEA,SAAO,EAAE,kBAAkB,iBAAiB;AAC9C;AAEA,MAAM,0BAA0B,CAC9B,mBACA,YACA,qBACG;AACH,SAAQ,OAAO,QAAa,YAAiB;AAC3C,UAAM,WAAW,UAAM,kBAAAC,UAAe;AAEtC,UAAM,WAAW,CAAC,YAChB,uCAAoB,KAAK;AAAA,MACvB,aAAa;AAAA,IACf,CAAC;AAEH,eAAO,8BAAc;AAAA,MACnB,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,EAAE,QAAQ,OAAO;AAAA,EACpB;AACF;AAEO,MAAM,kBAAkB,CAAC,QAAsB;AACpD,SAAO,2BAAa,SAAS,KAAK;AAAA,IAChC,SAAS,EAAE,CAAC,yBAAU,QAAQ,oBAAoB,GAAG,OAAO;AAAA,EAC9D,CAAC;AACH;AAKA,MAAM,qBAAqB,CACzB,OACA,mBACA,gBACa;AACb,UAAI,yCAAsB,KAAK,GAAG;AAChC,eAAO;AAAA,MACL,2BAAa,QAAQ,IAAI,IAAI,SAAS,KAAK,IAAI,CAAC,IAAI,YAAY,GAAG,CAAC;AAAA,MACpE,yBAAU,QAAQ;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,yBAAqB,2CAAwB,KAAK;AACxD,QAAM,yBAAqB,2CAAwB,KAAK;AAExD,MAAI,sBAAsB,oBAAoB;AAC5C,UAAM,eAAW,gCAAe;AAAA,MAC9B;AAAA,MACA,SAAS,kBAAkB;AAAA,MAC3B,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAC;AAED,UAAM,EAAE,cAAc,IAAI;AAE1B,WAAO,SAAS,qBAAqB,qBAAqB,kBAAkB,EAAE;AAAA,MAC5E;AAAA,IACF,CAAC;AAAA,EACH;AAEA,UAAI,yCAAsB,KAAK,GAAG;AAChC,WAAO,gBAAgB,MAAM,WAAW;AAAA,EAC1C;AAEA,QAAM;AACR;AAEA,MAAM,4BAA4B,OAChC,YACiC;AAEjC,UAAQ,IAAI,+BAA+B;AAE3C,QAAM,YAAY,QAAQ,IAAI,aAAa;AAC3C,QAAM,uBAAuB,YAAY,6BAA6B;AACtE,QAAM,4BAA4B,YAC9B,+BACA;AACJ,QAAM,kBAAkB;AAAA,IACtB,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA,IACT,UAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACA,QAAM,uBAAuB;AAAA,IAC3B,GAAG;AAAA,IACH,UAAU;AAAA,IACV,MAAM;AAAA,EACR;AAEA,MAAI,QAAQ,QAAQ,aAAa,gBAAgB;AAC/C,YAAQ,IAAI,+BAA+B;AAC3C,UAAM,SAAS,QAAQ;AACvB,QAAI,WAAW,UAAU;AACvB,YAAMC,YAAW,IAAI,2BAAa,EAAE;AACpC,MAAAA,UAAS,QAAQ,OAAO,EAAE,GAAG,iBAAiB,QAAQ,EAAE,CAAC;AACzD,MAAAA,UAAS,QAAQ,OAAO,EAAE,GAAG,sBAAsB,QAAQ,EAAE,CAAC;AAC9D,aAAOA;AAAA,IACT;AAEA,UAAM,UAAkC,CAAC;AACrC,UAAM,cAAc;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,gBAAY,QAAQ,gBAAc;AAChC,YAAM,cAAc,QAAQ,QAAQ,IAAI,UAAU;AAClD,UAAI,aAAa;AACf,gBAAQ,UAAU,IAAI;AAAA,MACxB;AAAA,IACF,CAAC;AAED,UAAM,mBAAmB,QAAQ,QAAQ,aAAa,IAAI,aAAa;AAEvE,UAAM,MAAM,IAAI,IAAI,oBAAoB,EAAE;AAC1C,QAAI,OAA4C,QAAQ;AAExD,UAAM,iBAAiB,CAAC,CAAC,IAAI,SAAS,MAAM,+CAA+C;AAC3F,UAAM,kBAAkB,CAAC,CAAC,IAAI,SAAS;AAAA,MACrC;AAAA,IACF;AAEA,QAAI,CAAC,kBAAkB,CAAC;AACtB,YAAM,IAAI,MAAM,+CAA+C;AAEjE,QAAI,gBAAgB;AAClB,aAAO,MAAM,QAAQ,KAAK;AAC1B,YAAM,aAAa,IAAI,gBAAgB,KAAK,KAAK,CAAC;AAClD,UAAI,WAAW,IAAI,eAAe,GAAG;AACnC,cAAMC,gBAAe,QAAQ,QAAQ,IAAI,qBAAqB,IAAI,GAAG;AACrE,YAAIA,eAAc;AAChB,qBAAW,IAAI,iBAAiBA,aAAY;AAC5C,iBAAO,WAAW,SAAS;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,MAAM,QAAQ,CAAC;AAC3D,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO,2BAAa,KAAK,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,CAAC;AAAA,IAC7F;AAEA,QAAI,cAAc,SAAS;AAC3B,QAAI,iBAAiB;AACnB,qBAAe,KAAK;AACpB,gBAAU,KAAK;AACf,eAAS,KAAK;AACd,WAAK,eAAe;AAAA,IACtB,OAAO;AACL,qBAAe,KAAK;AACpB,gBAAU,KAAK;AACf,eAAS,KAAK;AACd,WAAK,gBAAgB;AAAA,IACvB;AAEA,UAAM,eAAe,2BAAa,KAAK,IAAI;AAC3C,QAAI,QAAS,cAAa,QAAQ,IAAI,EAAE,GAAG,iBAAiB,QAAQ,OAAO,QAAQ,CAAC;AACpF,QAAI,aAAc,cAAa,QAAQ,IAAI,EAAE,GAAG,sBAAsB,OAAO,aAAa,CAAC;AAC3F,WAAO;AAAA,EACT;AACA,SAAO;AACT;","names":["request","event","nextjsNotFound","response","refreshToken"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
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 ternsecureClient_exports = {};
|
|
20
|
+
__export(ternsecureClient_exports, {
|
|
21
|
+
ternSecureBackendClient: () => ternSecureBackendClient
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(ternsecureClient_exports);
|
|
24
|
+
var import_backend = require("@tern-secure/backend");
|
|
25
|
+
var import_constant = require("./constant");
|
|
26
|
+
const backendClientDefaultOptions = {
|
|
27
|
+
apiKey: import_constant.API_KEY,
|
|
28
|
+
apiUrl: import_constant.API_URL,
|
|
29
|
+
apiVersion: import_constant.API_VERSION
|
|
30
|
+
};
|
|
31
|
+
const ternSecureBackendClient = async () => {
|
|
32
|
+
return createBackendClientWithOptions({});
|
|
33
|
+
};
|
|
34
|
+
const createBackendClientWithOptions = (options) => {
|
|
35
|
+
return (0, import_backend.createBackendInstanceClient)({
|
|
36
|
+
...backendClientDefaultOptions,
|
|
37
|
+
...options
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
41
|
+
0 && (module.exports = {
|
|
42
|
+
ternSecureBackendClient
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=ternsecureClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ternsecureClient.ts"],"sourcesContent":["import {\n createBackendInstanceClient,\n} from '@tern-secure/backend';\n\nimport { API_KEY, API_URL, API_VERSION } from './constant';\n\nconst backendClientDefaultOptions = {\n apiKey: API_KEY,\n apiUrl: API_URL,\n apiVersion: API_VERSION,\n};\n\nconst ternSecureBackendClient = async () => {\n return createBackendClientWithOptions({});\n};\n\nconst createBackendClientWithOptions: typeof createBackendInstanceClient = options => {\n return createBackendInstanceClient({\n ...backendClientDefaultOptions,\n ...options,\n });\n};\n\nexport { ternSecureBackendClient };"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAEO;AAEP,sBAA8C;AAE9C,MAAM,8BAA8B;AAAA,EAClC,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,YAAY;AACd;AAEA,MAAM,0BAA0B,YAAY;AAC1C,SAAO,+BAA+B,CAAC,CAAC;AAC1C;AAEA,MAAM,iCAAqE,aAAW;AACpF,aAAO,4CAA4B;AAAA,IACjC,GAAG;AAAA,IACH,GAAG;AAAA,EACL,CAAC;AACH;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/app-router/admin/api/endpoints/abstract.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n SessionSubEndpoint,\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/app-router/admin/api/endpoints/abstract.ts"],"sourcesContent":["import type { RequestProcessorContext } from '../../c-authenticateRequestProcessor';\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;\n method: string;\n requestProcessorContext: RequestProcessorContext;\n}\n\nexport interface EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean;\n handle(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response>;\n}\n\nexport abstract class BaseEndpointHandler implements EndpointHandler {\n abstract canHandle(endpoint: AuthEndpoint): boolean;\n abstract handle(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\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":"AAwBO,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":[]}
|
|
@@ -5,8 +5,13 @@ class RequestProcessorContext {
|
|
|
5
5
|
this.options = options;
|
|
6
6
|
this.initHeaderValues();
|
|
7
7
|
this.initCookieValues();
|
|
8
|
+
this.initUrlValues();
|
|
9
|
+
Object.assign(this, options);
|
|
8
10
|
this.ternUrl = this.ternSecureRequest.ternUrl;
|
|
9
11
|
}
|
|
12
|
+
get request() {
|
|
13
|
+
return this.ternSecureRequest;
|
|
14
|
+
}
|
|
10
15
|
initHeaderValues() {
|
|
11
16
|
this.sessionTokenInHeader = this.parseAuthorizationHeader(
|
|
12
17
|
this.getHeader(constants.Headers.Authorization)
|
|
@@ -21,10 +26,19 @@ class RequestProcessorContext {
|
|
|
21
26
|
this.accept = this.getHeader(constants.Headers.Accept);
|
|
22
27
|
}
|
|
23
28
|
initCookieValues() {
|
|
29
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
30
|
+
const defaultPrefix = isProduction ? "__HOST-" : "__dev_";
|
|
31
|
+
this.sessionTokenInCookie = this.getCookie(constants.Cookies.Session);
|
|
32
|
+
this.idTokenInCookie = this.getCookie(`${defaultPrefix}${constants.Cookies.IdToken}`);
|
|
33
|
+
this.refreshTokenInCookie = this.getCookie(`${defaultPrefix}${constants.Cookies.Refresh}`);
|
|
24
34
|
this.csrfTokenInCookie = this.getCookie(constants.Cookies.CsrfToken);
|
|
35
|
+
this.customTokenInCookie = this.getCookie(constants.Cookies.Custom);
|
|
25
36
|
}
|
|
26
|
-
|
|
27
|
-
|
|
37
|
+
initUrlValues() {
|
|
38
|
+
this.method = this.ternSecureRequest.method;
|
|
39
|
+
this.pathSegments = this.ternSecureRequest.ternUrl.pathname.split("/").filter(Boolean);
|
|
40
|
+
this.endpoint = this.pathSegments[2];
|
|
41
|
+
this.subEndpoint = this.pathSegments[3];
|
|
28
42
|
}
|
|
29
43
|
getHeader(name) {
|
|
30
44
|
return this.ternSecureRequest.headers.get(name) || void 0;
|
|
@@ -46,10 +60,10 @@ class RequestProcessorContext {
|
|
|
46
60
|
return void 0;
|
|
47
61
|
}
|
|
48
62
|
}
|
|
49
|
-
const createRequestProcessor =
|
|
63
|
+
const createRequestProcessor = (ternSecureRequest, options) => {
|
|
50
64
|
return new RequestProcessorContext(ternSecureRequest, options);
|
|
51
65
|
};
|
|
52
66
|
export {
|
|
53
67
|
createRequestProcessor
|
|
54
68
|
};
|
|
55
|
-
//# sourceMappingURL=
|
|
69
|
+
//# sourceMappingURL=c-authenticateRequestProcessor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/c-authenticateRequestProcessor.ts"],"sourcesContent":["import type { TernSecureRequest } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\n\nimport type { AuthEndpoint, SessionSubEndpoint, 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 idTokenInCookie: string | undefined;\n refreshTokenInCookie: string | undefined;\n csrfTokenInCookie: string | undefined;\n sessionTokenInCookie?: string | undefined;\n customTokenInCookie?: string | undefined;\n\n method: string;\n pathSegments: string[];\n endpoint?: AuthEndpoint;\n subEndpoint?: SessionSubEndpoint;\n\n ternUrl: URL;\n instanceType: string;\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.initUrlValues();\n Object.assign(this, options);\n this.ternUrl = this.ternSecureRequest.ternUrl;\n }\n\n public get request(): TernSecureRequest {\n return this.ternSecureRequest;\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 const isProduction = process.env.NODE_ENV === 'production';\n const defaultPrefix = isProduction ? '__HOST-' : '__dev_';\n this.sessionTokenInCookie = this.getCookie(constants.Cookies.Session);\n\n // System-fixed cookies using backend constants\n this.idTokenInCookie = this.getCookie(`${defaultPrefix}${constants.Cookies.IdToken}`);\n this.refreshTokenInCookie = this.getCookie(`${defaultPrefix}${constants.Cookies.Refresh}`);\n this.csrfTokenInCookie = this.getCookie(constants.Cookies.CsrfToken);\n this.customTokenInCookie = this.getCookie(constants.Cookies.Custom);\n }\n\n private initUrlValues() {\n this.method = this.ternSecureRequest.method;\n this.pathSegments = this.ternSecureRequest.ternUrl.pathname.split('/').filter(Boolean);\n this.endpoint = this.pathSegments[2] as AuthEndpoint;\n this.subEndpoint = this.pathSegments[3] as SessionSubEndpoint;\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 = (\n ternSecureRequest: TernSecureRequest,\n options: TernSecureHandlerOptions,\n): RequestProcessorContext => {\n return new RequestProcessorContext(ternSecureRequest, options);\n};\n"],"mappings":"AACA,SAAS,iBAAiB;AAsC1B,MAAM,wBAA2D;AAAA,EACxD,YACG,mBACA,SACR;AAFQ;AACA;AAER,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AACtB,SAAK,cAAc;AACnB,WAAO,OAAO,MAAM,OAAO;AAC3B,SAAK,UAAU,KAAK,kBAAkB;AAAA,EACxC;AAAA,EAEA,IAAW,UAA6B;AACtC,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,mBAAmB;AACzB,SAAK,uBAAuB,KAAK;AAAA,MAC/B,KAAK,UAAU,UAAU,QAAQ,aAAa;AAAA,IAChD;AACA,SAAK,SAAS,KAAK,UAAU,UAAU,QAAQ,MAAM;AACrD,SAAK,OAAO,KAAK,UAAU,UAAU,QAAQ,IAAI;AACjD,SAAK,gBAAgB,KAAK,UAAU,UAAU,QAAQ,aAAa;AACnE,SAAK,iBACH,KAAK,UAAU,UAAU,QAAQ,wBAAwB,KACzD,KAAK,UAAU,UAAU,QAAQ,cAAc;AACjD,SAAK,WAAW,KAAK,UAAU,UAAU,QAAQ,QAAQ;AACzD,SAAK,YAAY,KAAK,UAAU,UAAU,QAAQ,SAAS;AAC3D,SAAK,eAAe,KAAK,UAAU,UAAU,QAAQ,YAAY;AACjE,SAAK,SAAS,KAAK,UAAU,UAAU,QAAQ,MAAM;AAAA,EACvD;AAAA,EAEQ,mBAAmB;AACzB,UAAM,eAAe,QAAQ,IAAI,aAAa;AAC9C,UAAM,gBAAgB,eAAe,YAAY;AACjD,SAAK,uBAAuB,KAAK,UAAU,UAAU,QAAQ,OAAO;AAGpE,SAAK,kBAAkB,KAAK,UAAU,GAAG,aAAa,GAAG,UAAU,QAAQ,OAAO,EAAE;AACpF,SAAK,uBAAuB,KAAK,UAAU,GAAG,aAAa,GAAG,UAAU,QAAQ,OAAO,EAAE;AACzF,SAAK,oBAAoB,KAAK,UAAU,UAAU,QAAQ,SAAS;AACnE,SAAK,sBAAsB,KAAK,UAAU,UAAU,QAAQ,MAAM;AAAA,EACpE;AAAA,EAEQ,gBAAgB;AACtB,SAAK,SAAS,KAAK,kBAAkB;AACrC,SAAK,eAAe,KAAK,kBAAkB,QAAQ,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACrF,SAAK,WAAW,KAAK,aAAa,CAAC;AACnC,SAAK,cAAc,KAAK,aAAa,CAAC;AAAA,EACxC;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,CACpC,mBACA,YAC4B;AAC5B,SAAO,IAAI,wBAAwB,mBAAmB,OAAO;AAC/D;","names":[]}
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
const TENANT_ID = process.env.NEXT_PUBLIC_FIREBASE_TENANT_ID || "";
|
|
2
|
+
const FIREBASE_API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || "";
|
|
3
|
+
const FIREBASE_AUTH_DOMAIN = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || "";
|
|
4
|
+
const FIREBASE_PROJECT_ID = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || "";
|
|
5
|
+
const FIREBASE_STORAGE_BUCKET = process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || "";
|
|
6
|
+
const FIREBASE_MESSAGING_SENDER_ID = process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || "";
|
|
7
|
+
const FIREBASE_APP_ID = process.env.NEXT_PUBLIC_FIREBASE_APP_ID || "";
|
|
2
8
|
export {
|
|
9
|
+
FIREBASE_API_KEY,
|
|
10
|
+
FIREBASE_APP_ID,
|
|
11
|
+
FIREBASE_AUTH_DOMAIN,
|
|
12
|
+
FIREBASE_MESSAGING_SENDER_ID,
|
|
13
|
+
FIREBASE_PROJECT_ID,
|
|
14
|
+
FIREBASE_STORAGE_BUCKET,
|
|
3
15
|
TENANT_ID
|
|
4
16
|
};
|
|
5
17
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/constants.ts"],"sourcesContent":["export const TENANT_ID = process.env.NEXT_PUBLIC_FIREBASE_TENANT_ID || '';"],"mappings":"AAAO,MAAM,YAAY,QAAQ,IAAI,kCAAkC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/constants.ts"],"sourcesContent":["export const TENANT_ID = process.env.NEXT_PUBLIC_FIREBASE_TENANT_ID || '';\nexport const FIREBASE_API_KEY = process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '';\nexport const FIREBASE_AUTH_DOMAIN = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '';\nexport const FIREBASE_PROJECT_ID = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '';\nexport const FIREBASE_STORAGE_BUCKET = process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '';\nexport const FIREBASE_MESSAGING_SENDER_ID = process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '';\nexport const FIREBASE_APP_ID = process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '';"],"mappings":"AAAO,MAAM,YAAY,QAAQ,IAAI,kCAAkC;AAChE,MAAM,mBAAmB,QAAQ,IAAI,gCAAgC;AACrE,MAAM,uBAAuB,QAAQ,IAAI,oCAAoC;AAC7E,MAAM,sBAAsB,QAAQ,IAAI,mCAAmC;AAC3E,MAAM,0BAA0B,QAAQ,IAAI,uCAAuC;AACnF,MAAM,+BAA+B,QAAQ,IAAI,4CAA4C;AAC7F,MAAM,kBAAkB,QAAQ,IAAI,+BAA+B;","names":[]}
|
|
@@ -1,36 +1,35 @@
|
|
|
1
1
|
import { createApiErrorResponse } from "./responses";
|
|
2
|
-
import {
|
|
2
|
+
import { sessionEndpointHandler } from "./sessionHandlers";
|
|
3
3
|
class SessionsHandler {
|
|
4
4
|
canHandle(endpoint) {
|
|
5
5
|
return endpoint === "sessions";
|
|
6
6
|
}
|
|
7
|
-
async handle(
|
|
8
|
-
|
|
9
|
-
return await SessionEndpointHandler.handle(request, method, subEndpoint, config);
|
|
7
|
+
async handle(context, config) {
|
|
8
|
+
return await sessionEndpointHandler(context, config);
|
|
10
9
|
}
|
|
11
10
|
}
|
|
12
11
|
class UsersHandler {
|
|
13
12
|
canHandle(endpoint) {
|
|
14
13
|
return endpoint === "users";
|
|
15
14
|
}
|
|
16
|
-
handle(
|
|
15
|
+
handle(_context, _config) {
|
|
17
16
|
return Promise.resolve(
|
|
18
17
|
createApiErrorResponse("ENDPOINT_NOT_IMPLEMENTED", "Users endpoint not implemented", 501)
|
|
19
18
|
);
|
|
20
19
|
}
|
|
21
20
|
}
|
|
22
21
|
class EndpointRouter {
|
|
23
|
-
static handlers = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
static handlers = [new SessionsHandler(), new UsersHandler()];
|
|
23
|
+
static async route(context, config) {
|
|
24
|
+
const { endpoint } = context;
|
|
25
|
+
if (!endpoint) {
|
|
26
|
+
return createApiErrorResponse("ENDPOINT_REQUIRED", "Endpoint is required", 400);
|
|
27
|
+
}
|
|
29
28
|
const handler = this.handlers.find((h) => h.canHandle(endpoint));
|
|
30
29
|
if (!handler) {
|
|
31
30
|
return createApiErrorResponse("ENDPOINT_NOT_FOUND", "Endpoint not found", 404);
|
|
32
31
|
}
|
|
33
|
-
return handler.handle(
|
|
32
|
+
return handler.handle(context, config);
|
|
34
33
|
}
|
|
35
34
|
static addHandler(handler) {
|
|
36
35
|
this.handlers.push(handler);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/endpointRouter.ts"],"sourcesContent":["import type { RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createApiErrorResponse } from './responses';\nimport { sessionEndpointHandler } from './sessionHandlers';\nimport type { AuthEndpoint, TernSecureHandlerOptions } from './types';\n\nexport interface EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean;\n handle(context: RequestProcessorContext, config: TernSecureHandlerOptions): Promise<Response>;\n}\n\nclass SessionsHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'sessions';\n }\n\n async handle(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n return await sessionEndpointHandler(context, config);\n }\n}\n\nclass UsersHandler implements EndpointHandler {\n canHandle(endpoint: AuthEndpoint): boolean {\n return endpoint === 'users';\n }\n\n handle(_context: RequestProcessorContext, _config: TernSecureHandlerOptions): Promise<Response> {\n return Promise.resolve(\n createApiErrorResponse('ENDPOINT_NOT_IMPLEMENTED', 'Users endpoint not implemented', 501),\n );\n }\n}\n\nexport class EndpointRouter {\n private static readonly handlers: EndpointHandler[] = [new SessionsHandler(), new UsersHandler()];\n\n static async route(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n ): Promise<Response> {\n const { endpoint } = context;\n\n if (!endpoint) {\n return createApiErrorResponse('ENDPOINT_REQUIRED', 'Endpoint is required', 400);\n }\n\n const handler = this.handlers.find(h => h.canHandle(endpoint));\n\n if (!handler) {\n return createApiErrorResponse('ENDPOINT_NOT_FOUND', 'Endpoint not found', 404);\n }\n\n return handler.handle(context, config);\n }\n\n static addHandler(handler: EndpointHandler): void {\n this.handlers.push(handler);\n }\n\n static removeHandler(predicate: (handler: EndpointHandler) => boolean): void {\n const index = this.handlers.findIndex(predicate);\n if (index > -1) {\n this.handlers.splice(index, 1);\n }\n }\n}\n"],"mappings":"AACA,SAAS,8BAA8B;AACvC,SAAS,8BAA8B;AAQvC,MAAM,gBAA2C;AAAA,EAC/C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,MAAM,OACJ,SACA,QACmB;AACnB,WAAO,MAAM,uBAAuB,SAAS,MAAM;AAAA,EACrD;AACF;AAEA,MAAM,aAAwC;AAAA,EAC5C,UAAU,UAAiC;AACzC,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,OAAO,UAAmC,SAAsD;AAC9F,WAAO,QAAQ;AAAA,MACb,uBAAuB,4BAA4B,kCAAkC,GAAG;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,MAAM,eAAe;AAAA,EAC1B,OAAwB,WAA8B,CAAC,IAAI,gBAAgB,GAAG,IAAI,aAAa,CAAC;AAAA,EAEhG,aAAa,MACX,SACA,QACmB;AACnB,UAAM,EAAE,SAAS,IAAI;AAErB,QAAI,CAAC,UAAU;AACb,aAAO,uBAAuB,qBAAqB,wBAAwB,GAAG;AAAA,IAChF;AAEA,UAAM,UAAU,KAAK,SAAS,KAAK,OAAK,EAAE,UAAU,QAAQ,CAAC;AAE7D,QAAI,CAAC,SAAS;AACZ,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO,QAAQ,OAAO,SAAS,MAAM;AAAA,EACvC;AAAA,EAEA,OAAO,WAAW,SAAgC;AAChD,SAAK,SAAS,KAAK,OAAO;AAAA,EAC5B;AAAA,EAEA,OAAO,cAAc,WAAwD;AAC3E,UAAM,QAAQ,KAAK,SAAS,UAAU,SAAS;AAC/C,QAAI,QAAQ,IAAI;AACd,WAAK,SAAS,OAAO,OAAO,CAAC;AAAA,IAC/B;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
import { cookies } from "next/headers";
|
|
2
2
|
import { createApiErrorResponse } from "./responses";
|
|
3
|
-
function createRequestContext(request) {
|
|
4
|
-
const url = new URL(request.url);
|
|
5
|
-
const pathSegments = url.pathname.split("/").filter(Boolean);
|
|
6
|
-
return {
|
|
7
|
-
request,
|
|
8
|
-
origin: request.headers.get("origin"),
|
|
9
|
-
host: request.headers.get("host"),
|
|
10
|
-
referer: request.headers.get("referer"),
|
|
11
|
-
userAgent: request.headers.get("user-agent") || "",
|
|
12
|
-
method: request.method,
|
|
13
|
-
pathSegments
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
3
|
function createValidators(context) {
|
|
17
|
-
const {
|
|
4
|
+
const { origin, host, referrer, userAgent, method, pathSegments } = context;
|
|
5
|
+
const request = context.request;
|
|
18
6
|
async function validateCors(corsOptions) {
|
|
19
7
|
if (corsOptions.skipSameOrigin) {
|
|
20
8
|
if (!origin || host && origin.includes(host)) {
|
|
@@ -69,13 +57,13 @@ function createValidators(context) {
|
|
|
69
57
|
}
|
|
70
58
|
function validateCsrf(securityOptions) {
|
|
71
59
|
if (securityOptions.requireCSRF && origin && host && !origin.includes(host)) {
|
|
72
|
-
const hasCSRFHeader = request.headers.get("x-requested-with") === "XMLHttpRequest";
|
|
73
|
-
const hasValidReferer =
|
|
60
|
+
const hasCSRFHeader = context.request.headers.get("x-requested-with") === "XMLHttpRequest";
|
|
61
|
+
const hasValidReferer = referrer && host && referrer.includes(host);
|
|
74
62
|
if (!hasCSRFHeader && !hasValidReferer) {
|
|
75
|
-
const
|
|
76
|
-
(allowedRef) =>
|
|
63
|
+
const isAllowedReferrer = securityOptions.allowedReferers?.some(
|
|
64
|
+
(allowedRef) => referrer?.includes(allowedRef)
|
|
77
65
|
);
|
|
78
|
-
if (!
|
|
66
|
+
if (!isAllowedReferrer) {
|
|
79
67
|
return createApiErrorResponse("CSRF_PROTECTION", "Access denied", 403);
|
|
80
68
|
}
|
|
81
69
|
}
|
|
@@ -85,7 +73,7 @@ function createValidators(context) {
|
|
|
85
73
|
function validateRequiredHeaders(securityOptions) {
|
|
86
74
|
if (securityOptions.requiredHeaders) {
|
|
87
75
|
for (const [headerName, expectedValue] of Object.entries(securityOptions.requiredHeaders)) {
|
|
88
|
-
const actualValue = request.headers.get(headerName);
|
|
76
|
+
const actualValue = context.request.headers.get(headerName);
|
|
89
77
|
if (actualValue !== expectedValue) {
|
|
90
78
|
return createApiErrorResponse(
|
|
91
79
|
"INVALID_HEADERS",
|
|
@@ -100,7 +88,7 @@ function createValidators(context) {
|
|
|
100
88
|
function validateUserAgent(securityOptions) {
|
|
101
89
|
if (securityOptions.userAgent?.block?.length) {
|
|
102
90
|
const isBlocked = securityOptions.userAgent.block.some(
|
|
103
|
-
(blocked) =>
|
|
91
|
+
(blocked) => context.request.headers.get("user-agent")?.toLowerCase().includes(blocked.toLowerCase())
|
|
104
92
|
);
|
|
105
93
|
if (isBlocked) {
|
|
106
94
|
return createApiErrorResponse("USER_AGENT_BLOCKED", "Access denied", 403);
|
|
@@ -108,7 +96,7 @@ function createValidators(context) {
|
|
|
108
96
|
}
|
|
109
97
|
if (securityOptions.userAgent?.allow?.length) {
|
|
110
98
|
const isAllowed = securityOptions.userAgent.allow.some(
|
|
111
|
-
(allowed) =>
|
|
99
|
+
(allowed) => request.headers.get("user-agent")?.toLowerCase().includes(allowed.toLowerCase())
|
|
112
100
|
);
|
|
113
101
|
if (!isAllowed) {
|
|
114
102
|
return createApiErrorResponse("USER_AGENT_NOT_ALLOWED", "Access denied", 403);
|
|
@@ -265,7 +253,6 @@ function createValidators(context) {
|
|
|
265
253
|
};
|
|
266
254
|
}
|
|
267
255
|
export {
|
|
268
|
-
createRequestContext,
|
|
269
256
|
createValidators
|
|
270
257
|
};
|
|
271
258
|
//# sourceMappingURL=fnValidators.js.map
|
|
@@ -1 +1 @@
|
|
|
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":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/fnValidators.ts"],"sourcesContent":["import { cookies } from 'next/headers';\n\nimport type { RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createApiErrorResponse } from './responses';\nimport type {\n AuthEndpoint,\n ComprehensiveValidationResult,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionSubEndpoint,\n ValidationConfig,\n} from './types';\n\n/**\n * Main validators factory function\n * Returns an object containing all validator functions and utilities\n */\nexport function createValidators(context: RequestProcessorContext) {\n const { origin, host, referrer, userAgent, method, pathSegments } = context;\n const request = context.request;\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 = context.request.headers.get('x-requested-with') === 'XMLHttpRequest';\n const hasValidReferer = referrer && host && referrer.includes(host);\n\n if (!hasCSRFHeader && !hasValidReferer) {\n const isAllowedReferrer = securityOptions.allowedReferers?.some((allowedRef: string) =>\n referrer?.includes(allowedRef),\n );\n\n if (!isAllowedReferrer) {\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 = context.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 context.request.headers.get('user-agent')?.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 request.headers.get('user-agent')?.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":"AAAA,SAAS,eAAe;AAGxB,SAAS,8BAA8B;AAehC,SAAS,iBAAiB,SAAkC;AACjE,QAAM,EAAE,QAAQ,MAAM,UAAU,WAAW,QAAQ,aAAa,IAAI;AACpE,QAAM,UAAU,QAAQ;AAExB,iBAAe,aAAa,aAAoD;AAC9E,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,eAAO,uBAAuB,2BAA2B,sBAAsB,GAAG;AAAA,MACpF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,0BAA0B,aAAoC;AACrE,UAAM,WAAW,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAEnD,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,iBAA4D;AAC1F,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,iBAAmD;AACvE,QAAI,gBAAgB,eAAe,UAAU,QAAQ,CAAC,OAAO,SAAS,IAAI,GAAG;AAC3E,YAAM,gBAAgB,QAAQ,QAAQ,QAAQ,IAAI,kBAAkB,MAAM;AAC1E,YAAM,kBAAkB,YAAY,QAAQ,SAAS,SAAS,IAAI;AAElE,UAAI,CAAC,iBAAiB,CAAC,iBAAiB;AACtC,cAAM,oBAAoB,gBAAgB,iBAAiB;AAAA,UAAK,CAAC,eAC/D,UAAU,SAAS,UAAU;AAAA,QAC/B;AAEA,YAAI,CAAC,mBAAmB;AACtB,iBAAO,uBAAuB,mBAAmB,iBAAiB,GAAG;AAAA,QACvE;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,wBAAwB,iBAAmD;AAClF,QAAI,gBAAgB,iBAAiB;AACnC,iBAAW,CAAC,YAAY,aAAa,KAAK,OAAO,QAAQ,gBAAgB,eAAe,GAAG;AACzF,cAAM,cAAc,QAAQ,QAAQ,QAAQ,IAAI,UAAU;AAC1D,YAAI,gBAAgB,eAAe;AACjC,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,kBAAkB,iBAAmD;AAC5E,QAAI,gBAAgB,WAAW,OAAO,QAAQ;AAC5C,YAAM,YAAY,gBAAgB,UAAU,MAAM;AAAA,QAAK,CAAC,YACtD,QAAQ,QAAQ,QAAQ,IAAI,YAAY,GAAG,YAAY,EAAE,SAAS,QAAQ,YAAY,CAAC;AAAA,MACzF;AAEA,UAAI,WAAW;AACb,eAAO,uBAAuB,sBAAsB,iBAAiB,GAAG;AAAA,MAC1E;AAAA,IACF;AAEA,QAAI,gBAAgB,WAAW,OAAO,QAAQ;AAC5C,YAAM,YAAY,gBAAgB,UAAU,MAAM;AAAA,QAAK,CAAC,YACtD,QAAQ,QAAQ,IAAI,YAAY,GAAG,YAAY,EAAE,SAAS,QAAQ,YAAY,CAAC;AAAA,MACjF;AAEA,UAAI,CAAC,WAAW;AACd,eAAO,uBAAuB,0BAA0B,iBAAiB,GAAG;AAAA,MAC9E;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,kBACP,WACA,iBACiB;AACjB,QAAI,CAAC,WAAW;AACd,aAAO,uBAAuB,sBAAsB,0BAA0B,GAAG;AAAA,IACnF;AAEA,QAAI,CAAC,iBAAiB;AACpB,aAAO,uBAAuB,uBAAuB,+BAA+B,GAAG;AAAA,IACzF;AAEA,QAAI,cAAc,iBAAiB;AACjC,aAAO,uBAAuB,uBAAuB,uBAAuB,GAAG;AAAA,IACjF;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,wBAAyC;AAChD,QAAI,aAAa,SAAS,GAAG;AAC3B,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,WAAS,iBACP,WACA,gBACiB;AACjB,QAAI,CAAC,kBAAkB,CAAC,eAAe,SAAS;AAC9C,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,QAAI,WAAW,aAAa,CAAC,eAAe,QAAQ,SAAS,MAAa,GAAG;AAC3E,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,WAAO;AAAA,EACT;AAEA,WAAS,oBACP,aACA,mBACiB;AACjB,QAAI,CAAC,aAAa;AAChB,aAAO,uBAAuB,yBAAyB,iCAAiC,GAAG;AAAA,IAC7F;AAEA,QAAI,CAAC,qBAAqB,CAAC,kBAAkB,SAAS;AACpD,aAAO,uBAAuB,sBAAsB,sBAAsB,GAAG;AAAA,IAC/E;AAEA,QAAI,CAAC,kBAAkB,SAAS,SAAS,MAAa,GAAG;AACvD,aAAO,uBAAuB,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,OAAO,uBAAuB,0BAA0B,0BAA0B,GAAG;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AAEA,WAAS,gBAAgB,SAA8C;AACrE,QAAI,CAAC,SAAS;AACZ,aAAO;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,cAAc,MAAM,QAAQ;AAClC,cAAM,kBAAkB,YAAY,IAAI,WAAW,GAAG;AACtD,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":[]}
|
|
@@ -8,11 +8,8 @@ import {
|
|
|
8
8
|
setNextServerToken
|
|
9
9
|
} from "./actions";
|
|
10
10
|
import { EndpointRouter } from "./endpointRouter";
|
|
11
|
-
import { RequestContextBuilder, ValidationPipeline } from "./handlerUtils";
|
|
12
11
|
export {
|
|
13
12
|
EndpointRouter,
|
|
14
|
-
RequestContextBuilder,
|
|
15
|
-
ValidationPipeline,
|
|
16
13
|
clearNextSessionCookie,
|
|
17
14
|
clearSessionCookieServer,
|
|
18
15
|
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 { EndpointRouter } from './endpointRouter'\
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { createTernSecureNextJsHandler } from './ternsecureNextjsHandler'\n\nexport {\n clearSessionCookieServer,\n clearNextSessionCookie,\n createSessionCookieServer,\n createNextSessionCookie,\n setNextServerSession,\n setNextServerToken\n} from './actions'\n\nexport { EndpointRouter } from './endpointRouter'\n\nexport type { TernSecureHandlerOptions } from './types'"],"mappings":"AAAA,SAAS,qCAAqC;AAE9C;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACG;AAEP,SAAS,sBAAsB;","names":[]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { constants } from "@tern-secure/backend";
|
|
2
|
+
import { getAuth } from "@tern-secure/backend/auth";
|
|
3
|
+
import { getCookieName, getCookiePrefix } from "@tern-secure/shared/cookie";
|
|
4
|
+
import { ternSecureBackendClient } from "../../server/ternsecureClient";
|
|
5
|
+
import {
|
|
6
|
+
FIREBASE_API_KEY,
|
|
7
|
+
FIREBASE_APP_ID,
|
|
8
|
+
FIREBASE_AUTH_DOMAIN,
|
|
9
|
+
FIREBASE_MESSAGING_SENDER_ID,
|
|
10
|
+
FIREBASE_PROJECT_ID,
|
|
11
|
+
FIREBASE_STORAGE_BUCKET
|
|
12
|
+
} from "./constants";
|
|
13
|
+
const COOKIE_OPTIONS = {
|
|
14
|
+
httpOnly: true,
|
|
15
|
+
secure: process.env.NODE_ENV === "production",
|
|
16
|
+
sameSite: "strict"
|
|
17
|
+
};
|
|
18
|
+
async function refreshCookieWithIdToken(idToken, cookieStore, options) {
|
|
19
|
+
const backendClient = await ternSecureBackendClient();
|
|
20
|
+
const authOptions = {
|
|
21
|
+
firebaseConfig: {
|
|
22
|
+
apiKey: FIREBASE_API_KEY,
|
|
23
|
+
authDomain: FIREBASE_AUTH_DOMAIN,
|
|
24
|
+
projectId: FIREBASE_PROJECT_ID,
|
|
25
|
+
storageBucket: FIREBASE_STORAGE_BUCKET,
|
|
26
|
+
messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,
|
|
27
|
+
appId: FIREBASE_APP_ID,
|
|
28
|
+
tenantId: options?.tenantId || void 0
|
|
29
|
+
},
|
|
30
|
+
apiClient: backendClient
|
|
31
|
+
};
|
|
32
|
+
const { createCustomIdAndRefreshToken } = getAuth(authOptions);
|
|
33
|
+
const customTokens = await createCustomIdAndRefreshToken(idToken);
|
|
34
|
+
const cookiePrefix = getCookiePrefix();
|
|
35
|
+
await Promise.all([
|
|
36
|
+
cookieStore.set(
|
|
37
|
+
getCookieName(constants.Cookies.IdToken, cookiePrefix),
|
|
38
|
+
customTokens.idToken,
|
|
39
|
+
COOKIE_OPTIONS
|
|
40
|
+
),
|
|
41
|
+
cookieStore.set(
|
|
42
|
+
getCookieName(constants.Cookies.Refresh, cookiePrefix),
|
|
43
|
+
customTokens.refreshToken,
|
|
44
|
+
COOKIE_OPTIONS
|
|
45
|
+
),
|
|
46
|
+
cookieStore.set(
|
|
47
|
+
getCookieName(constants.Cookies.Custom, cookiePrefix),
|
|
48
|
+
customTokens.customToken,
|
|
49
|
+
COOKIE_OPTIONS
|
|
50
|
+
)
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
refreshCookieWithIdToken
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/request.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\nimport { getAuth } from '@tern-secure/backend/auth';\nimport { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nimport { ternSecureBackendClient } from '../../server/ternsecureClient';\nimport type { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport {\n FIREBASE_API_KEY,\n FIREBASE_APP_ID,\n FIREBASE_AUTH_DOMAIN,\n FIREBASE_MESSAGING_SENDER_ID,\n FIREBASE_PROJECT_ID,\n FIREBASE_STORAGE_BUCKET,\n} from './constants';\nimport type { TernSecureHandlerOptions } from './types';\n\nconst COOKIE_OPTIONS = {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict' as const,\n};\n\nexport async function refreshCookieWithIdToken(\n idToken: string,\n cookieStore: NextCookieStore,\n options?: TernSecureHandlerOptions,\n): Promise<void> {\n const backendClient = await ternSecureBackendClient();\n const authOptions: AuthenticateRequestOptions = {\n firebaseConfig: {\n apiKey: FIREBASE_API_KEY,\n authDomain: FIREBASE_AUTH_DOMAIN,\n projectId: FIREBASE_PROJECT_ID,\n storageBucket: FIREBASE_STORAGE_BUCKET,\n messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,\n appId: FIREBASE_APP_ID,\n tenantId: options?.tenantId || undefined,\n },\n apiClient: backendClient,\n };\n\n const { createCustomIdAndRefreshToken } = getAuth(authOptions);\n\n const customTokens = await createCustomIdAndRefreshToken(idToken);\n\n const cookiePrefix = getCookiePrefix();\n\n await Promise.all([\n cookieStore.set(\n getCookieName(constants.Cookies.IdToken, cookiePrefix),\n customTokens.idToken,\n COOKIE_OPTIONS,\n ),\n cookieStore.set(\n getCookieName(constants.Cookies.Refresh, cookiePrefix),\n customTokens.refreshToken,\n COOKIE_OPTIONS,\n ),\n cookieStore.set(\n getCookieName(constants.Cookies.Custom, cookiePrefix),\n customTokens.customToken,\n COOKIE_OPTIONS,\n ),\n ]);\n}\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,eAAe,uBAAuB;AAE/C,SAAS,+BAA+B;AAExC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,MAAM,iBAAiB;AAAA,EACrB,UAAU;AAAA,EACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,EACjC,UAAU;AACZ;AAEA,eAAsB,yBACpB,SACA,aACA,SACe;AACf,QAAM,gBAAgB,MAAM,wBAAwB;AACpD,QAAM,cAA0C;AAAA,IAC9C,gBAAgB;AAAA,MACd,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,eAAe;AAAA,MACf,mBAAmB;AAAA,MACnB,OAAO;AAAA,MACP,UAAU,SAAS,YAAY;AAAA,IACjC;AAAA,IACA,WAAW;AAAA,EACb;AAEA,QAAM,EAAE,8BAA8B,IAAI,QAAQ,WAAW;AAE7D,QAAM,eAAe,MAAM,8BAA8B,OAAO;AAEhE,QAAM,eAAe,gBAAgB;AAErC,QAAM,QAAQ,IAAI;AAAA,IAChB,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,QAAQ,YAAY;AAAA,MACpD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,EACF,CAAC;AACH;","names":[]}
|