@tern-secure/nextjs 5.2.0-canary.v20251003171521 → 5.2.0-canary.v20251008131428
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/request.js +9 -8
- package/dist/cjs/app-router/admin/request.js.map +1 -1
- package/dist/cjs/app-router/admin/sessionHandlers.js +4 -4
- package/dist/cjs/app-router/admin/sessionHandlers.js.map +1 -1
- package/dist/cjs/app-router/admin/types.js +7 -9
- package/dist/cjs/app-router/admin/types.js.map +1 -1
- package/dist/cjs/server/ternSecureEdgeMiddleware.js +0 -101
- package/dist/cjs/server/ternSecureEdgeMiddleware.js.map +1 -1
- package/dist/esm/app-router/admin/request.js +9 -8
- package/dist/esm/app-router/admin/request.js.map +1 -1
- package/dist/esm/app-router/admin/sessionHandlers.js +4 -4
- package/dist/esm/app-router/admin/sessionHandlers.js.map +1 -1
- package/dist/esm/app-router/admin/types.js +7 -9
- package/dist/esm/app-router/admin/types.js.map +1 -1
- package/dist/esm/server/ternSecureEdgeMiddleware.js +1 -106
- package/dist/esm/server/ternSecureEdgeMiddleware.js.map +1 -1
- package/dist/types/app-router/admin/request.d.ts +1 -1
- package/dist/types/app-router/admin/request.d.ts.map +1 -1
- package/dist/types/app-router/admin/sessionHandlers.d.ts +1 -1
- package/dist/types/app-router/admin/sessionHandlers.d.ts.map +1 -1
- package/dist/types/app-router/admin/types.d.ts +1 -1
- package/dist/types/app-router/admin/types.d.ts.map +1 -1
- package/dist/types/server/ternSecureEdgeMiddleware.d.ts +2 -4
- package/dist/types/server/ternSecureEdgeMiddleware.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -26,12 +26,7 @@ var import_auth = require("@tern-secure/backend/auth");
|
|
|
26
26
|
var import_cookie = require("@tern-secure/shared/cookie");
|
|
27
27
|
var import_ternsecureClient = require("../../server/ternsecureClient");
|
|
28
28
|
var import_constants = require("./constants");
|
|
29
|
-
|
|
30
|
-
httpOnly: true,
|
|
31
|
-
secure: process.env.NODE_ENV === "production",
|
|
32
|
-
sameSite: "strict"
|
|
33
|
-
};
|
|
34
|
-
async function refreshCookieWithIdToken(idToken, cookieStore, options, referrer) {
|
|
29
|
+
async function refreshCookieWithIdToken(idToken, cookieStore, config, referrer) {
|
|
35
30
|
const backendClient = await (0, import_ternsecureClient.ternSecureBackendClient)();
|
|
36
31
|
const authOptions = {
|
|
37
32
|
firebaseConfig: {
|
|
@@ -41,10 +36,16 @@ async function refreshCookieWithIdToken(idToken, cookieStore, options, referrer)
|
|
|
41
36
|
storageBucket: import_constants.FIREBASE_STORAGE_BUCKET,
|
|
42
37
|
messagingSenderId: import_constants.FIREBASE_MESSAGING_SENDER_ID,
|
|
43
38
|
appId: import_constants.FIREBASE_APP_ID,
|
|
44
|
-
tenantId:
|
|
39
|
+
tenantId: config?.tenantId || void 0
|
|
45
40
|
},
|
|
46
41
|
apiClient: backendClient
|
|
47
42
|
};
|
|
43
|
+
const COOKIE_OPTIONS = {
|
|
44
|
+
httpOnly: config?.cookies?.httpOnly,
|
|
45
|
+
secure: config?.cookies?.secure,
|
|
46
|
+
sameSite: config?.cookies?.sameSite,
|
|
47
|
+
maxAge: config?.cookies?.maxAge
|
|
48
|
+
};
|
|
48
49
|
const { createCustomIdAndRefreshToken } = (0, import_auth.getAuth)(authOptions);
|
|
49
50
|
const customTokens = await createCustomIdAndRefreshToken(idToken, { referer: referrer });
|
|
50
51
|
const cookiePrefix = (0, import_cookie.getCookiePrefix)();
|
|
@@ -60,7 +61,7 @@ async function refreshCookieWithIdToken(idToken, cookieStore, options, referrer)
|
|
|
60
61
|
COOKIE_OPTIONS
|
|
61
62
|
)
|
|
62
63
|
];
|
|
63
|
-
if (
|
|
64
|
+
if (config?.enableCustomToken) {
|
|
64
65
|
cookiePromises.push(
|
|
65
66
|
cookieStore.set(import_backend.constants.Cookies.Custom, customTokens.customToken, COOKIE_OPTIONS)
|
|
66
67
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/request.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\nimport { getAuth } from '@tern-secure/backend/auth';\nimport { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nimport { ternSecureBackendClient } from '../../server/ternsecureClient';\nimport type { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport {\n FIREBASE_API_KEY,\n FIREBASE_APP_ID,\n FIREBASE_AUTH_DOMAIN,\n FIREBASE_MESSAGING_SENDER_ID,\n FIREBASE_PROJECT_ID,\n FIREBASE_STORAGE_BUCKET,\n} from './constants';\nimport type { TernSecureHandlerOptions } from './types';\n\
|
|
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\nexport async function refreshCookieWithIdToken(\n idToken: string,\n cookieStore: NextCookieStore,\n config?: TernSecureHandlerOptions,\n referrer?: string,\n): Promise<void> {\n const backendClient = await ternSecureBackendClient();\n\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: config?.tenantId || undefined,\n },\n apiClient: backendClient,\n };\n\n const COOKIE_OPTIONS = {\n httpOnly: config?.cookies?.httpOnly,\n secure: config?.cookies?.secure,\n sameSite: config?.cookies?.sameSite,\n maxAge: config?.cookies?.maxAge,\n };\n\n const { createCustomIdAndRefreshToken } = getAuth(authOptions);\n\n const customTokens = await createCustomIdAndRefreshToken(idToken, { referer: referrer });\n\n const cookiePrefix = getCookiePrefix();\n\n const cookiePromises = [\n cookieStore.set(\n getCookieName(constants.Cookies.IdToken, cookiePrefix),\n customTokens.idToken,\n COOKIE_OPTIONS,\n ),\n cookieStore.set(\n getCookieName(constants.Cookies.Refresh, cookiePrefix),\n customTokens.refreshToken,\n COOKIE_OPTIONS,\n ),\n ];\n\n if (config?.enableCustomToken) {\n cookiePromises.push(\n cookieStore.set(constants.Cookies.Custom, customTokens.customToken, COOKIE_OPTIONS),\n );\n }\n\n await Promise.all(cookiePromises);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAA0B;AAC1B,kBAAwB;AACxB,oBAA+C;AAE/C,8BAAwC;AAExC,uBAOO;AAGP,eAAsB,yBACpB,SACA,aACA,QACA,UACe;AACf,QAAM,gBAAgB,UAAM,iDAAwB;AAEpD,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,QAAQ,YAAY;AAAA,IAChC;AAAA,IACA,WAAW;AAAA,EACb;AAEA,QAAM,iBAAiB;AAAA,IACrB,UAAU,QAAQ,SAAS;AAAA,IAC3B,QAAQ,QAAQ,SAAS;AAAA,IACzB,UAAU,QAAQ,SAAS;AAAA,IAC3B,QAAQ,QAAQ,SAAS;AAAA,EAC3B;AAEA,QAAM,EAAE,8BAA8B,QAAI,qBAAQ,WAAW;AAE7D,QAAM,eAAe,MAAM,8BAA8B,SAAS,EAAE,SAAS,SAAS,CAAC;AAEvF,QAAM,mBAAe,+BAAgB;AAErC,QAAM,iBAAiB;AAAA,IACrB,YAAY;AAAA,UACV,6BAAc,yBAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA,YAAY;AAAA,UACV,6BAAc,yBAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,mBAAmB;AAC7B,mBAAe;AAAA,MACb,YAAY,IAAI,yBAAU,QAAQ,QAAQ,aAAa,aAAa,cAAc;AAAA,IACpF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,cAAc;AAClC;","names":[]}
|
|
@@ -28,7 +28,7 @@ var import_NextCookieAdapter = require("../../utils/NextCookieAdapter");
|
|
|
28
28
|
var import_fnValidators = require("./fnValidators");
|
|
29
29
|
var import_request = require("./request");
|
|
30
30
|
var import_responses = require("./responses");
|
|
31
|
-
async function sessionEndpointHandler(context,
|
|
31
|
+
async function sessionEndpointHandler(context, config) {
|
|
32
32
|
const { subEndpoint, method, referrer } = context;
|
|
33
33
|
const validators = (0, import_fnValidators.createValidators)(context);
|
|
34
34
|
const {
|
|
@@ -41,7 +41,7 @@ async function sessionEndpointHandler(context, options) {
|
|
|
41
41
|
if (!subEndpoint) {
|
|
42
42
|
return (0, import_responses.createApiErrorResponse)("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
|
|
43
43
|
}
|
|
44
|
-
const sessionsConfig =
|
|
44
|
+
const sessionsConfig = config.endpoints?.sessions;
|
|
45
45
|
const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
|
|
46
46
|
validateSubEndpoint(subEndpoint, subEndpointConfig);
|
|
47
47
|
if (subEndpointConfig?.security) {
|
|
@@ -79,7 +79,7 @@ async function sessionEndpointHandler(context, options) {
|
|
|
79
79
|
validateCsrfToken(csrfToken || "", csrfCookieValue.value);
|
|
80
80
|
const handleCreateSession = async (cookieStore2, idToken2) => {
|
|
81
81
|
try {
|
|
82
|
-
await (0, import_request.refreshCookieWithIdToken)(idToken2, cookieStore2,
|
|
82
|
+
await (0, import_request.refreshCookieWithIdToken)(idToken2, cookieStore2, config, referrer);
|
|
83
83
|
return import_responses.SessionResponseHelper.createSessionCreationResponse({
|
|
84
84
|
success: true,
|
|
85
85
|
message: "Session created successfully"
|
|
@@ -94,7 +94,7 @@ async function sessionEndpointHandler(context, options) {
|
|
|
94
94
|
if (decodedSession.errors) {
|
|
95
95
|
return (0, import_responses.createApiErrorResponse)("INVALID_SESSION", "Invalid session for refresh", 401);
|
|
96
96
|
}
|
|
97
|
-
const refreshRes = await (0, import_request.refreshCookieWithIdToken)(idToken2, cookieStore2,
|
|
97
|
+
const refreshRes = await (0, import_request.refreshCookieWithIdToken)(idToken2, cookieStore2, config);
|
|
98
98
|
return import_responses.SessionResponseHelper.createRefreshResponse(refreshRes);
|
|
99
99
|
} catch (error2) {
|
|
100
100
|
return (0, import_responses.createApiErrorResponse)("REFRESH_FAILED", "Session refresh failed", 500);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import { clearSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { type RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createValidators } from './fnValidators';\nimport { refreshCookieWithIdToken } from './request';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type { SessionSubEndpoint, TernSecureHandlerOptions } from './types';\n\nexport async function sessionEndpointHandler(\n context: RequestProcessorContext,\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import { clearSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { type RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createValidators } from './fnValidators';\nimport { refreshCookieWithIdToken } from './request';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type { SessionSubEndpoint, TernSecureHandlerOptions } from './types';\n\nexport async function sessionEndpointHandler(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n): Promise<Response> {\n const { subEndpoint, method, referrer } = context;\n\n const validators = createValidators(context);\n\n const {\n validateSubEndpoint,\n validateSecurity,\n validateSessionRequest,\n validateCsrfToken,\n validateIdToken,\n } = validators;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const sessionsConfig = config.endpoints?.sessions;\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n validateSubEndpoint(subEndpoint, subEndpointConfig);\n\n if (subEndpointConfig?.security) {\n await validateSecurity(subEndpointConfig.security);\n }\n\n const SessionGetHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const handleSessionVerify = async (): Promise<Response> => {\n try {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);\n if (errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n };\n\n switch (subEndpoint) {\n case 'verify':\n return handleSessionVerify();\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n };\n\n const SessionPostHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await validateSessionRequest();\n if (error) return error;\n\n const csrfCookieValue = await cookieStore.get('_session_terncf');\n validateCsrfToken(csrfToken || '', csrfCookieValue.value);\n\n const handleCreateSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n await refreshCookieWithIdToken(idToken, cookieStore, config, referrer);\n return SessionResponseHelper.createSessionCreationResponse({\n success: true,\n message: 'Session created successfully',\n });\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n };\n\n const handleRefreshSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n const decodedSession = ternDecodeJwtUnguarded(idToken);\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await refreshCookieWithIdToken(idToken, cookieStore, config);\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n };\n\n const handleRevokeSession = async (cookieStore: NextCookieStore): Promise<Response> => {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n };\n\n switch (subEndpoint) {\n case 'createsession': {\n validateIdToken(idToken);\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleCreateSession(cookieStore, idToken!);\n }\n\n case 'refresh':\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleRefreshSession(cookieStore, idToken!);\n\n case 'revoke':\n return handleRevokeSession(cookieStore);\n\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n };\n\n switch (method) {\n case 'GET':\n return SessionGetHandler(subEndpoint);\n\n case 'POST':\n return SessionPostHandler(subEndpoint);\n\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n}\n"],"mappings":"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","names":["subEndpoint","cookieStore","idToken","error"]}
|
|
@@ -37,13 +37,13 @@ const DEFAULT_CORS_OPTIONS = {
|
|
|
37
37
|
// 24 hours
|
|
38
38
|
};
|
|
39
39
|
const DEFAULT_COOKIE_OPTIONS = {
|
|
40
|
-
//namePrefix: '__session',
|
|
41
|
-
path: "/",
|
|
42
40
|
httpOnly: true,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
path: "/",
|
|
42
|
+
secure: process.env.NODE_ENV === "production",
|
|
43
|
+
sameSite: "strict",
|
|
44
|
+
maxAge: 12 * 60 * 60 * 24,
|
|
45
|
+
// twelve days
|
|
46
|
+
priority: "high"
|
|
47
47
|
};
|
|
48
48
|
const FIXED_TOKEN_CONFIGS = {
|
|
49
49
|
id: {
|
|
@@ -166,17 +166,15 @@ class CookieUtils {
|
|
|
166
166
|
const sessionConfig = cookieOptions.session || {};
|
|
167
167
|
const defaultSession = DEFAULT_COOKIE_OPTIONS.session || {};
|
|
168
168
|
return {
|
|
169
|
-
domain: sessionConfig.domain ?? cookieOptions.domain,
|
|
170
169
|
path: sessionConfig.path ?? cookieOptions.path ?? "/",
|
|
171
170
|
httpOnly: sessionConfig.httpOnly ?? cookieOptions.httpOnly ?? true,
|
|
172
171
|
sameSite: sessionConfig.sameSite ?? cookieOptions.sameSite ?? "lax",
|
|
173
172
|
maxAge: sessionConfig.maxAge ?? defaultSession.maxAge ?? 3600 * 24 * 7
|
|
174
173
|
};
|
|
175
174
|
}
|
|
176
|
-
static getFixedTokenConfig(
|
|
175
|
+
static getFixedTokenConfig(tokenType) {
|
|
177
176
|
const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];
|
|
178
177
|
return {
|
|
179
|
-
domain: cookieOptions.domain,
|
|
180
178
|
path: fixedConfig.path,
|
|
181
179
|
httpOnly: fixedConfig.httpOnly,
|
|
182
180
|
sameSite: fixedConfig.sameSite,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig,\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_COOKIE_OPTIONS: CookieOptions = {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig,\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_COOKIE_OPTIONS: CookieOptions = {\n httpOnly: true,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 12 * 60 * 60 * 24, // twelve days\n priority: 'high',\n};\n\n\nexport const FIXED_TOKEN_CONFIGS = {\n id: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600, // 1 hour\n },\n refresh: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 30, // 30 days (changes when user events occur)\n },\n signature: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n custom: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n} as const;\n\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n requireCSRF: true,\n allowedReferers: [],\n requiredHeaders: {},\n ipWhitelist: [],\n userAgent: {\n block: [],\n allow: [],\n },\n};\n\nexport const DEFAULT_ENDPOINT_CONFIG: EndpointConfig = {\n enabled: true,\n methods: ['GET', 'POST'],\n requireAuth: false,\n security: DEFAULT_SECURITY_OPTIONS,\n};\n\nexport const DEFAULT_SESSIONS_CONFIG: SessionEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n verify: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n createsession: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n },\n },\n refresh: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n revoke: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n },\n};\n\nexport const DEFAULT_HANDLER_OPTIONS: Required<TernSecureHandlerOptions> & {\n endpoints: Required<NonNullable<TernSecureHandlerOptions['endpoints']>>;\n} = {\n cors: DEFAULT_CORS_OPTIONS,\n cookies: DEFAULT_COOKIE_OPTIONS,\n rateLimit: {\n windowMs: 15 * 60 * 1000, // 15 minutes\n maxRequests: 100,\n skipSuccessful: false,\n skipFailedRequests: false,\n },\n security: DEFAULT_SECURITY_OPTIONS,\n endpoints: {\n sessions: DEFAULT_SESSIONS_CONFIG,\n },\n tenantId: '',\n enableCustomToken: false,\n debug: false,\n environment: 'production',\n basePath: '/api/auth',\n};\n\nexport interface ValidationResult {\n error?: NextResponse;\n data?: any;\n}\n\nexport interface ValidationConfig {\n cors?: CorsOptions;\n security?: SecurityOptions;\n endpoint?: {\n name: AuthEndpoint;\n config: EndpointConfig;\n };\n subEndpoint?: {\n name: SessionSubEndpoint;\n config: EndpointConfig;\n };\n requireIdToken?: boolean;\n requireCsrfToken?: boolean;\n}\n\nexport interface ComprehensiveValidationResult {\n isValid: boolean;\n error?: Response;\n corsResponse?: Response;\n sessionData?: {\n body: any;\n idToken?: string;\n csrfToken?: string;\n };\n}\n\nexport type suffix = 'session' | 'id' | 'refresh' | 'signature' | 'custom';\n\nexport class CookieUtils {\n static getCookieName(namePrefix: string, tokenType: suffix): string {\n return `${namePrefix}.${tokenType}`;\n }\n\n static getCookieNames(namePrefix: string) {\n return {\n session: this.getCookieName(namePrefix, 'session'),\n id: this.getCookieName(namePrefix, 'id'),\n refresh: this.getCookieName(namePrefix, 'refresh'),\n signature: this.getCookieName(namePrefix, 'signature'),\n custom: this.getCookieName(namePrefix, 'custom'),\n };\n }\n\n static getSessionConfig(cookieOptions: CookieOptions): TokenCookieConfig {\n const sessionConfig = cookieOptions.session || {};\n const defaultSession = DEFAULT_COOKIE_OPTIONS.session || {};\n\n return {\n path: sessionConfig.path ?? cookieOptions.path ?? '/',\n httpOnly: sessionConfig.httpOnly ?? cookieOptions.httpOnly ?? true,\n sameSite: sessionConfig.sameSite ?? cookieOptions.sameSite ?? 'lax',\n maxAge: sessionConfig.maxAge ?? defaultSession.maxAge ?? 3600 * 24 * 7,\n };\n }\n\n static getFixedTokenConfig(\n tokenType: Exclude<suffix, 'session'>,\n ): TokenCookieConfig {\n const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];\n\n return {\n path: fixedConfig.path,\n httpOnly: fixedConfig.httpOnly,\n sameSite: fixedConfig.sameSite,\n maxAge: fixedConfig.maxAge,\n };\n }\n\n static validateSessionMaxAge(maxAge: number): boolean {\n const minAge = 300; // 5 minutes\n const maxAgeLimit = 3600 * 24 * 14; // 2 weeks\n return maxAge >= minAge && maxAge <= maxAgeLimit;\n }\n}\n\nexport {\n AuthEndpoint,\n CookieOptions,\n CorsOptions,\n SecurityOptions,\n SessionSubEndpoint,\n EndpointConfig,\n SessionEndpointConfig,\n TernSecureHandlerOptions,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -90,9 +90,6 @@ const ternSecureMiddleware = (...args) => {
|
|
|
90
90
|
return handlerResult;
|
|
91
91
|
};
|
|
92
92
|
const nextMiddleware = async (request2, event2) => {
|
|
93
|
-
if (isFirebaseCookieRequest(request2)) {
|
|
94
|
-
return handleFirebaseAuthRequest(request2);
|
|
95
|
-
}
|
|
96
93
|
return withAuthNextMiddleware(request2, event2);
|
|
97
94
|
};
|
|
98
95
|
if (request && event) {
|
|
@@ -114,18 +111,6 @@ const parseHandlerAndOptions = (args) => {
|
|
|
114
111
|
(args.length === 2 ? args[1] : typeof args[0] === "function" ? {} : args[0]) || {}
|
|
115
112
|
];
|
|
116
113
|
};
|
|
117
|
-
const isFirebaseRequest = (request) => request.nextUrl.pathname.startsWith("/__/");
|
|
118
|
-
const rewriteFirebaseRequest = (options, request) => {
|
|
119
|
-
const newUrl = new URL(request.url);
|
|
120
|
-
newUrl.host = options.firebaseOptions?.authDomain || "";
|
|
121
|
-
newUrl.port = "";
|
|
122
|
-
return import_server.NextResponse.rewrite(newUrl);
|
|
123
|
-
};
|
|
124
|
-
const finalTarget = (request) => {
|
|
125
|
-
const finalTargetUrl = request.nextUrl.searchParams.get("finalTarget");
|
|
126
|
-
return finalTargetUrl ? new URL(finalTargetUrl, request.url) : void 0;
|
|
127
|
-
};
|
|
128
|
-
const isFirebaseCookieRequest = (request) => request.nextUrl.pathname === "/__cookies__";
|
|
129
114
|
const createMiddlewareRedirects = (ternSecureRequest) => {
|
|
130
115
|
const redirectToSignIn = (opts = {}) => {
|
|
131
116
|
const url = ternSecureRequest.ternUrl.toString();
|
|
@@ -184,92 +169,6 @@ const handleControlError = (error, ternSecureRequest, nextrequest) => {
|
|
|
184
169
|
}
|
|
185
170
|
throw error;
|
|
186
171
|
};
|
|
187
|
-
const handleFirebaseAuthRequest = async (request) => {
|
|
188
|
-
console.log("Checking for __cookies__ path");
|
|
189
|
-
const isDevMode = process.env.NODE_ENV === "development";
|
|
190
|
-
const ID_TOKEN_COOKIE_NAME = isDevMode ? `__dev_FIREBASE_[DEFAULT]` : `__HOST-FIREBASE_[DEFAULT]`;
|
|
191
|
-
const REFRESH_TOKEN_COOKIE_NAME = isDevMode ? "__dev_FIREBASEID_[DEFAULT]" : `__HOST-FIREBASEID_[DEFAULT]`;
|
|
192
|
-
const ID_TOKEN_COOKIE = {
|
|
193
|
-
path: "/",
|
|
194
|
-
secure: !isDevMode,
|
|
195
|
-
sameSite: "strict",
|
|
196
|
-
partitioned: true,
|
|
197
|
-
name: ID_TOKEN_COOKIE_NAME,
|
|
198
|
-
maxAge: 3456e4,
|
|
199
|
-
priority: "high"
|
|
200
|
-
};
|
|
201
|
-
const REFRESH_TOKEN_COOKIE = {
|
|
202
|
-
...ID_TOKEN_COOKIE,
|
|
203
|
-
httpOnly: true,
|
|
204
|
-
name: REFRESH_TOKEN_COOKIE_NAME
|
|
205
|
-
};
|
|
206
|
-
if (request.nextUrl.pathname === "/__cookies__") {
|
|
207
|
-
console.log("Handling /__cookies__ request");
|
|
208
|
-
const method = request.method;
|
|
209
|
-
if (method === "DELETE") {
|
|
210
|
-
const response2 = new import_server.NextResponse("");
|
|
211
|
-
response2.cookies.delete({ ...ID_TOKEN_COOKIE, maxAge: 0 });
|
|
212
|
-
response2.cookies.delete({ ...REFRESH_TOKEN_COOKIE, maxAge: 0 });
|
|
213
|
-
return response2;
|
|
214
|
-
}
|
|
215
|
-
const headers = {};
|
|
216
|
-
const headerNames = [
|
|
217
|
-
"content-type",
|
|
218
|
-
"X-Firebase-Client",
|
|
219
|
-
"X-Firebase-gmpid",
|
|
220
|
-
"X-Firebase-AppCheck",
|
|
221
|
-
"X-Client-Version"
|
|
222
|
-
];
|
|
223
|
-
headerNames.forEach((headerName) => {
|
|
224
|
-
const headerValue = request.headers.get(headerName);
|
|
225
|
-
if (headerValue) {
|
|
226
|
-
headers[headerName] = headerValue;
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
const finalTargetParam = request.nextUrl.searchParams.get("finalTarget");
|
|
230
|
-
const url = new URL(finalTargetParam || "");
|
|
231
|
-
let body = request.body;
|
|
232
|
-
const isTokenRequest = !!url.pathname.match(/^(\/securetoken\.googleapis\.com)?\/v1\/token/);
|
|
233
|
-
const isSignInRequest = !!url.pathname.match(
|
|
234
|
-
/^(\/identitytoolkit\.googleapis\.com)?\/v1\/accounts:signInWith/
|
|
235
|
-
);
|
|
236
|
-
if (!isTokenRequest && !isSignInRequest)
|
|
237
|
-
throw new Error("Could not determine the request type to proxy");
|
|
238
|
-
if (isTokenRequest) {
|
|
239
|
-
body = await request.text();
|
|
240
|
-
const bodyParams = new URLSearchParams(body.trim());
|
|
241
|
-
if (bodyParams.has("refresh_token")) {
|
|
242
|
-
const refreshToken2 = request.cookies.get(REFRESH_TOKEN_COOKIE.name)?.value;
|
|
243
|
-
if (refreshToken2) {
|
|
244
|
-
bodyParams.set("refresh_token", refreshToken2);
|
|
245
|
-
body = bodyParams.toString();
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const response = await fetch(url, { method, body, headers });
|
|
250
|
-
const json = await response.json();
|
|
251
|
-
if (!response.ok) {
|
|
252
|
-
return import_server.NextResponse.json(json, { status: response.status, statusText: response.statusText });
|
|
253
|
-
}
|
|
254
|
-
let refreshToken, idToken, maxAge;
|
|
255
|
-
if (isSignInRequest) {
|
|
256
|
-
refreshToken = json.refreshToken;
|
|
257
|
-
idToken = json.idToken;
|
|
258
|
-
maxAge = json.expiresIn;
|
|
259
|
-
json.refreshToken = "REDACTED";
|
|
260
|
-
} else {
|
|
261
|
-
refreshToken = json.refresh_token;
|
|
262
|
-
idToken = json.id_token;
|
|
263
|
-
maxAge = json.expires_in;
|
|
264
|
-
json.refresh_token = "REDACTED";
|
|
265
|
-
}
|
|
266
|
-
const nextResponse = import_server.NextResponse.json(json);
|
|
267
|
-
if (idToken) nextResponse.cookies.set({ ...ID_TOKEN_COOKIE, maxAge, value: idToken });
|
|
268
|
-
if (refreshToken) nextResponse.cookies.set({ ...REFRESH_TOKEN_COOKIE, value: refreshToken });
|
|
269
|
-
return nextResponse;
|
|
270
|
-
}
|
|
271
|
-
return null;
|
|
272
|
-
};
|
|
273
172
|
// Annotate the CommonJS export names for ESM import in node:
|
|
274
173
|
0 && (module.exports = {
|
|
275
174
|
redirectAdapter,
|
|
@@ -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 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":"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","names":["request","event","nextjsNotFound","response","refreshToken"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ternSecureEdgeMiddleware.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { constants, createTernSecureRequest, enableDebugLogging } 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 { 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 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 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 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 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 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\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"],"mappings":"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","names":["request","event","nextjsNotFound"]}
|
|
@@ -10,12 +10,7 @@ import {
|
|
|
10
10
|
FIREBASE_PROJECT_ID,
|
|
11
11
|
FIREBASE_STORAGE_BUCKET
|
|
12
12
|
} from "./constants";
|
|
13
|
-
|
|
14
|
-
httpOnly: true,
|
|
15
|
-
secure: process.env.NODE_ENV === "production",
|
|
16
|
-
sameSite: "strict"
|
|
17
|
-
};
|
|
18
|
-
async function refreshCookieWithIdToken(idToken, cookieStore, options, referrer) {
|
|
13
|
+
async function refreshCookieWithIdToken(idToken, cookieStore, config, referrer) {
|
|
19
14
|
const backendClient = await ternSecureBackendClient();
|
|
20
15
|
const authOptions = {
|
|
21
16
|
firebaseConfig: {
|
|
@@ -25,10 +20,16 @@ async function refreshCookieWithIdToken(idToken, cookieStore, options, referrer)
|
|
|
25
20
|
storageBucket: FIREBASE_STORAGE_BUCKET,
|
|
26
21
|
messagingSenderId: FIREBASE_MESSAGING_SENDER_ID,
|
|
27
22
|
appId: FIREBASE_APP_ID,
|
|
28
|
-
tenantId:
|
|
23
|
+
tenantId: config?.tenantId || void 0
|
|
29
24
|
},
|
|
30
25
|
apiClient: backendClient
|
|
31
26
|
};
|
|
27
|
+
const COOKIE_OPTIONS = {
|
|
28
|
+
httpOnly: config?.cookies?.httpOnly,
|
|
29
|
+
secure: config?.cookies?.secure,
|
|
30
|
+
sameSite: config?.cookies?.sameSite,
|
|
31
|
+
maxAge: config?.cookies?.maxAge
|
|
32
|
+
};
|
|
32
33
|
const { createCustomIdAndRefreshToken } = getAuth(authOptions);
|
|
33
34
|
const customTokens = await createCustomIdAndRefreshToken(idToken, { referer: referrer });
|
|
34
35
|
const cookiePrefix = getCookiePrefix();
|
|
@@ -44,7 +45,7 @@ async function refreshCookieWithIdToken(idToken, cookieStore, options, referrer)
|
|
|
44
45
|
COOKIE_OPTIONS
|
|
45
46
|
)
|
|
46
47
|
];
|
|
47
|
-
if (
|
|
48
|
+
if (config?.enableCustomToken) {
|
|
48
49
|
cookiePromises.push(
|
|
49
50
|
cookieStore.set(constants.Cookies.Custom, customTokens.customToken, COOKIE_OPTIONS)
|
|
50
51
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/request.ts"],"sourcesContent":["import type { AuthenticateRequestOptions } from '@tern-secure/backend';\nimport { constants } from '@tern-secure/backend';\nimport { getAuth } from '@tern-secure/backend/auth';\nimport { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nimport { ternSecureBackendClient } from '../../server/ternsecureClient';\nimport type { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport {\n FIREBASE_API_KEY,\n FIREBASE_APP_ID,\n FIREBASE_AUTH_DOMAIN,\n FIREBASE_MESSAGING_SENDER_ID,\n FIREBASE_PROJECT_ID,\n FIREBASE_STORAGE_BUCKET,\n} from './constants';\nimport type { TernSecureHandlerOptions } from './types';\n\
|
|
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\nexport async function refreshCookieWithIdToken(\n idToken: string,\n cookieStore: NextCookieStore,\n config?: TernSecureHandlerOptions,\n referrer?: string,\n): Promise<void> {\n const backendClient = await ternSecureBackendClient();\n\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: config?.tenantId || undefined,\n },\n apiClient: backendClient,\n };\n\n const COOKIE_OPTIONS = {\n httpOnly: config?.cookies?.httpOnly,\n secure: config?.cookies?.secure,\n sameSite: config?.cookies?.sameSite,\n maxAge: config?.cookies?.maxAge,\n };\n\n const { createCustomIdAndRefreshToken } = getAuth(authOptions);\n\n const customTokens = await createCustomIdAndRefreshToken(idToken, { referer: referrer });\n\n const cookiePrefix = getCookiePrefix();\n\n const cookiePromises = [\n cookieStore.set(\n getCookieName(constants.Cookies.IdToken, cookiePrefix),\n customTokens.idToken,\n COOKIE_OPTIONS,\n ),\n cookieStore.set(\n getCookieName(constants.Cookies.Refresh, cookiePrefix),\n customTokens.refreshToken,\n COOKIE_OPTIONS,\n ),\n ];\n\n if (config?.enableCustomToken) {\n cookiePromises.push(\n cookieStore.set(constants.Cookies.Custom, customTokens.customToken, COOKIE_OPTIONS),\n );\n }\n\n await Promise.all(cookiePromises);\n}\n"],"mappings":"AACA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,eAAe,uBAAuB;AAE/C,SAAS,+BAA+B;AAExC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,eAAsB,yBACpB,SACA,aACA,QACA,UACe;AACf,QAAM,gBAAgB,MAAM,wBAAwB;AAEpD,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,QAAQ,YAAY;AAAA,IAChC;AAAA,IACA,WAAW;AAAA,EACb;AAEA,QAAM,iBAAiB;AAAA,IACrB,UAAU,QAAQ,SAAS;AAAA,IAC3B,QAAQ,QAAQ,SAAS;AAAA,IACzB,UAAU,QAAQ,SAAS;AAAA,IAC3B,QAAQ,QAAQ,SAAS;AAAA,EAC3B;AAEA,QAAM,EAAE,8BAA8B,IAAI,QAAQ,WAAW;AAE7D,QAAM,eAAe,MAAM,8BAA8B,SAAS,EAAE,SAAS,SAAS,CAAC;AAEvF,QAAM,eAAe,gBAAgB;AAErC,QAAM,iBAAiB;AAAA,IACrB,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,IACA,YAAY;AAAA,MACV,cAAc,UAAU,QAAQ,SAAS,YAAY;AAAA,MACrD,aAAa;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,mBAAmB;AAC7B,mBAAe;AAAA,MACb,YAAY,IAAI,UAAU,QAAQ,QAAQ,aAAa,aAAa,cAAc;AAAA,IACpF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,cAAc;AAClC;","names":[]}
|
|
@@ -5,7 +5,7 @@ import { NextCookieStore } from "../../utils/NextCookieAdapter";
|
|
|
5
5
|
import { createValidators } from "./fnValidators";
|
|
6
6
|
import { refreshCookieWithIdToken } from "./request";
|
|
7
7
|
import { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from "./responses";
|
|
8
|
-
async function sessionEndpointHandler(context,
|
|
8
|
+
async function sessionEndpointHandler(context, config) {
|
|
9
9
|
const { subEndpoint, method, referrer } = context;
|
|
10
10
|
const validators = createValidators(context);
|
|
11
11
|
const {
|
|
@@ -18,7 +18,7 @@ async function sessionEndpointHandler(context, options) {
|
|
|
18
18
|
if (!subEndpoint) {
|
|
19
19
|
return createApiErrorResponse("SUB_ENDPOINT_REQUIRED", "Session sub-endpoint required", 400);
|
|
20
20
|
}
|
|
21
|
-
const sessionsConfig =
|
|
21
|
+
const sessionsConfig = config.endpoints?.sessions;
|
|
22
22
|
const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];
|
|
23
23
|
validateSubEndpoint(subEndpoint, subEndpointConfig);
|
|
24
24
|
if (subEndpointConfig?.security) {
|
|
@@ -56,7 +56,7 @@ async function sessionEndpointHandler(context, options) {
|
|
|
56
56
|
validateCsrfToken(csrfToken || "", csrfCookieValue.value);
|
|
57
57
|
const handleCreateSession = async (cookieStore2, idToken2) => {
|
|
58
58
|
try {
|
|
59
|
-
await refreshCookieWithIdToken(idToken2, cookieStore2,
|
|
59
|
+
await refreshCookieWithIdToken(idToken2, cookieStore2, config, referrer);
|
|
60
60
|
return SessionResponseHelper.createSessionCreationResponse({
|
|
61
61
|
success: true,
|
|
62
62
|
message: "Session created successfully"
|
|
@@ -71,7 +71,7 @@ async function sessionEndpointHandler(context, options) {
|
|
|
71
71
|
if (decodedSession.errors) {
|
|
72
72
|
return createApiErrorResponse("INVALID_SESSION", "Invalid session for refresh", 401);
|
|
73
73
|
}
|
|
74
|
-
const refreshRes = await refreshCookieWithIdToken(idToken2, cookieStore2,
|
|
74
|
+
const refreshRes = await refreshCookieWithIdToken(idToken2, cookieStore2, config);
|
|
75
75
|
return SessionResponseHelper.createRefreshResponse(refreshRes);
|
|
76
76
|
} catch (error2) {
|
|
77
77
|
return createApiErrorResponse("REFRESH_FAILED", "Session refresh failed", 500);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import { clearSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { type RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createValidators } from './fnValidators';\nimport { refreshCookieWithIdToken } from './request';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type { SessionSubEndpoint, TernSecureHandlerOptions } from './types';\n\nexport async function sessionEndpointHandler(\n context: RequestProcessorContext,\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"sourcesContent":["import { clearSessionCookie } from '@tern-secure/backend/admin';\nimport { ternDecodeJwtUnguarded } from '@tern-secure/backend/jwt';\nimport { cookies } from 'next/headers';\n\nimport { NextCookieStore } from '../../utils/NextCookieAdapter';\nimport { type RequestProcessorContext } from './c-authenticateRequestProcessor';\nimport { createValidators } from './fnValidators';\nimport { refreshCookieWithIdToken } from './request';\nimport { createApiErrorResponse, HttpResponseHelper, SessionResponseHelper } from './responses';\nimport type { SessionSubEndpoint, TernSecureHandlerOptions } from './types';\n\nexport async function sessionEndpointHandler(\n context: RequestProcessorContext,\n config: TernSecureHandlerOptions,\n): Promise<Response> {\n const { subEndpoint, method, referrer } = context;\n\n const validators = createValidators(context);\n\n const {\n validateSubEndpoint,\n validateSecurity,\n validateSessionRequest,\n validateCsrfToken,\n validateIdToken,\n } = validators;\n\n if (!subEndpoint) {\n return createApiErrorResponse('SUB_ENDPOINT_REQUIRED', 'Session sub-endpoint required', 400);\n }\n\n const sessionsConfig = config.endpoints?.sessions;\n const subEndpointConfig = sessionsConfig?.subEndpoints?.[subEndpoint];\n\n validateSubEndpoint(subEndpoint, subEndpointConfig);\n\n if (subEndpointConfig?.security) {\n await validateSecurity(subEndpointConfig.security);\n }\n\n const SessionGetHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const handleSessionVerify = async (): Promise<Response> => {\n try {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n if (!sessionCookie) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n const { data: decodedSession, errors } = ternDecodeJwtUnguarded(sessionCookie);\n if (errors) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n\n return SessionResponseHelper.createVerificationResponse(decodedSession);\n } catch (error) {\n return SessionResponseHelper.createUnauthorizedResponse();\n }\n };\n\n switch (subEndpoint) {\n case 'verify':\n return handleSessionVerify();\n default:\n return HttpResponseHelper.createNotFoundResponse();\n }\n };\n\n const SessionPostHandler = async (subEndpoint: SessionSubEndpoint): Promise<Response> => {\n const cookieStore = new NextCookieStore();\n\n const { idToken, csrfToken, error } = await validateSessionRequest();\n if (error) return error;\n\n const csrfCookieValue = await cookieStore.get('_session_terncf');\n validateCsrfToken(csrfToken || '', csrfCookieValue.value);\n\n const handleCreateSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n await refreshCookieWithIdToken(idToken, cookieStore, config, referrer);\n return SessionResponseHelper.createSessionCreationResponse({\n success: true,\n message: 'Session created successfully',\n });\n } catch (error) {\n return createApiErrorResponse('SESSION_CREATION_FAILED', 'Session creation failed', 500);\n }\n };\n\n const handleRefreshSession = async (\n cookieStore: NextCookieStore,\n idToken: string,\n ): Promise<Response> => {\n try {\n const decodedSession = ternDecodeJwtUnguarded(idToken);\n if (decodedSession.errors) {\n return createApiErrorResponse('INVALID_SESSION', 'Invalid session for refresh', 401);\n }\n\n const refreshRes = await refreshCookieWithIdToken(idToken, cookieStore, config);\n return SessionResponseHelper.createRefreshResponse(refreshRes);\n } catch (error) {\n return createApiErrorResponse('REFRESH_FAILED', 'Session refresh failed', 500);\n }\n };\n\n const handleRevokeSession = async (cookieStore: NextCookieStore): Promise<Response> => {\n const res = await clearSessionCookie(cookieStore);\n return SessionResponseHelper.createRevokeResponse(res);\n };\n\n switch (subEndpoint) {\n case 'createsession': {\n validateIdToken(idToken);\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleCreateSession(cookieStore, idToken!);\n }\n\n case 'refresh':\n //eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return handleRefreshSession(cookieStore, idToken!);\n\n case 'revoke':\n return handleRevokeSession(cookieStore);\n\n default:\n return HttpResponseHelper.createSubEndpointNotSupportedResponse();\n }\n };\n\n switch (method) {\n case 'GET':\n return SessionGetHandler(subEndpoint);\n\n case 'POST':\n return SessionPostHandler(subEndpoint);\n\n default:\n return HttpResponseHelper.createMethodNotAllowedResponse();\n }\n}\n"],"mappings":"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","names":["subEndpoint","cookieStore","idToken","error"]}
|
|
@@ -7,13 +7,13 @@ const DEFAULT_CORS_OPTIONS = {
|
|
|
7
7
|
// 24 hours
|
|
8
8
|
};
|
|
9
9
|
const DEFAULT_COOKIE_OPTIONS = {
|
|
10
|
-
//namePrefix: '__session',
|
|
11
|
-
path: "/",
|
|
12
10
|
httpOnly: true,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
path: "/",
|
|
12
|
+
secure: process.env.NODE_ENV === "production",
|
|
13
|
+
sameSite: "strict",
|
|
14
|
+
maxAge: 12 * 60 * 60 * 24,
|
|
15
|
+
// twelve days
|
|
16
|
+
priority: "high"
|
|
17
17
|
};
|
|
18
18
|
const FIXED_TOKEN_CONFIGS = {
|
|
19
19
|
id: {
|
|
@@ -136,17 +136,15 @@ class CookieUtils {
|
|
|
136
136
|
const sessionConfig = cookieOptions.session || {};
|
|
137
137
|
const defaultSession = DEFAULT_COOKIE_OPTIONS.session || {};
|
|
138
138
|
return {
|
|
139
|
-
domain: sessionConfig.domain ?? cookieOptions.domain,
|
|
140
139
|
path: sessionConfig.path ?? cookieOptions.path ?? "/",
|
|
141
140
|
httpOnly: sessionConfig.httpOnly ?? cookieOptions.httpOnly ?? true,
|
|
142
141
|
sameSite: sessionConfig.sameSite ?? cookieOptions.sameSite ?? "lax",
|
|
143
142
|
maxAge: sessionConfig.maxAge ?? defaultSession.maxAge ?? 3600 * 24 * 7
|
|
144
143
|
};
|
|
145
144
|
}
|
|
146
|
-
static getFixedTokenConfig(
|
|
145
|
+
static getFixedTokenConfig(tokenType) {
|
|
147
146
|
const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];
|
|
148
147
|
return {
|
|
149
|
-
domain: cookieOptions.domain,
|
|
150
148
|
path: fixedConfig.path,
|
|
151
149
|
httpOnly: fixedConfig.httpOnly,
|
|
152
150
|
sameSite: fixedConfig.sameSite,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig,\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_COOKIE_OPTIONS: CookieOptions = {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/app-router/admin/types.ts"],"sourcesContent":["import type {\n AuthEndpoint,\n CookieOpts as CookieOptions,\n CorsOptions,\n EndpointConfig,\n SecurityOptions,\n SessionEndpointConfig,\n SessionSubEndpoint,\n TernSecureHandlerOptions,\n TokenCookieConfig,\n} from '@tern-secure/types';\nimport { type NextResponse } from 'next/server';\n\nexport const DEFAULT_CORS_OPTIONS: CorsOptions = {\n allowedOrigins: [],\n allowedMethods: ['GET', 'POST'],\n allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],\n allowCredentials: true,\n maxAge: 86400, // 24 hours\n};\n\nexport const DEFAULT_COOKIE_OPTIONS: CookieOptions = {\n httpOnly: true,\n path: '/',\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 12 * 60 * 60 * 24, // twelve days\n priority: 'high',\n};\n\n\nexport const FIXED_TOKEN_CONFIGS = {\n id: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600, // 1 hour\n },\n refresh: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 30, // 30 days (changes when user events occur)\n },\n signature: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n custom: {\n path: '/',\n httpOnly: true,\n sameSite: 'lax' as const,\n maxAge: 3600 * 24 * 7, // 1 week (as needed)\n },\n} as const;\n\nexport const DEFAULT_SECURITY_OPTIONS: SecurityOptions = {\n requireCSRF: true,\n allowedReferers: [],\n requiredHeaders: {},\n ipWhitelist: [],\n userAgent: {\n block: [],\n allow: [],\n },\n};\n\nexport const DEFAULT_ENDPOINT_CONFIG: EndpointConfig = {\n enabled: true,\n methods: ['GET', 'POST'],\n requireAuth: false,\n security: DEFAULT_SECURITY_OPTIONS,\n};\n\nexport const DEFAULT_SESSIONS_CONFIG: SessionEndpointConfig = {\n ...DEFAULT_ENDPOINT_CONFIG,\n subEndpoints: {\n verify: {\n enabled: true,\n methods: ['GET'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n allowedReferers: [],\n },\n },\n createsession: {\n enabled: true,\n methods: ['POST'],\n requireAuth: false,\n security: {\n requireCSRF: true,\n },\n },\n refresh: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n revoke: {\n enabled: true,\n methods: ['POST'],\n requireAuth: true,\n security: {\n requireCSRF: true,\n },\n },\n },\n};\n\nexport const DEFAULT_HANDLER_OPTIONS: Required<TernSecureHandlerOptions> & {\n endpoints: Required<NonNullable<TernSecureHandlerOptions['endpoints']>>;\n} = {\n cors: DEFAULT_CORS_OPTIONS,\n cookies: DEFAULT_COOKIE_OPTIONS,\n rateLimit: {\n windowMs: 15 * 60 * 1000, // 15 minutes\n maxRequests: 100,\n skipSuccessful: false,\n skipFailedRequests: false,\n },\n security: DEFAULT_SECURITY_OPTIONS,\n endpoints: {\n sessions: DEFAULT_SESSIONS_CONFIG,\n },\n tenantId: '',\n enableCustomToken: false,\n debug: false,\n environment: 'production',\n basePath: '/api/auth',\n};\n\nexport interface ValidationResult {\n error?: NextResponse;\n data?: any;\n}\n\nexport interface ValidationConfig {\n cors?: CorsOptions;\n security?: SecurityOptions;\n endpoint?: {\n name: AuthEndpoint;\n config: EndpointConfig;\n };\n subEndpoint?: {\n name: SessionSubEndpoint;\n config: EndpointConfig;\n };\n requireIdToken?: boolean;\n requireCsrfToken?: boolean;\n}\n\nexport interface ComprehensiveValidationResult {\n isValid: boolean;\n error?: Response;\n corsResponse?: Response;\n sessionData?: {\n body: any;\n idToken?: string;\n csrfToken?: string;\n };\n}\n\nexport type suffix = 'session' | 'id' | 'refresh' | 'signature' | 'custom';\n\nexport class CookieUtils {\n static getCookieName(namePrefix: string, tokenType: suffix): string {\n return `${namePrefix}.${tokenType}`;\n }\n\n static getCookieNames(namePrefix: string) {\n return {\n session: this.getCookieName(namePrefix, 'session'),\n id: this.getCookieName(namePrefix, 'id'),\n refresh: this.getCookieName(namePrefix, 'refresh'),\n signature: this.getCookieName(namePrefix, 'signature'),\n custom: this.getCookieName(namePrefix, 'custom'),\n };\n }\n\n static getSessionConfig(cookieOptions: CookieOptions): TokenCookieConfig {\n const sessionConfig = cookieOptions.session || {};\n const defaultSession = DEFAULT_COOKIE_OPTIONS.session || {};\n\n return {\n path: sessionConfig.path ?? cookieOptions.path ?? '/',\n httpOnly: sessionConfig.httpOnly ?? cookieOptions.httpOnly ?? true,\n sameSite: sessionConfig.sameSite ?? cookieOptions.sameSite ?? 'lax',\n maxAge: sessionConfig.maxAge ?? defaultSession.maxAge ?? 3600 * 24 * 7,\n };\n }\n\n static getFixedTokenConfig(\n tokenType: Exclude<suffix, 'session'>,\n ): TokenCookieConfig {\n const fixedConfig = FIXED_TOKEN_CONFIGS[tokenType];\n\n return {\n path: fixedConfig.path,\n httpOnly: fixedConfig.httpOnly,\n sameSite: fixedConfig.sameSite,\n maxAge: fixedConfig.maxAge,\n };\n }\n\n static validateSessionMaxAge(maxAge: number): boolean {\n const minAge = 300; // 5 minutes\n const maxAgeLimit = 3600 * 24 * 14; // 2 weeks\n return maxAge >= minAge && maxAge <= maxAgeLimit;\n }\n}\n\nexport {\n AuthEndpoint,\n CookieOptions,\n CorsOptions,\n SecurityOptions,\n SessionSubEndpoint,\n EndpointConfig,\n SessionEndpointConfig,\n TernSecureHandlerOptions,\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
constants,
|
|
3
|
-
createTernSecureRequest,
|
|
4
|
-
enableDebugLogging
|
|
5
|
-
} from "@tern-secure/backend";
|
|
1
|
+
import { constants, createTernSecureRequest, enableDebugLogging } from "@tern-secure/backend";
|
|
6
2
|
import { notFound as nextjsNotFound } from "next/navigation";
|
|
7
3
|
import { NextResponse } from "next/server";
|
|
8
4
|
import { isRedirect, setHeader } from "../utils/response";
|
|
@@ -78,9 +74,6 @@ const ternSecureMiddleware = (...args) => {
|
|
|
78
74
|
return handlerResult;
|
|
79
75
|
};
|
|
80
76
|
const nextMiddleware = async (request2, event2) => {
|
|
81
|
-
if (isFirebaseCookieRequest(request2)) {
|
|
82
|
-
return handleFirebaseAuthRequest(request2);
|
|
83
|
-
}
|
|
84
77
|
return withAuthNextMiddleware(request2, event2);
|
|
85
78
|
};
|
|
86
79
|
if (request && event) {
|
|
@@ -102,18 +95,6 @@ const parseHandlerAndOptions = (args) => {
|
|
|
102
95
|
(args.length === 2 ? args[1] : typeof args[0] === "function" ? {} : args[0]) || {}
|
|
103
96
|
];
|
|
104
97
|
};
|
|
105
|
-
const isFirebaseRequest = (request) => request.nextUrl.pathname.startsWith("/__/");
|
|
106
|
-
const rewriteFirebaseRequest = (options, request) => {
|
|
107
|
-
const newUrl = new URL(request.url);
|
|
108
|
-
newUrl.host = options.firebaseOptions?.authDomain || "";
|
|
109
|
-
newUrl.port = "";
|
|
110
|
-
return NextResponse.rewrite(newUrl);
|
|
111
|
-
};
|
|
112
|
-
const finalTarget = (request) => {
|
|
113
|
-
const finalTargetUrl = request.nextUrl.searchParams.get("finalTarget");
|
|
114
|
-
return finalTargetUrl ? new URL(finalTargetUrl, request.url) : void 0;
|
|
115
|
-
};
|
|
116
|
-
const isFirebaseCookieRequest = (request) => request.nextUrl.pathname === "/__cookies__";
|
|
117
98
|
const createMiddlewareRedirects = (ternSecureRequest) => {
|
|
118
99
|
const redirectToSignIn = (opts = {}) => {
|
|
119
100
|
const url = ternSecureRequest.ternUrl.toString();
|
|
@@ -172,92 +153,6 @@ const handleControlError = (error, ternSecureRequest, nextrequest) => {
|
|
|
172
153
|
}
|
|
173
154
|
throw error;
|
|
174
155
|
};
|
|
175
|
-
const handleFirebaseAuthRequest = async (request) => {
|
|
176
|
-
console.log("Checking for __cookies__ path");
|
|
177
|
-
const isDevMode = process.env.NODE_ENV === "development";
|
|
178
|
-
const ID_TOKEN_COOKIE_NAME = isDevMode ? `__dev_FIREBASE_[DEFAULT]` : `__HOST-FIREBASE_[DEFAULT]`;
|
|
179
|
-
const REFRESH_TOKEN_COOKIE_NAME = isDevMode ? "__dev_FIREBASEID_[DEFAULT]" : `__HOST-FIREBASEID_[DEFAULT]`;
|
|
180
|
-
const ID_TOKEN_COOKIE = {
|
|
181
|
-
path: "/",
|
|
182
|
-
secure: !isDevMode,
|
|
183
|
-
sameSite: "strict",
|
|
184
|
-
partitioned: true,
|
|
185
|
-
name: ID_TOKEN_COOKIE_NAME,
|
|
186
|
-
maxAge: 3456e4,
|
|
187
|
-
priority: "high"
|
|
188
|
-
};
|
|
189
|
-
const REFRESH_TOKEN_COOKIE = {
|
|
190
|
-
...ID_TOKEN_COOKIE,
|
|
191
|
-
httpOnly: true,
|
|
192
|
-
name: REFRESH_TOKEN_COOKIE_NAME
|
|
193
|
-
};
|
|
194
|
-
if (request.nextUrl.pathname === "/__cookies__") {
|
|
195
|
-
console.log("Handling /__cookies__ request");
|
|
196
|
-
const method = request.method;
|
|
197
|
-
if (method === "DELETE") {
|
|
198
|
-
const response2 = new NextResponse("");
|
|
199
|
-
response2.cookies.delete({ ...ID_TOKEN_COOKIE, maxAge: 0 });
|
|
200
|
-
response2.cookies.delete({ ...REFRESH_TOKEN_COOKIE, maxAge: 0 });
|
|
201
|
-
return response2;
|
|
202
|
-
}
|
|
203
|
-
const headers = {};
|
|
204
|
-
const headerNames = [
|
|
205
|
-
"content-type",
|
|
206
|
-
"X-Firebase-Client",
|
|
207
|
-
"X-Firebase-gmpid",
|
|
208
|
-
"X-Firebase-AppCheck",
|
|
209
|
-
"X-Client-Version"
|
|
210
|
-
];
|
|
211
|
-
headerNames.forEach((headerName) => {
|
|
212
|
-
const headerValue = request.headers.get(headerName);
|
|
213
|
-
if (headerValue) {
|
|
214
|
-
headers[headerName] = headerValue;
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
const finalTargetParam = request.nextUrl.searchParams.get("finalTarget");
|
|
218
|
-
const url = new URL(finalTargetParam || "");
|
|
219
|
-
let body = request.body;
|
|
220
|
-
const isTokenRequest = !!url.pathname.match(/^(\/securetoken\.googleapis\.com)?\/v1\/token/);
|
|
221
|
-
const isSignInRequest = !!url.pathname.match(
|
|
222
|
-
/^(\/identitytoolkit\.googleapis\.com)?\/v1\/accounts:signInWith/
|
|
223
|
-
);
|
|
224
|
-
if (!isTokenRequest && !isSignInRequest)
|
|
225
|
-
throw new Error("Could not determine the request type to proxy");
|
|
226
|
-
if (isTokenRequest) {
|
|
227
|
-
body = await request.text();
|
|
228
|
-
const bodyParams = new URLSearchParams(body.trim());
|
|
229
|
-
if (bodyParams.has("refresh_token")) {
|
|
230
|
-
const refreshToken2 = request.cookies.get(REFRESH_TOKEN_COOKIE.name)?.value;
|
|
231
|
-
if (refreshToken2) {
|
|
232
|
-
bodyParams.set("refresh_token", refreshToken2);
|
|
233
|
-
body = bodyParams.toString();
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
const response = await fetch(url, { method, body, headers });
|
|
238
|
-
const json = await response.json();
|
|
239
|
-
if (!response.ok) {
|
|
240
|
-
return NextResponse.json(json, { status: response.status, statusText: response.statusText });
|
|
241
|
-
}
|
|
242
|
-
let refreshToken, idToken, maxAge;
|
|
243
|
-
if (isSignInRequest) {
|
|
244
|
-
refreshToken = json.refreshToken;
|
|
245
|
-
idToken = json.idToken;
|
|
246
|
-
maxAge = json.expiresIn;
|
|
247
|
-
json.refreshToken = "REDACTED";
|
|
248
|
-
} else {
|
|
249
|
-
refreshToken = json.refresh_token;
|
|
250
|
-
idToken = json.id_token;
|
|
251
|
-
maxAge = json.expires_in;
|
|
252
|
-
json.refresh_token = "REDACTED";
|
|
253
|
-
}
|
|
254
|
-
const nextResponse = NextResponse.json(json);
|
|
255
|
-
if (idToken) nextResponse.cookies.set({ ...ID_TOKEN_COOKIE, maxAge, value: idToken });
|
|
256
|
-
if (refreshToken) nextResponse.cookies.set({ ...REFRESH_TOKEN_COOKIE, value: refreshToken });
|
|
257
|
-
return nextResponse;
|
|
258
|
-
}
|
|
259
|
-
return null;
|
|
260
|
-
};
|
|
261
156
|
export {
|
|
262
157
|
redirectAdapter,
|
|
263
158
|
ternSecureMiddleware
|
|
@@ -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 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":"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","names":["request","event","response","refreshToken"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ternSecureEdgeMiddleware.ts"],"sourcesContent":["import type {\r\n AuthenticateRequestOptions,\r\n AuthObject,\r\n TernSecureRequest,\r\n} from '@tern-secure/backend';\r\nimport { constants, createTernSecureRequest, enableDebugLogging } 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 { 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 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 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 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 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 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\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"],"mappings":"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","names":["request","event"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { NextCookieStore } from '../../utils/NextCookieAdapter';
|
|
2
2
|
import type { TernSecureHandlerOptions } from './types';
|
|
3
|
-
export declare function refreshCookieWithIdToken(idToken: string, cookieStore: NextCookieStore,
|
|
3
|
+
export declare function refreshCookieWithIdToken(idToken: string, cookieStore: NextCookieStore, config?: TernSecureHandlerOptions, referrer?: string): Promise<void>;
|
|
4
4
|
//# sourceMappingURL=request.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/request.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AASrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/request.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AASrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAExD,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,eAAe,EAC5B,MAAM,CAAC,EAAE,wBAAwB,EACjC,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAiDf"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type RequestProcessorContext } from './c-authenticateRequestProcessor';
|
|
2
2
|
import type { TernSecureHandlerOptions } from './types';
|
|
3
|
-
export declare function sessionEndpointHandler(context: RequestProcessorContext,
|
|
3
|
+
export declare function sessionEndpointHandler(context: RequestProcessorContext, config: TernSecureHandlerOptions): Promise<Response>;
|
|
4
4
|
//# sourceMappingURL=sessionHandlers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionHandlers.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAIhF,OAAO,KAAK,EAAsB,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAE5E,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,uBAAuB,EAChC,
|
|
1
|
+
{"version":3,"file":"sessionHandlers.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/sessionHandlers.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAIhF,OAAO,KAAK,EAAsB,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAE5E,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,uBAAuB,EAChC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,QAAQ,CAAC,CAiInB"}
|
|
@@ -73,7 +73,7 @@ export declare class CookieUtils {
|
|
|
73
73
|
custom: string;
|
|
74
74
|
};
|
|
75
75
|
static getSessionConfig(cookieOptions: CookieOptions): TokenCookieConfig;
|
|
76
|
-
static getFixedTokenConfig(
|
|
76
|
+
static getFixedTokenConfig(tokenType: Exclude<suffix, 'session'>): TokenCookieConfig;
|
|
77
77
|
static validateSessionMaxAge(maxAge: number): boolean;
|
|
78
78
|
}
|
|
79
79
|
export { AuthEndpoint, CookieOptions, CorsOptions, SecurityOptions, SessionSubEndpoint, EndpointConfig, SessionEndpointConfig, TernSecureHandlerOptions, };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,IAAI,aAAa,EAC3B,WAAW,EACX,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,oBAAoB,EAAE,WAMlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,IAAI,aAAa,EAC3B,WAAW,EACX,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,oBAAoB,EAAE,WAMlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,aAOpC,CAAC;AAGF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;CAyBtB,CAAC;AAEX,eAAO,MAAM,wBAAwB,EAAE,eAStC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,cAKrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,qBAqCrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,wBAAwB,CAAC,GAAG;IACzE,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,wBAAwB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAmBzE,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,QAAQ,CAAC,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,MAAM,EAAE,cAAc,CAAC;KACxB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,kBAAkB,CAAC;QACzB,MAAM,EAAE,cAAc,CAAC;KACxB,CAAC;IACF,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,YAAY,CAAC,EAAE,QAAQ,CAAC;IACxB,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,GAAG,CAAC;QACV,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,MAAM,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3E,qBAAa,WAAW;IACtB,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAInE,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM;;;;;;;IAUxC,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,aAAa,GAAG,iBAAiB;IAYxE,MAAM,CAAC,mBAAmB,CACxB,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,GACpC,iBAAiB;IAWpB,MAAM,CAAC,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;CAKtD;AAED,OAAO,EACL,YAAY,EACZ,aAAa,EACb,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,wBAAwB,GACzB,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { TernSecureConfig } from '@tern-secure/types';
|
|
1
|
+
import type { AuthenticateRequestOptions, AuthObject } from '@tern-secure/backend';
|
|
3
2
|
import type { NextMiddleware, NextRequest } from 'next/server';
|
|
4
3
|
import { NextResponse } from 'next/server';
|
|
5
4
|
import { type AuthProtect } from './protect';
|
|
@@ -14,9 +13,8 @@ export interface MiddlewareAuth {
|
|
|
14
13
|
protect: AuthProtect;
|
|
15
14
|
}
|
|
16
15
|
type MiddlewareHandler = (auth: MiddlewareAuth, request: NextMiddlewareRequestParam, event: NextMiddlewareEvtParam) => NextMiddlewareReturn;
|
|
17
|
-
export interface MiddlewareOptions extends
|
|
16
|
+
export interface MiddlewareOptions extends AuthenticateRequestOptions {
|
|
18
17
|
debug?: boolean;
|
|
19
|
-
firebaseOptions?: TernSecureConfig;
|
|
20
18
|
}
|
|
21
19
|
type MiddlewareOptionsCallback = (req: NextRequest) => MiddlewareOptions | Promise<MiddlewareOptions>;
|
|
22
20
|
interface TernSecureMiddleware {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ternSecureEdgeMiddleware.d.ts","sourceRoot":"","sources":["../../../src/server/ternSecureEdgeMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"ternSecureEdgeMiddleware.d.ts","sourceRoot":"","sources":["../../../src/server/ternSecureEdgeMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,0BAA0B,EAC1B,UAAU,EAEX,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C,OAAO,EAAE,KAAK,WAAW,EAAiB,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9D,OAAO,KAAK,EACV,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAGjB,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG;IAC9C,gBAAgB,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACxC,gBAAgB,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;CACzC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAElC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED,KAAK,iBAAiB,GAAG,CACvB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,0BAA0B,EACnC,KAAK,EAAE,sBAAsB,KAC1B,oBAAoB,CAAC;AAE1B,MAAM,WAAW,iBAAkB,SAAQ,0BAA0B;IACnE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AACD,KAAK,yBAAyB,GAAG,CAC/B,GAAG,EAAE,WAAW,KACb,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEpD,UAAU,oBAAoB;IAC5B;;;OAGG;IACH,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,cAAc,CAAC;IAE1E;;;OAGG;IACH,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,yBAAyB,GAAG,cAAc,CAAC;IAElF;;;OAGG;IACH,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,cAAc,CAAC;IAC9C;;;OAGG;IACH,CAAC,OAAO,EAAE,0BAA0B,EAAE,KAAK,EAAE,sBAAsB,GAAG,oBAAoB,CAAC;CAC5F;AAED,eAAO,MAAM,oBAAoB,EAuF3B,oBAAoB,CAAC;AAwD3B,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,GAAG,GAAG,0BAIhD,CAAC"}
|
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.v20251008131428",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
"jose": "^5.9.6",
|
|
64
64
|
"server-only": "^0.0.1",
|
|
65
65
|
"tslib": "2.4.1",
|
|
66
|
-
"@tern-secure/backend": "1.2.0-canary.
|
|
67
|
-
"@tern-secure/react": "1.2.0-canary.
|
|
68
|
-
"@tern-secure/shared": "1.3.0-canary.
|
|
69
|
-
"@tern-secure/types": "1.1.0-canary.
|
|
66
|
+
"@tern-secure/backend": "1.2.0-canary.v20251008131428",
|
|
67
|
+
"@tern-secure/react": "1.2.0-canary.v20251008131428",
|
|
68
|
+
"@tern-secure/shared": "1.3.0-canary.v20251008131428",
|
|
69
|
+
"@tern-secure/types": "1.1.0-canary.v20251008131428"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"next": "^13.0.0 || ^14.0.0 || ^15.0.0",
|