@tern-secure/nextjs 5.2.0-canary.v20251127221555 → 5.2.0-canary.v20251127235234
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/server/protect.js +2 -2
- package/dist/cjs/server/protect.js.map +1 -1
- package/dist/cjs/server/ternSecureProxy.js +4 -4
- package/dist/cjs/server/ternSecureProxy.js.map +1 -1
- package/dist/esm/server/protect.js +2 -2
- package/dist/esm/server/protect.js.map +1 -1
- package/dist/esm/server/ternSecureProxy.js +4 -4
- package/dist/esm/server/ternSecureProxy.js.map +1 -1
- package/package.json +5 -5
|
@@ -26,7 +26,7 @@ var import_constants = require("../constants");
|
|
|
26
26
|
var import_nextFetcher = require("./nextFetcher");
|
|
27
27
|
function createProtect(opts) {
|
|
28
28
|
const { redirectToSignIn, authObject, redirect, notFound, request } = opts;
|
|
29
|
-
return async (...args) => {
|
|
29
|
+
return (async (...args) => {
|
|
30
30
|
const optionValuesAsParam = args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;
|
|
31
31
|
const paramsOrFunction = optionValuesAsParam ? void 0 : args[0];
|
|
32
32
|
const unauthenticatedUrl = args[0]?.unauthenticatedUrl || args[1]?.unauthenticatedUrl;
|
|
@@ -61,7 +61,7 @@ function createProtect(opts) {
|
|
|
61
61
|
if (authObject.require(paramsOrFunction)) {
|
|
62
62
|
return authObject;
|
|
63
63
|
}
|
|
64
|
-
};
|
|
64
|
+
});
|
|
65
65
|
}
|
|
66
66
|
const isServerActionRequest = (req) => {
|
|
67
67
|
return !!req.headers.get(import_constants.constants.Headers.NextUrl) && (req.headers.get(import_backend.constants.Headers.Accept)?.includes("text/x-component") || req.headers.get(import_backend.constants.Headers.ContentType)?.includes("multipart/form-data") || !!req.headers.get(import_constants.constants.Headers.NextAction));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/protect.ts"],"sourcesContent":["import type { AuthObject, RedirectFun, SignedInAuthObject } from \"@tern-secure/backend\";\nimport { constants } from \"@tern-secure/backend\";\nimport type { CheckAuthorizationFromSessionClaims } from \"@tern-secure/types\";\n\nimport { constants as nextConstants } from \"../constants\";\nimport { isNextFetcher } from \"./nextFetcher\";\n\ntype AuthProtectOptions = {\n /**\n * The URL to redirect the user to if they are not authorized.\n */\n unauthorizedUrl?: string;\n /**\n * The URL to redirect the user to if they are not authenticated.\n */\n unauthenticatedUrl?: string;\n};\n\nexport interface AuthProtect {\n (\n params?: (require: CheckAuthorizationFromSessionClaims) => boolean,\n options?: AuthProtectOptions\n ): Promise<SignedInAuthObject>;\n (options?: AuthProtectOptions): Promise<SignedInAuthObject>;\n}\n\nexport function createProtect(opts: {\n request: Request;\n authObject: AuthObject;\n notFound: () => never;\n redirect: (url: string) => void;\n redirectToSignIn: RedirectFun<unknown>;\n}): AuthProtect {\n const { redirectToSignIn, authObject, redirect, notFound, request } = opts;\n\n return (async (...args: any[]) => {\n const optionValuesAsParam =\n args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;\n const paramsOrFunction = optionValuesAsParam ? undefined : (args[0] as \n | CheckAuthorizationFromSessionClaims\n | ((require: CheckAuthorizationFromSessionClaims) => boolean));\n const unauthenticatedUrl = (args[0]?.unauthenticatedUrl ||\n args[1]?.unauthenticatedUrl) as string | undefined;\n const unauthorizedUrl = (args[0]?.unauthorizedUrl ||\n args[1]?.unauthorizedUrl) as string | undefined;\n\n const handleUnauthenticated = () => {\n if (unauthenticatedUrl) {\n redirect(unauthenticatedUrl);\n }\n if (isPageRequest(request)) {\n return redirectToSignIn();\n }\n return notFound();\n };\n\n const handleUnauthorized = () => {\n if (unauthorizedUrl) {\n redirect(unauthorizedUrl);\n }\n notFound();\n };\n\n if (!authObject.userId) {\n handleUnauthenticated();\n }\n\n if (!paramsOrFunction) {\n return authObject;\n }\n\n if (typeof paramsOrFunction === \"function\") {\n if (paramsOrFunction(authObject.require)) {\n return authObject;\n }\n return handleUnauthorized();\n }\n\n if (authObject.require(paramsOrFunction)) {\n return authObject;\n }\n }) as AuthProtect;\n}\n\nconst isServerActionRequest = (req: Request) => {\n return (\n !!req.headers.get(nextConstants.Headers.NextUrl) &&\n (req.headers.get(constants.Headers.Accept)?.includes(\"text/x-component\") ||\n req.headers\n .get(constants.Headers.ContentType)\n ?.includes(\"multipart/form-data\") ||\n !!req.headers.get(nextConstants.Headers.NextAction))\n );\n};\n\nconst isPageRequest = (req: Request): boolean => {\n return (\n req.headers.get(constants.Headers.SecFetchDest) === \"document\" ||\n req.headers.get(constants.Headers.SecFetchDest) === \"iframe\" ||\n req.headers.get(constants.Headers.Accept)?.includes(\"text/html\") ||\n isAppRouterInternalNavigation(req) ||\n isPagesRouterInternalNavigation(req)\n );\n};\n\nconst isAppRouterInternalNavigation = (req: Request) =>\n (!!req.headers.get(nextConstants.Headers.NextUrl) &&\n !isServerActionRequest(req)) ||\n isPagePathAvailable();\n\nconst isPagePathAvailable = () => {\n const __fetch = globalThis.fetch;\n\n if (!isNextFetcher(__fetch)) {\n return false;\n }\n\n const { page, pagePath } = __fetch.__nextGetStaticStore().getStore() || {};\n\n return Boolean(\n // available on next@14\n pagePath ||\n // available on next@15\n page\n );\n};\n\nconst isPagesRouterInternalNavigation = (req: Request) =>\n !!req.headers.get(nextConstants.Headers.NextjsData);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAA0B;AAG1B,uBAA2C;AAC3C,yBAA8B;AAqBvB,SAAS,cAAc,MAMd;AACd,QAAM,EAAE,kBAAkB,YAAY,UAAU,UAAU,QAAQ,IAAI;AAEtE,
|
|
1
|
+
{"version":3,"sources":["../../../src/server/protect.ts"],"sourcesContent":["import type { AuthObject, RedirectFun, SignedInAuthObject } from \"@tern-secure/backend\";\nimport { constants } from \"@tern-secure/backend\";\nimport type { CheckAuthorizationFromSessionClaims } from \"@tern-secure/types\";\n\nimport { constants as nextConstants } from \"../constants\";\nimport { isNextFetcher } from \"./nextFetcher\";\n\ntype AuthProtectOptions = {\n /**\n * The URL to redirect the user to if they are not authorized.\n */\n unauthorizedUrl?: string;\n /**\n * The URL to redirect the user to if they are not authenticated.\n */\n unauthenticatedUrl?: string;\n};\n\nexport interface AuthProtect {\n (\n params?: (require: CheckAuthorizationFromSessionClaims) => boolean,\n options?: AuthProtectOptions\n ): Promise<SignedInAuthObject>;\n (options?: AuthProtectOptions): Promise<SignedInAuthObject>;\n}\n\nexport function createProtect(opts: {\n request: Request;\n authObject: AuthObject;\n notFound: () => never;\n redirect: (url: string) => void;\n redirectToSignIn: RedirectFun<unknown>;\n}): AuthProtect {\n const { redirectToSignIn, authObject, redirect, notFound, request } = opts;\n\n return (async (...args: any[]) => {\n const optionValuesAsParam =\n args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;\n const paramsOrFunction = optionValuesAsParam ? undefined : (args[0] as \n | CheckAuthorizationFromSessionClaims\n | ((require: CheckAuthorizationFromSessionClaims) => boolean));\n const unauthenticatedUrl = (args[0]?.unauthenticatedUrl ||\n args[1]?.unauthenticatedUrl) as string | undefined;\n const unauthorizedUrl = (args[0]?.unauthorizedUrl ||\n args[1]?.unauthorizedUrl) as string | undefined;\n\n const handleUnauthenticated = () => {\n if (unauthenticatedUrl) {\n redirect(unauthenticatedUrl);\n }\n if (isPageRequest(request)) {\n return redirectToSignIn();\n }\n return notFound();\n };\n\n const handleUnauthorized = () => {\n if (unauthorizedUrl) {\n redirect(unauthorizedUrl);\n }\n notFound();\n };\n\n if (!authObject.userId) {\n handleUnauthenticated();\n }\n\n if (!paramsOrFunction) {\n return authObject;\n }\n\n if (typeof paramsOrFunction === \"function\") {\n if (paramsOrFunction(authObject.require)) {\n return authObject;\n }\n return handleUnauthorized();\n }\n\n if (authObject.require(paramsOrFunction)) {\n return authObject;\n }\n }) as AuthProtect;\n}\n\nconst isServerActionRequest = (req: Request) => {\n return (\n !!req.headers.get(nextConstants.Headers.NextUrl) &&\n (req.headers.get(constants.Headers.Accept)?.includes(\"text/x-component\") ||\n req.headers\n .get(constants.Headers.ContentType)\n ?.includes(\"multipart/form-data\") ||\n !!req.headers.get(nextConstants.Headers.NextAction))\n );\n};\n\nconst isPageRequest = (req: Request): boolean => {\n return (\n req.headers.get(constants.Headers.SecFetchDest) === \"document\" ||\n req.headers.get(constants.Headers.SecFetchDest) === \"iframe\" ||\n req.headers.get(constants.Headers.Accept)?.includes(\"text/html\") ||\n isAppRouterInternalNavigation(req) ||\n isPagesRouterInternalNavigation(req)\n );\n};\n\nconst isAppRouterInternalNavigation = (req: Request) =>\n (!!req.headers.get(nextConstants.Headers.NextUrl) &&\n !isServerActionRequest(req)) ||\n isPagePathAvailable();\n\nconst isPagePathAvailable = () => {\n const __fetch = globalThis.fetch;\n\n if (!isNextFetcher(__fetch)) {\n return false;\n }\n\n const { page, pagePath } = __fetch.__nextGetStaticStore().getStore() || {};\n\n return Boolean(\n // available on next@14\n pagePath ||\n // available on next@15\n page\n );\n};\n\nconst isPagesRouterInternalNavigation = (req: Request) =>\n !!req.headers.get(nextConstants.Headers.NextjsData);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAA0B;AAG1B,uBAA2C;AAC3C,yBAA8B;AAqBvB,SAAS,cAAc,MAMd;AACd,QAAM,EAAE,kBAAkB,YAAY,UAAU,UAAU,QAAQ,IAAI;AAEtE,UAAQ,UAAU,SAAgB;AAChC,UAAM,sBACJ,KAAK,CAAC,GAAG,sBAAsB,KAAK,CAAC,GAAG;AAC1C,UAAM,mBAAmB,sBAAsB,SAAa,KAAK,CAAC;AAGlE,UAAM,qBAAsB,KAAK,CAAC,GAAG,sBACnC,KAAK,CAAC,GAAG;AACX,UAAM,kBAAmB,KAAK,CAAC,GAAG,mBAChC,KAAK,CAAC,GAAG;AAEX,UAAM,wBAAwB,MAAM;AAClC,UAAI,oBAAoB;AACtB,iBAAS,kBAAkB;AAAA,MAC7B;AACA,UAAI,cAAc,OAAO,GAAG;AAC1B,eAAO,iBAAiB;AAAA,MAC1B;AACA,aAAO,SAAS;AAAA,IAClB;AAEA,UAAM,qBAAqB,MAAM;AAC/B,UAAI,iBAAiB;AACnB,iBAAS,eAAe;AAAA,MAC1B;AACA,eAAS;AAAA,IACX;AAEA,QAAI,CAAC,WAAW,QAAQ;AACtB,4BAAsB;AAAA,IACxB;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,qBAAqB,YAAY;AAC1C,UAAI,iBAAiB,WAAW,OAAO,GAAG;AACxC,eAAO;AAAA,MACT;AACA,aAAO,mBAAmB;AAAA,IAC5B;AAEA,QAAI,WAAW,QAAQ,gBAAgB,GAAG;AACxC,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,wBAAwB,CAAC,QAAiB;AAC9C,SACE,CAAC,CAAC,IAAI,QAAQ,IAAI,iBAAAA,UAAc,QAAQ,OAAO,MAC9C,IAAI,QAAQ,IAAI,yBAAU,QAAQ,MAAM,GAAG,SAAS,kBAAkB,KACrE,IAAI,QACD,IAAI,yBAAU,QAAQ,WAAW,GAChC,SAAS,qBAAqB,KAClC,CAAC,CAAC,IAAI,QAAQ,IAAI,iBAAAA,UAAc,QAAQ,UAAU;AAExD;AAEA,MAAM,gBAAgB,CAAC,QAA0B;AAC/C,SACE,IAAI,QAAQ,IAAI,yBAAU,QAAQ,YAAY,MAAM,cACpD,IAAI,QAAQ,IAAI,yBAAU,QAAQ,YAAY,MAAM,YACpD,IAAI,QAAQ,IAAI,yBAAU,QAAQ,MAAM,GAAG,SAAS,WAAW,KAC/D,8BAA8B,GAAG,KACjC,gCAAgC,GAAG;AAEvC;AAEA,MAAM,gCAAgC,CAAC,QACpC,CAAC,CAAC,IAAI,QAAQ,IAAI,iBAAAA,UAAc,QAAQ,OAAO,KAC9C,CAAC,sBAAsB,GAAG,KAC5B,oBAAoB;AAEtB,MAAM,sBAAsB,MAAM;AAChC,QAAM,UAAU,WAAW;AAE3B,MAAI,KAAC,kCAAc,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,MAAM,SAAS,IAAI,QAAQ,qBAAqB,EAAE,SAAS,KAAK,CAAC;AAEzE,SAAO;AAAA;AAAA,IAEL;AAAA,IAEE;AAAA,EACJ;AACF;AAEA,MAAM,kCAAkC,CAAC,QACvC,CAAC,CAAC,IAAI,QAAQ,IAAI,iBAAAA,UAAc,QAAQ,UAAU;","names":["nextConstants"]}
|
|
@@ -32,7 +32,7 @@ var import_nextErrors = require("./nextErrors");
|
|
|
32
32
|
var import_protect = require("./protect");
|
|
33
33
|
var import_ternsecureClient = require("./ternsecureClient");
|
|
34
34
|
var import_utils = require("./utils");
|
|
35
|
-
const ternSecureProxy = (...args) => {
|
|
35
|
+
const ternSecureProxy = ((...args) => {
|
|
36
36
|
const [request, event] = parseRequestAndEvent(args);
|
|
37
37
|
const [handler, params] = parseHandlerAndOptions(args);
|
|
38
38
|
const middleware = () => {
|
|
@@ -115,7 +115,7 @@ const ternSecureProxy = (...args) => {
|
|
|
115
115
|
return nextMiddleware;
|
|
116
116
|
};
|
|
117
117
|
return middleware();
|
|
118
|
-
};
|
|
118
|
+
});
|
|
119
119
|
const parseRequestAndEvent = (args) => {
|
|
120
120
|
return [
|
|
121
121
|
args[0] instanceof Request ? args[0] : void 0,
|
|
@@ -152,7 +152,7 @@ const createMiddlewareRedirects = (ternSecureRequest) => {
|
|
|
152
152
|
return { redirectToSignIn, redirectToSignUp };
|
|
153
153
|
};
|
|
154
154
|
const createMiddlewareProtect = (ternSecureRequest, authObject, redirectToSignIn) => {
|
|
155
|
-
return async (params, options) => {
|
|
155
|
+
return (async (params, options) => {
|
|
156
156
|
const notFound = () => (0, import_navigation.notFound)();
|
|
157
157
|
const redirect = (url) => (0, import_nextErrors.nextjsRedirectError)(url, {
|
|
158
158
|
redirectUrl: url
|
|
@@ -164,7 +164,7 @@ const createMiddlewareProtect = (ternSecureRequest, authObject, redirectToSignIn
|
|
|
164
164
|
authObject,
|
|
165
165
|
redirectToSignIn
|
|
166
166
|
})(params, options);
|
|
167
|
-
};
|
|
167
|
+
});
|
|
168
168
|
};
|
|
169
169
|
const redirectAdapter = (url) => {
|
|
170
170
|
return import_server.NextResponse.redirect(url, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/ternSecureProxy.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n RedirectFun,\r\n RequestState,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { AuthStatus, constants, createRedirect, createTernSecureRequest } from '@tern-secure/backend';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware, NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { FIREBASE_API_KEY, FIREBASE_APP_ID, FIREBASE_PROJECT_ID,SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect, createProtect } from './protect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends AuthenticateRequestOptions {\r\n debug?: boolean;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureProxy = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n const apiKey = resolvedParams.apiKey || FIREBASE_API_KEY;\r\n const appId = FIREBASE_APP_ID;\r\n const projectId = FIREBASE_PROJECT_ID;\r\n const firebaseConfig = resolvedParams.firebaseConfig || {\r\n apiKey,\r\n appId,\r\n projectId,\r\n }\r\n const firebaseAdminConfig = resolvedParams.firebaseAdminConfig;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n apiKey,\r\n firebaseConfig,\r\n firebaseAdminConfig,\r\n ...resolvedParams,\r\n };\r\n\r\n const reqBackendClient = await ternSecureBackendClient();\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const locationHeader = requestStateClient.headers.get(constants.Headers.Location);\r\n const appCheckToken = requestStateClient.headers.get(constants.Headers.AppCheckToken);\r\n console.log(\"[ternSecureProxy] App Check Token in Proxy:\", appCheckToken);\r\n if (locationHeader) {\r\n return new Response(null, {\r\n status: 307,\r\n headers: requestStateClient.headers,\r\n });\r\n } else if (requestStateClient.status === AuthStatus.Handshake) {\r\n throw new Error('TernSecure: handshake status without redirect is not supported.');\r\n }\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const redirectToSignIn = createProxyRedirectToSignIn(ternSecureRequest);\r\n const redirectToSignUp = createProxyRedirectToSignUp(ternSecureRequest);\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request, requestStateClient);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient, appCheckToken || undefined);\r\n return handlerResult;\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\n\r\nconst createProxyRedirectToSignIn = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignIn'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\nconst createProxyRedirectToSignUp = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignUp'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\n/**\r\n * Create middleware redirect functions\r\n * @deprecated\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n requestState: RequestState,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: requestState.signInUrl,\r\n signUpUrl: requestState.signUpUrl,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n"],"mappings":"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","names":["request","event","nextjsNotFound"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ternSecureProxy.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n RedirectFun,\r\n RequestState,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { AuthStatus, constants, createRedirect, createTernSecureRequest } from '@tern-secure/backend';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware, NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { FIREBASE_API_KEY, FIREBASE_APP_ID, FIREBASE_PROJECT_ID,SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect, createProtect } from './protect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends AuthenticateRequestOptions {\r\n debug?: boolean;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureProxy = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n const apiKey = resolvedParams.apiKey || FIREBASE_API_KEY;\r\n const appId = FIREBASE_APP_ID;\r\n const projectId = FIREBASE_PROJECT_ID;\r\n const firebaseConfig = resolvedParams.firebaseConfig || {\r\n apiKey,\r\n appId,\r\n projectId,\r\n }\r\n const firebaseAdminConfig = resolvedParams.firebaseAdminConfig;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n apiKey,\r\n firebaseConfig,\r\n firebaseAdminConfig,\r\n ...resolvedParams,\r\n };\r\n\r\n const reqBackendClient = await ternSecureBackendClient();\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const locationHeader = requestStateClient.headers.get(constants.Headers.Location);\r\n const appCheckToken = requestStateClient.headers.get(constants.Headers.AppCheckToken);\r\n console.log(\"[ternSecureProxy] App Check Token in Proxy:\", appCheckToken);\r\n if (locationHeader) {\r\n return new Response(null, {\r\n status: 307,\r\n headers: requestStateClient.headers,\r\n });\r\n } else if (requestStateClient.status === AuthStatus.Handshake) {\r\n throw new Error('TernSecure: handshake status without redirect is not supported.');\r\n }\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const redirectToSignIn = createProxyRedirectToSignIn(ternSecureRequest);\r\n const redirectToSignUp = createProxyRedirectToSignUp(ternSecureRequest);\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request, requestStateClient);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient, appCheckToken || undefined);\r\n return handlerResult;\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\n\r\nconst createProxyRedirectToSignIn = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignIn'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\nconst createProxyRedirectToSignUp = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignUp'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\n/**\r\n * Create middleware redirect functions\r\n * @deprecated\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n requestState: RequestState,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: requestState.signInUrl,\r\n signUpUrl: requestState.signUpUrl,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n"],"mappings":"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","names":["request","event","nextjsNotFound"]}
|
|
@@ -3,7 +3,7 @@ import { constants as nextConstants } from "../constants";
|
|
|
3
3
|
import { isNextFetcher } from "./nextFetcher";
|
|
4
4
|
function createProtect(opts) {
|
|
5
5
|
const { redirectToSignIn, authObject, redirect, notFound, request } = opts;
|
|
6
|
-
return async (...args) => {
|
|
6
|
+
return (async (...args) => {
|
|
7
7
|
const optionValuesAsParam = args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;
|
|
8
8
|
const paramsOrFunction = optionValuesAsParam ? void 0 : args[0];
|
|
9
9
|
const unauthenticatedUrl = args[0]?.unauthenticatedUrl || args[1]?.unauthenticatedUrl;
|
|
@@ -38,7 +38,7 @@ function createProtect(opts) {
|
|
|
38
38
|
if (authObject.require(paramsOrFunction)) {
|
|
39
39
|
return authObject;
|
|
40
40
|
}
|
|
41
|
-
};
|
|
41
|
+
});
|
|
42
42
|
}
|
|
43
43
|
const isServerActionRequest = (req) => {
|
|
44
44
|
return !!req.headers.get(nextConstants.Headers.NextUrl) && (req.headers.get(constants.Headers.Accept)?.includes("text/x-component") || req.headers.get(constants.Headers.ContentType)?.includes("multipart/form-data") || !!req.headers.get(nextConstants.Headers.NextAction));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/protect.ts"],"sourcesContent":["import type { AuthObject, RedirectFun, SignedInAuthObject } from \"@tern-secure/backend\";\nimport { constants } from \"@tern-secure/backend\";\nimport type { CheckAuthorizationFromSessionClaims } from \"@tern-secure/types\";\n\nimport { constants as nextConstants } from \"../constants\";\nimport { isNextFetcher } from \"./nextFetcher\";\n\ntype AuthProtectOptions = {\n /**\n * The URL to redirect the user to if they are not authorized.\n */\n unauthorizedUrl?: string;\n /**\n * The URL to redirect the user to if they are not authenticated.\n */\n unauthenticatedUrl?: string;\n};\n\nexport interface AuthProtect {\n (\n params?: (require: CheckAuthorizationFromSessionClaims) => boolean,\n options?: AuthProtectOptions\n ): Promise<SignedInAuthObject>;\n (options?: AuthProtectOptions): Promise<SignedInAuthObject>;\n}\n\nexport function createProtect(opts: {\n request: Request;\n authObject: AuthObject;\n notFound: () => never;\n redirect: (url: string) => void;\n redirectToSignIn: RedirectFun<unknown>;\n}): AuthProtect {\n const { redirectToSignIn, authObject, redirect, notFound, request } = opts;\n\n return (async (...args: any[]) => {\n const optionValuesAsParam =\n args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;\n const paramsOrFunction = optionValuesAsParam ? undefined : (args[0] as \n | CheckAuthorizationFromSessionClaims\n | ((require: CheckAuthorizationFromSessionClaims) => boolean));\n const unauthenticatedUrl = (args[0]?.unauthenticatedUrl ||\n args[1]?.unauthenticatedUrl) as string | undefined;\n const unauthorizedUrl = (args[0]?.unauthorizedUrl ||\n args[1]?.unauthorizedUrl) as string | undefined;\n\n const handleUnauthenticated = () => {\n if (unauthenticatedUrl) {\n redirect(unauthenticatedUrl);\n }\n if (isPageRequest(request)) {\n return redirectToSignIn();\n }\n return notFound();\n };\n\n const handleUnauthorized = () => {\n if (unauthorizedUrl) {\n redirect(unauthorizedUrl);\n }\n notFound();\n };\n\n if (!authObject.userId) {\n handleUnauthenticated();\n }\n\n if (!paramsOrFunction) {\n return authObject;\n }\n\n if (typeof paramsOrFunction === \"function\") {\n if (paramsOrFunction(authObject.require)) {\n return authObject;\n }\n return handleUnauthorized();\n }\n\n if (authObject.require(paramsOrFunction)) {\n return authObject;\n }\n }) as AuthProtect;\n}\n\nconst isServerActionRequest = (req: Request) => {\n return (\n !!req.headers.get(nextConstants.Headers.NextUrl) &&\n (req.headers.get(constants.Headers.Accept)?.includes(\"text/x-component\") ||\n req.headers\n .get(constants.Headers.ContentType)\n ?.includes(\"multipart/form-data\") ||\n !!req.headers.get(nextConstants.Headers.NextAction))\n );\n};\n\nconst isPageRequest = (req: Request): boolean => {\n return (\n req.headers.get(constants.Headers.SecFetchDest) === \"document\" ||\n req.headers.get(constants.Headers.SecFetchDest) === \"iframe\" ||\n req.headers.get(constants.Headers.Accept)?.includes(\"text/html\") ||\n isAppRouterInternalNavigation(req) ||\n isPagesRouterInternalNavigation(req)\n );\n};\n\nconst isAppRouterInternalNavigation = (req: Request) =>\n (!!req.headers.get(nextConstants.Headers.NextUrl) &&\n !isServerActionRequest(req)) ||\n isPagePathAvailable();\n\nconst isPagePathAvailable = () => {\n const __fetch = globalThis.fetch;\n\n if (!isNextFetcher(__fetch)) {\n return false;\n }\n\n const { page, pagePath } = __fetch.__nextGetStaticStore().getStore() || {};\n\n return Boolean(\n // available on next@14\n pagePath ||\n // available on next@15\n page\n );\n};\n\nconst isPagesRouterInternalNavigation = (req: Request) =>\n !!req.headers.get(nextConstants.Headers.NextjsData);\n"],"mappings":"AACA,SAAS,iBAAiB;AAG1B,SAAS,aAAa,qBAAqB;AAC3C,SAAS,qBAAqB;AAqBvB,SAAS,cAAc,MAMd;AACd,QAAM,EAAE,kBAAkB,YAAY,UAAU,UAAU,QAAQ,IAAI;AAEtE,
|
|
1
|
+
{"version":3,"sources":["../../../src/server/protect.ts"],"sourcesContent":["import type { AuthObject, RedirectFun, SignedInAuthObject } from \"@tern-secure/backend\";\nimport { constants } from \"@tern-secure/backend\";\nimport type { CheckAuthorizationFromSessionClaims } from \"@tern-secure/types\";\n\nimport { constants as nextConstants } from \"../constants\";\nimport { isNextFetcher } from \"./nextFetcher\";\n\ntype AuthProtectOptions = {\n /**\n * The URL to redirect the user to if they are not authorized.\n */\n unauthorizedUrl?: string;\n /**\n * The URL to redirect the user to if they are not authenticated.\n */\n unauthenticatedUrl?: string;\n};\n\nexport interface AuthProtect {\n (\n params?: (require: CheckAuthorizationFromSessionClaims) => boolean,\n options?: AuthProtectOptions\n ): Promise<SignedInAuthObject>;\n (options?: AuthProtectOptions): Promise<SignedInAuthObject>;\n}\n\nexport function createProtect(opts: {\n request: Request;\n authObject: AuthObject;\n notFound: () => never;\n redirect: (url: string) => void;\n redirectToSignIn: RedirectFun<unknown>;\n}): AuthProtect {\n const { redirectToSignIn, authObject, redirect, notFound, request } = opts;\n\n return (async (...args: any[]) => {\n const optionValuesAsParam =\n args[0]?.unauthenticatedUrl || args[0]?.unauthorizedUrl;\n const paramsOrFunction = optionValuesAsParam ? undefined : (args[0] as \n | CheckAuthorizationFromSessionClaims\n | ((require: CheckAuthorizationFromSessionClaims) => boolean));\n const unauthenticatedUrl = (args[0]?.unauthenticatedUrl ||\n args[1]?.unauthenticatedUrl) as string | undefined;\n const unauthorizedUrl = (args[0]?.unauthorizedUrl ||\n args[1]?.unauthorizedUrl) as string | undefined;\n\n const handleUnauthenticated = () => {\n if (unauthenticatedUrl) {\n redirect(unauthenticatedUrl);\n }\n if (isPageRequest(request)) {\n return redirectToSignIn();\n }\n return notFound();\n };\n\n const handleUnauthorized = () => {\n if (unauthorizedUrl) {\n redirect(unauthorizedUrl);\n }\n notFound();\n };\n\n if (!authObject.userId) {\n handleUnauthenticated();\n }\n\n if (!paramsOrFunction) {\n return authObject;\n }\n\n if (typeof paramsOrFunction === \"function\") {\n if (paramsOrFunction(authObject.require)) {\n return authObject;\n }\n return handleUnauthorized();\n }\n\n if (authObject.require(paramsOrFunction)) {\n return authObject;\n }\n }) as AuthProtect;\n}\n\nconst isServerActionRequest = (req: Request) => {\n return (\n !!req.headers.get(nextConstants.Headers.NextUrl) &&\n (req.headers.get(constants.Headers.Accept)?.includes(\"text/x-component\") ||\n req.headers\n .get(constants.Headers.ContentType)\n ?.includes(\"multipart/form-data\") ||\n !!req.headers.get(nextConstants.Headers.NextAction))\n );\n};\n\nconst isPageRequest = (req: Request): boolean => {\n return (\n req.headers.get(constants.Headers.SecFetchDest) === \"document\" ||\n req.headers.get(constants.Headers.SecFetchDest) === \"iframe\" ||\n req.headers.get(constants.Headers.Accept)?.includes(\"text/html\") ||\n isAppRouterInternalNavigation(req) ||\n isPagesRouterInternalNavigation(req)\n );\n};\n\nconst isAppRouterInternalNavigation = (req: Request) =>\n (!!req.headers.get(nextConstants.Headers.NextUrl) &&\n !isServerActionRequest(req)) ||\n isPagePathAvailable();\n\nconst isPagePathAvailable = () => {\n const __fetch = globalThis.fetch;\n\n if (!isNextFetcher(__fetch)) {\n return false;\n }\n\n const { page, pagePath } = __fetch.__nextGetStaticStore().getStore() || {};\n\n return Boolean(\n // available on next@14\n pagePath ||\n // available on next@15\n page\n );\n};\n\nconst isPagesRouterInternalNavigation = (req: Request) =>\n !!req.headers.get(nextConstants.Headers.NextjsData);\n"],"mappings":"AACA,SAAS,iBAAiB;AAG1B,SAAS,aAAa,qBAAqB;AAC3C,SAAS,qBAAqB;AAqBvB,SAAS,cAAc,MAMd;AACd,QAAM,EAAE,kBAAkB,YAAY,UAAU,UAAU,QAAQ,IAAI;AAEtE,UAAQ,UAAU,SAAgB;AAChC,UAAM,sBACJ,KAAK,CAAC,GAAG,sBAAsB,KAAK,CAAC,GAAG;AAC1C,UAAM,mBAAmB,sBAAsB,SAAa,KAAK,CAAC;AAGlE,UAAM,qBAAsB,KAAK,CAAC,GAAG,sBACnC,KAAK,CAAC,GAAG;AACX,UAAM,kBAAmB,KAAK,CAAC,GAAG,mBAChC,KAAK,CAAC,GAAG;AAEX,UAAM,wBAAwB,MAAM;AAClC,UAAI,oBAAoB;AACtB,iBAAS,kBAAkB;AAAA,MAC7B;AACA,UAAI,cAAc,OAAO,GAAG;AAC1B,eAAO,iBAAiB;AAAA,MAC1B;AACA,aAAO,SAAS;AAAA,IAClB;AAEA,UAAM,qBAAqB,MAAM;AAC/B,UAAI,iBAAiB;AACnB,iBAAS,eAAe;AAAA,MAC1B;AACA,eAAS;AAAA,IACX;AAEA,QAAI,CAAC,WAAW,QAAQ;AACtB,4BAAsB;AAAA,IACxB;AAEA,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,qBAAqB,YAAY;AAC1C,UAAI,iBAAiB,WAAW,OAAO,GAAG;AACxC,eAAO;AAAA,MACT;AACA,aAAO,mBAAmB;AAAA,IAC5B;AAEA,QAAI,WAAW,QAAQ,gBAAgB,GAAG;AACxC,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,MAAM,wBAAwB,CAAC,QAAiB;AAC9C,SACE,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,OAAO,MAC9C,IAAI,QAAQ,IAAI,UAAU,QAAQ,MAAM,GAAG,SAAS,kBAAkB,KACrE,IAAI,QACD,IAAI,UAAU,QAAQ,WAAW,GAChC,SAAS,qBAAqB,KAClC,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,UAAU;AAExD;AAEA,MAAM,gBAAgB,CAAC,QAA0B;AAC/C,SACE,IAAI,QAAQ,IAAI,UAAU,QAAQ,YAAY,MAAM,cACpD,IAAI,QAAQ,IAAI,UAAU,QAAQ,YAAY,MAAM,YACpD,IAAI,QAAQ,IAAI,UAAU,QAAQ,MAAM,GAAG,SAAS,WAAW,KAC/D,8BAA8B,GAAG,KACjC,gCAAgC,GAAG;AAEvC;AAEA,MAAM,gCAAgC,CAAC,QACpC,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,OAAO,KAC9C,CAAC,sBAAsB,GAAG,KAC5B,oBAAoB;AAEtB,MAAM,sBAAsB,MAAM;AAChC,QAAM,UAAU,WAAW;AAE3B,MAAI,CAAC,cAAc,OAAO,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,MAAM,SAAS,IAAI,QAAQ,qBAAqB,EAAE,SAAS,KAAK,CAAC;AAEzE,SAAO;AAAA;AAAA,IAEL;AAAA,IAEE;AAAA,EACJ;AACF;AAEA,MAAM,kCAAkC,CAAC,QACvC,CAAC,CAAC,IAAI,QAAQ,IAAI,cAAc,QAAQ,UAAU;","names":[]}
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import { createProtect } from "./protect";
|
|
17
17
|
import { ternSecureBackendClient } from "./ternsecureClient";
|
|
18
18
|
import { decorateRequest } from "./utils";
|
|
19
|
-
const ternSecureProxy = (...args) => {
|
|
19
|
+
const ternSecureProxy = ((...args) => {
|
|
20
20
|
const [request, event] = parseRequestAndEvent(args);
|
|
21
21
|
const [handler, params] = parseHandlerAndOptions(args);
|
|
22
22
|
const middleware = () => {
|
|
@@ -99,7 +99,7 @@ const ternSecureProxy = (...args) => {
|
|
|
99
99
|
return nextMiddleware;
|
|
100
100
|
};
|
|
101
101
|
return middleware();
|
|
102
|
-
};
|
|
102
|
+
});
|
|
103
103
|
const parseRequestAndEvent = (args) => {
|
|
104
104
|
return [
|
|
105
105
|
args[0] instanceof Request ? args[0] : void 0,
|
|
@@ -136,7 +136,7 @@ const createMiddlewareRedirects = (ternSecureRequest) => {
|
|
|
136
136
|
return { redirectToSignIn, redirectToSignUp };
|
|
137
137
|
};
|
|
138
138
|
const createMiddlewareProtect = (ternSecureRequest, authObject, redirectToSignIn) => {
|
|
139
|
-
return async (params, options) => {
|
|
139
|
+
return (async (params, options) => {
|
|
140
140
|
const notFound = () => nextjsNotFound();
|
|
141
141
|
const redirect = (url) => nextjsRedirectError(url, {
|
|
142
142
|
redirectUrl: url
|
|
@@ -148,7 +148,7 @@ const createMiddlewareProtect = (ternSecureRequest, authObject, redirectToSignIn
|
|
|
148
148
|
authObject,
|
|
149
149
|
redirectToSignIn
|
|
150
150
|
})(params, options);
|
|
151
|
-
};
|
|
151
|
+
});
|
|
152
152
|
};
|
|
153
153
|
const redirectAdapter = (url) => {
|
|
154
154
|
return NextResponse.redirect(url, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/ternSecureProxy.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n RedirectFun,\r\n RequestState,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { AuthStatus, constants, createRedirect, createTernSecureRequest } from '@tern-secure/backend';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware, NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { FIREBASE_API_KEY, FIREBASE_APP_ID, FIREBASE_PROJECT_ID,SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect, createProtect } from './protect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends AuthenticateRequestOptions {\r\n debug?: boolean;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureProxy = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n const apiKey = resolvedParams.apiKey || FIREBASE_API_KEY;\r\n const appId = FIREBASE_APP_ID;\r\n const projectId = FIREBASE_PROJECT_ID;\r\n const firebaseConfig = resolvedParams.firebaseConfig || {\r\n apiKey,\r\n appId,\r\n projectId,\r\n }\r\n const firebaseAdminConfig = resolvedParams.firebaseAdminConfig;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n apiKey,\r\n firebaseConfig,\r\n firebaseAdminConfig,\r\n ...resolvedParams,\r\n };\r\n\r\n const reqBackendClient = await ternSecureBackendClient();\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const locationHeader = requestStateClient.headers.get(constants.Headers.Location);\r\n const appCheckToken = requestStateClient.headers.get(constants.Headers.AppCheckToken);\r\n console.log(\"[ternSecureProxy] App Check Token in Proxy:\", appCheckToken);\r\n if (locationHeader) {\r\n return new Response(null, {\r\n status: 307,\r\n headers: requestStateClient.headers,\r\n });\r\n } else if (requestStateClient.status === AuthStatus.Handshake) {\r\n throw new Error('TernSecure: handshake status without redirect is not supported.');\r\n }\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const redirectToSignIn = createProxyRedirectToSignIn(ternSecureRequest);\r\n const redirectToSignUp = createProxyRedirectToSignUp(ternSecureRequest);\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request, requestStateClient);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient, appCheckToken || undefined);\r\n return handlerResult;\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\n\r\nconst createProxyRedirectToSignIn = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignIn'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\nconst createProxyRedirectToSignUp = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignUp'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\n/**\r\n * Create middleware redirect functions\r\n * @deprecated\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n requestState: RequestState,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: requestState.signInUrl,\r\n signUpUrl: requestState.signUpUrl,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n"],"mappings":"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","names":["request","event"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ternSecureProxy.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n RedirectFun,\r\n RequestState,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { AuthStatus, constants, createRedirect, createTernSecureRequest } from '@tern-secure/backend';\r\nimport { notFound as nextjsNotFound } from 'next/navigation';\r\nimport type { NextMiddleware, NextRequest } from 'next/server';\r\nimport { NextResponse } from 'next/server';\r\n\r\nimport { isRedirect, setHeader } from '../utils/response';\r\nimport { serverRedirectWithAuth } from '../utils/serverRedirectAuth';\r\nimport { FIREBASE_API_KEY, FIREBASE_APP_ID, FIREBASE_PROJECT_ID,SIGN_IN_URL, SIGN_UP_URL } from './constant';\r\nimport {\r\n isNextjsNotFoundError,\r\n isNextjsRedirectError,\r\n isRedirectToSignInError,\r\n isRedirectToSignUpError,\r\n nextjsRedirectError,\r\n redirectToSignInError,\r\n redirectToSignUpError,\r\n} from './nextErrors';\r\nimport { type AuthProtect, createProtect } from './protect';\r\nimport { ternSecureBackendClient } from './ternsecureClient';\r\nimport type {\r\n NextMiddlewareEvtParam,\r\n NextMiddlewareRequestParam,\r\n NextMiddlewareReturn,\r\n} from './types';\r\nimport { decorateRequest } from './utils';\r\n\r\nexport type MiddlewareAuthObject = AuthObject & {\r\n redirectToSignIn: RedirectFun<Response>;\r\n redirectToSignUp: RedirectFun<Response>;\r\n};\r\n\r\nexport interface MiddlewareAuth {\r\n (): Promise<MiddlewareAuthObject>;\r\n\r\n protect: AuthProtect;\r\n}\r\n\r\ntype MiddlewareHandler = (\r\n auth: MiddlewareAuth,\r\n request: NextMiddlewareRequestParam,\r\n event: NextMiddlewareEvtParam,\r\n) => NextMiddlewareReturn;\r\n\r\nexport interface MiddlewareOptions extends AuthenticateRequestOptions {\r\n debug?: boolean;\r\n}\r\ntype MiddlewareOptionsCallback = (\r\n req: NextRequest,\r\n) => MiddlewareOptions | Promise<MiddlewareOptions>;\r\n\r\ninterface TernSecureMiddleware {\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptions): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware((auth, request, event) => { ... }, (req) => options);\r\n */\r\n (handler: MiddlewareHandler, options?: MiddlewareOptionsCallback): NextMiddleware;\r\n\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware(options);\r\n */\r\n (options?: MiddlewareOptions): NextMiddleware;\r\n /**\r\n * @example\r\n * export default ternSecureMiddleware;\r\n */\r\n (request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam): NextMiddlewareReturn;\r\n}\r\n\r\nexport const ternSecureProxy = ((\r\n ...args: unknown[]\r\n): NextMiddleware | NextMiddlewareReturn => {\r\n const [request, event] = parseRequestAndEvent(args);\r\n const [handler, params] = parseHandlerAndOptions(args);\r\n\r\n const middleware = () => {\r\n const withAuthNextMiddleware: NextMiddleware = async (request, event) => {\r\n const resolvedParams = typeof params === 'function' ? await params(request) : params;\r\n\r\n const signInUrl = resolvedParams.signInUrl || SIGN_IN_URL;\r\n const signUpUrl = resolvedParams.signUpUrl || SIGN_UP_URL;\r\n const apiKey = resolvedParams.apiKey || FIREBASE_API_KEY;\r\n const appId = FIREBASE_APP_ID;\r\n const projectId = FIREBASE_PROJECT_ID;\r\n const firebaseConfig = resolvedParams.firebaseConfig || {\r\n apiKey,\r\n appId,\r\n projectId,\r\n }\r\n const firebaseAdminConfig = resolvedParams.firebaseAdminConfig;\r\n\r\n const options = {\r\n signInUrl,\r\n signUpUrl,\r\n apiKey,\r\n firebaseConfig,\r\n firebaseAdminConfig,\r\n ...resolvedParams,\r\n };\r\n\r\n const reqBackendClient = await ternSecureBackendClient();\r\n\r\n const ternSecureRequest = createTernSecureRequest(request);\r\n\r\n const requestStateClient = await reqBackendClient.authenticateRequest(\r\n ternSecureRequest,\r\n options,\r\n );\r\n\r\n const locationHeader = requestStateClient.headers.get(constants.Headers.Location);\r\n const appCheckToken = requestStateClient.headers.get(constants.Headers.AppCheckToken);\r\n console.log(\"[ternSecureProxy] App Check Token in Proxy:\", appCheckToken);\r\n if (locationHeader) {\r\n return new Response(null, {\r\n status: 307,\r\n headers: requestStateClient.headers,\r\n });\r\n } else if (requestStateClient.status === AuthStatus.Handshake) {\r\n throw new Error('TernSecure: handshake status without redirect is not supported.');\r\n }\r\n\r\n const authObjectClient = requestStateClient.auth();\r\n\r\n const redirectToSignIn = createProxyRedirectToSignIn(ternSecureRequest);\r\n const redirectToSignUp = createProxyRedirectToSignUp(ternSecureRequest);\r\n const protect = await createMiddlewareProtect(\r\n ternSecureRequest,\r\n authObjectClient,\r\n redirectToSignIn,\r\n );\r\n\r\n const authObj: MiddlewareAuthObject = Object.assign(authObjectClient, {\r\n redirectToSignIn,\r\n redirectToSignUp,\r\n });\r\n\r\n const authHandler = () => Promise.resolve(authObj);\r\n authHandler.protect = protect;\r\n\r\n let handlerResult: Response = NextResponse.next();\r\n\r\n try {\r\n const userHandlerResult = await handler?.(authHandler, request, event);\r\n handlerResult = userHandlerResult || handlerResult;\r\n } catch (error: any) {\r\n handlerResult = handleControlError(error, ternSecureRequest, request, requestStateClient);\r\n }\r\n\r\n if (requestStateClient.headers) {\r\n requestStateClient.headers.forEach((value, key) => {\r\n handlerResult.headers.append(key, value);\r\n });\r\n }\r\n\r\n if (isRedirect(handlerResult)) {\r\n return serverRedirectWithAuth(ternSecureRequest, handlerResult);\r\n }\r\n\r\n decorateRequest(ternSecureRequest, handlerResult, requestStateClient, appCheckToken || undefined);\r\n return handlerResult;\r\n };\r\n\r\n const nextMiddleware: NextMiddleware = async (request, event) => {\r\n return withAuthNextMiddleware(request, event);\r\n };\r\n\r\n if (request && event) {\r\n return nextMiddleware(request, event);\r\n }\r\n\r\n return nextMiddleware;\r\n };\r\n return middleware();\r\n}) as TernSecureMiddleware;\r\n\r\nconst parseRequestAndEvent = (args: unknown[]) => {\r\n return [\r\n args[0] instanceof Request ? args[0] : undefined,\r\n args[0] instanceof Request ? args[1] : undefined,\r\n ] as [NextMiddlewareRequestParam | undefined, NextMiddlewareEvtParam | undefined];\r\n};\r\n\r\nconst parseHandlerAndOptions = (args: unknown[]) => {\r\n return [\r\n typeof args[0] === 'function' ? args[0] : undefined,\r\n (args.length === 2 ? args[1] : typeof args[0] === 'function' ? {} : args[0]) || {},\r\n ] as [MiddlewareHandler | undefined, MiddlewareOptions | MiddlewareOptionsCallback];\r\n};\r\n\r\n\r\nconst createProxyRedirectToSignIn = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignIn'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\nconst createProxyRedirectToSignUp = (\r\n ternSecureRequest: TernSecureRequest,\r\n): MiddlewareAuthObject['redirectToSignUp'] => {\r\n return (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n};\r\n\r\n/**\r\n * Create middleware redirect functions\r\n * @deprecated\r\n */\r\nconst createMiddlewareRedirects = (ternSecureRequest: TernSecureRequest) => {\r\n const redirectToSignIn: MiddlewareAuthObject['redirectToSignIn'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignInError(url, opts.returnBackUrl);\r\n };\r\n\r\n const redirectToSignUp: MiddlewareAuthObject['redirectToSignUp'] = (opts = {}) => {\r\n const url = ternSecureRequest.ternUrl.toString();\r\n redirectToSignUpError(url, opts.returnBackUrl);\r\n };\r\n\r\n return { redirectToSignIn, redirectToSignUp };\r\n};\r\n\r\nconst createMiddlewareProtect = (\r\n ternSecureRequest: TernSecureRequest,\r\n authObject: AuthObject,\r\n redirectToSignIn: RedirectFun<Response>,\r\n) => {\r\n return (async (params: any, options: any) => {\r\n const notFound = () => nextjsNotFound();\r\n\r\n const redirect = (url: string) =>\r\n nextjsRedirectError(url, {\r\n redirectUrl: url,\r\n });\r\n\r\n return createProtect({\r\n request: ternSecureRequest,\r\n redirect,\r\n notFound,\r\n authObject,\r\n redirectToSignIn,\r\n })(params, options);\r\n }) as unknown as Promise<AuthProtect>;\r\n};\r\n\r\nexport const redirectAdapter = (url: string | URL) => {\r\n return NextResponse.redirect(url, {\r\n headers: { [constants.Headers.TernSecureRedirectTo]: 'true' },\r\n });\r\n};\r\n\r\n/**\r\n * Handle control flow errors in middleware\r\n */\r\nconst handleControlError = (\r\n error: any,\r\n ternSecureRequest: TernSecureRequest,\r\n nextrequest: NextRequest,\r\n requestState: RequestState,\r\n): Response => {\r\n if (isNextjsNotFoundError(error)) {\r\n return setHeader(\r\n NextResponse.rewrite(new URL(`/tern_${Date.now()}`, nextrequest.url)),\r\n constants.Headers.AuthReason,\r\n 'protect-rewrite',\r\n );\r\n }\r\n\r\n const isRedirectToSignIn = isRedirectToSignInError(error);\r\n const isRedirectToSignUp = isRedirectToSignUpError(error);\r\n\r\n if (isRedirectToSignIn || isRedirectToSignUp) {\r\n const redirect = createRedirect({\r\n redirectAdapter,\r\n baseUrl: ternSecureRequest.ternUrl,\r\n signInUrl: requestState.signInUrl,\r\n signUpUrl: requestState.signUpUrl,\r\n });\r\n\r\n const { returnBackUrl } = error;\r\n\r\n return redirect[isRedirectToSignIn ? 'redirectToSignIn' : 'redirectToSignUp']({\r\n returnBackUrl,\r\n });\r\n }\r\n\r\n if (isNextjsRedirectError(error)) {\r\n return redirectAdapter(error.redirectUrl);\r\n }\r\n\r\n throw error;\r\n};\r\n"],"mappings":"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","names":["request","event"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tern-secure/nextjs",
|
|
3
|
-
"version": "5.2.0-canary.
|
|
3
|
+
"version": "5.2.0-canary.v20251127235234",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -61,10 +61,10 @@
|
|
|
61
61
|
"jose": "^5.9.6",
|
|
62
62
|
"server-only": "^0.0.1",
|
|
63
63
|
"tslib": "2.8.1",
|
|
64
|
-
"@tern-secure/backend": "1.2.0-canary.
|
|
65
|
-
"@tern-secure/react": "1.2.0-canary.
|
|
66
|
-
"@tern-secure/shared": "1.3.0-canary.
|
|
67
|
-
"@tern-secure/types": "1.1.0-canary.
|
|
64
|
+
"@tern-secure/backend": "1.2.0-canary.v20251127235234",
|
|
65
|
+
"@tern-secure/react": "1.2.0-canary.v20251127235234",
|
|
66
|
+
"@tern-secure/shared": "1.3.0-canary.v20251127235234",
|
|
67
|
+
"@tern-secure/types": "1.1.0-canary.v20251127235234"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"firebase": "^12.0.0",
|