@tern-secure/backend 1.2.0-canary.v20251029025859 → 1.2.0-canary.v20251108045933
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/__tests__/request.test.d.ts +2 -0
- package/dist/__tests__/request.test.d.ts.map +1 -0
- package/dist/admin/index.js +31 -8
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +17 -8
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/nextSessionTernSecure.d.ts.map +1 -1
- package/dist/admin/sessionTernSecure.d.ts.map +1 -1
- package/dist/auth/getauth.d.ts +1 -0
- package/dist/auth/getauth.d.ts.map +1 -1
- package/dist/auth/index.js +49 -31
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +3 -3
- package/dist/{chunk-IBABNFOK.mjs → chunk-ASGV4MFO.mjs} +2 -2
- package/dist/{chunk-5AP2WM3W.mjs → chunk-DDUNOEIM.mjs} +20 -31
- package/dist/chunk-DDUNOEIM.mjs.map +1 -0
- package/dist/{chunk-VY5FVZL2.mjs → chunk-DFAJCSBJ.mjs} +17 -3
- package/dist/chunk-DFAJCSBJ.mjs.map +1 -0
- package/dist/{chunk-A5G3CWO5.mjs → chunk-MS6L7M3C.mjs} +9 -4
- package/dist/chunk-MS6L7M3C.mjs.map +1 -0
- package/dist/constants.d.ts +13 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.js +156 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -11
- package/dist/index.mjs.map +1 -1
- package/dist/jwt/index.js +19 -30
- package/dist/jwt/index.js.map +1 -1
- package/dist/jwt/index.mjs +1 -1
- package/dist/jwt/verifyJwt.d.ts.map +1 -1
- package/dist/tokens/authstate.d.ts +16 -4
- package/dist/tokens/authstate.d.ts.map +1 -1
- package/dist/tokens/c-authenticateRequestProcessor.d.ts +5 -0
- package/dist/tokens/c-authenticateRequestProcessor.d.ts.map +1 -1
- package/dist/tokens/request.d.ts.map +1 -1
- package/dist/tokens/types.d.ts +4 -0
- package/dist/tokens/types.d.ts.map +1 -1
- package/package.json +9 -7
- package/dist/chunk-5AP2WM3W.mjs.map +0 -1
- package/dist/chunk-A5G3CWO5.mjs.map +0 -1
- package/dist/chunk-VY5FVZL2.mjs.map +0 -1
- /package/dist/{chunk-IBABNFOK.mjs.map → chunk-ASGV4MFO.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tokens/keys.ts","../src/tokens/verify.ts","../src/auth/getauth.ts"],"sourcesContent":["import { type RemoteJWKSetOptions } from 'jose';\n\nimport {\n CACHE_CONTROL_REGEX,\n DEFAULT_CACHE_DURATION,\n GOOGLE_PUBLIC_KEYS_URL,\n MAX_CACHE_LAST_UPDATED_AT_SECONDS\n} from '../constants';\nimport { TokenVerificationError, TokenVerificationErrorReason } from '../utils/errors';\n\nexport type PublicKeys = { [key: string]: string };\n\ninterface PublicKeysResponse {\n keys: PublicKeys;\n expiresAt: number;\n}\n\nexport type LoadJWKFromRemoteOptions = RemoteJWKSetOptions & {\n kid: string;\n keyURL?: string;\n skipJwksCache?: boolean;\n};\n\ntype CertificateCache = Record<string, string>;\n\nlet cache: CertificateCache = {};\nlet lastUpdatedAt = 0;\nlet googleExpiresAt = 0;\n\nfunction getFromCache(kid: string) {\n return cache[kid];\n}\n\nfunction getCacheValues() {\n return Object.values(cache);\n}\n\nfunction setInCache(kid: string, certificate: string, shouldExpire = true) {\n cache[kid] = certificate;\n lastUpdatedAt = shouldExpire ? Date.now() : -1;\n}\n\nasync function fetchPublicKeys(keyUrl: string): Promise<PublicKeysResponse> {\n const url = new URL(keyUrl);\n const response = await fetch(url);\n if (!response.ok) {\n throw new TokenVerificationError({\n message: `Error loading public keys from ${url.href} with code=${response.status} `,\n reason: TokenVerificationErrorReason.TokenInvalid,\n });\n }\n\n const data = await response.json();\n const expiresAt = getExpiresAt(response);\n\n return {\n keys: data,\n expiresAt,\n };\n}\n\nexport async function loadJWKFromRemote({\n keyURL = GOOGLE_PUBLIC_KEYS_URL,\n skipJwksCache,\n kid,\n}: LoadJWKFromRemoteOptions): Promise<string> {\n if (skipJwksCache || isCacheExpired() || !getFromCache(kid)) {\n const { keys, expiresAt } = await fetchPublicKeys(keyURL);\n\n if (!keys || Object.keys(keys).length === 0) {\n throw new TokenVerificationError({\n message: `The JWKS endpoint ${keyURL} returned no keys`,\n reason: TokenVerificationErrorReason.RemoteJWKFailedToLoad,\n });\n }\n googleExpiresAt = expiresAt;\n\n Object.entries(keys).forEach(([keyId, cert]) => {\n setInCache(keyId, cert);\n });\n }\n const cert = getFromCache(kid);\n if (!cert) {\n getCacheValues();\n const availableKids = Object.keys(cache).sort().join(', ');\n\n throw new TokenVerificationError({\n message: `No public key found for kid \"${kid}\". Available kids: [${availableKids}]`,\n reason: TokenVerificationErrorReason.TokenInvalid,\n });\n }\n return cert;\n}\n\nfunction isCacheExpired() {\n const now = Date.now();\n if (lastUpdatedAt === -1) {\n return false;\n }\n\n const cacheAge = now - lastUpdatedAt;\n const maxCacheAge = MAX_CACHE_LAST_UPDATED_AT_SECONDS * 1000;\n const localCacheExpired = cacheAge >= maxCacheAge;\n const googleCacheExpired = now >= googleExpiresAt;\n\n const isExpired = localCacheExpired || googleCacheExpired;\n\n if (isExpired) {\n cache = {};\n }\n\n return isExpired;\n}\n\nfunction getExpiresAt(res: Response) {\n const cacheControlHeader = res.headers.get('cache-control');\n if (!cacheControlHeader) {\n return Date.now() + DEFAULT_CACHE_DURATION;\n }\n const maxAgeMatch = cacheControlHeader.match(CACHE_CONTROL_REGEX);\n const maxAge = maxAgeMatch ? parseInt(maxAgeMatch[1], 10) : DEFAULT_CACHE_DURATION / 1000;\n\n return Date.now() + maxAge * 1000;\n}\n\nexport const getCacheStats = () => ({\n localExpiry: lastUpdatedAt + MAX_CACHE_LAST_UPDATED_AT_SECONDS * 1000,\n googleExpiry: googleExpiresAt,\n cacheCount: Object.keys(cache).length,\n});\n","import type { DecodedIdToken, TernSecureConfig, TernSecureUserData } from '@tern-secure/types';\n\nimport type { JwtReturnType } from '../jwt/types';\nimport { ternDecodeJwt, verifyJwt, type VerifyJwtOptions } from '../jwt/verifyJwt';\nimport { TokenVerificationError, TokenVerificationErrorReason } from '../utils/errors';\nimport type { LoadJWKFromRemoteOptions } from './keys';\nimport { loadJWKFromRemote } from './keys';\n\nexport type VerifyTokenVOptions = Omit<VerifyJwtOptions, 'key'> & Omit<LoadJWKFromRemoteOptions, 'kid'> & {\n jwtKey?: string;\n};\n\nexport { TernSecureConfig, TernSecureUserData };\n\nexport async function verifyToken(\n token: string,\n options: VerifyTokenVOptions,\n): Promise<JwtReturnType<DecodedIdToken, TokenVerificationError>> {\n const { data: decodedResult, errors } = ternDecodeJwt(token);\n\n if (errors) {\n return { errors };\n }\n\n const { header } = decodedResult;\n const { kid } = header;\n\n if (!kid) {\n return {\n errors: [\n new TokenVerificationError({\n reason: TokenVerificationErrorReason.TokenInvalid,\n message: 'JWT \"kid\" header is missing.',\n }),\n ],\n };\n }\n\n try {\n const key = options.jwtKey || (await loadJWKFromRemote({ ...options, kid }));\n\n if (!key) {\n return {\n errors: [\n new TokenVerificationError({\n reason: TokenVerificationErrorReason.TokenInvalid,\n message: `No public key found for kid \"${kid}\".`,\n }),\n ],\n };\n }\n return await verifyJwt(token, { ...options, key });\n } catch (error) {\n if (error instanceof TokenVerificationError) {\n return { errors: [error] };\n }\n return {\n errors: [error as TokenVerificationError],\n };\n }\n}\n","import { createCustomToken } from '../jwt/customJwt';\nimport type { AuthenticateRequestOptions, TernSecureUserData } from '../tokens/types';\nimport { verifyToken } from '../tokens/verify';\n\nexport interface IdAndRefreshTokens {\n idToken: string;\n refreshToken: string;\n}\n\nexport interface CustomTokens {\n auth_time: number;\n idToken: string;\n refreshToken: string;\n customToken: string;\n}\n\ninterface CustomForIdAndRefreshTokenOptions {\n tenantId?: string;\n appCheckToken?: string;\n referer?: string;\n}\n\ninterface FirebaseRefreshTokenResponse {\n kind: string;\n id_token: string;\n refresh_token: string;\n expires_in: string;\n isNewUser: boolean;\n}\n\ninterface FirebaseCustomTokenResponse {\n kind: string;\n idToken: string;\n refreshToken: string;\n expiresIn: string;\n isNewUser: boolean;\n}\n\ntype AuthResult<T = any> = { data: T; error: null } | { data: null; error: any };\n\nconst API_KEY_ERROR = 'API Key is required';\nconst NO_DATA_ERROR = 'No token data received';\n\nfunction parseFirebaseResponse<T>(data: unknown): T {\n if (typeof data === 'string') {\n try {\n return JSON.parse(data) as T;\n } catch (error) {\n throw new Error(`Failed to parse Firebase response: ${error}`);\n }\n }\n return data as T;\n}\n\nexport function getAuth(options: AuthenticateRequestOptions) {\n const { apiKey } = options;\n const firebaseApiKey = options.firebaseConfig?.apiKey;\n const effectiveApiKey = apiKey || firebaseApiKey;\n\n async function getUserData(idToken?: string, localId?: string): Promise<TernSecureUserData> {\n if (!effectiveApiKey) {\n throw new Error(API_KEY_ERROR);\n }\n const response = await options.apiClient?.userData.getUserData(effectiveApiKey, {\n idToken,\n localId,\n });\n\n if (!response?.data) {\n throw new Error(NO_DATA_ERROR);\n }\n\n const parsedData = parseFirebaseResponse<TernSecureUserData>(response.data);\n return parsedData;\n }\n\n async function refreshExpiredIdToken(\n refreshToken: string,\n opts: CustomForIdAndRefreshTokenOptions,\n ): Promise<AuthResult> {\n if (!effectiveApiKey) {\n return { data: null, error: new Error(API_KEY_ERROR) };\n }\n const response = await options.apiClient?.tokens.refreshToken(effectiveApiKey, {\n refresh_token: refreshToken,\n request_origin: opts.referer,\n });\n\n if (!response?.data) {\n return {\n data: null,\n error: new Error(NO_DATA_ERROR),\n };\n }\n\n const parsedData = parseFirebaseResponse<FirebaseRefreshTokenResponse>(response.data);\n\n return {\n data: {\n idToken: parsedData.id_token,\n refreshToken: parsedData.refresh_token,\n },\n error: null,\n };\n }\n\n async function customForIdAndRefreshToken(\n customToken: string,\n opts: CustomForIdAndRefreshTokenOptions,\n ): Promise<IdAndRefreshTokens> {\n if (!effectiveApiKey) {\n throw new Error('API Key is required to create custom token');\n }\n const response = await options.apiClient?.tokens.exchangeCustomForIdAndRefreshTokens(\n effectiveApiKey,\n {\n token: customToken,\n returnSecureToken: true,\n },\n {\n referer: opts.referer,\n },\n );\n\n if (!response?.data) {\n throw new Error('No data received from Firebase token exchange');\n }\n\n const parsedData = parseFirebaseResponse<FirebaseCustomTokenResponse>(response.data);\n\n return {\n idToken: parsedData.idToken,\n refreshToken: parsedData.refreshToken,\n };\n }\n\n async function createCustomIdAndRefreshToken(\n idToken: string,\n opts: CustomForIdAndRefreshTokenOptions,\n ): Promise<CustomTokens> {\n const decoded = await verifyToken(idToken, options);\n const { data, errors } = decoded;\n if (errors) {\n throw errors[0];\n }\n\n //todo:\n /**\n * For sensitive applications, the auth_time should be checked before issuing the session cookie, minimizing the window of attack in case an ID token is stolen:\n */\n //if (new Date().getTime() / 1000 - data.auth_time < 5 * 60) {\n //proceed\n //}\n\n const customToken = await createCustomToken(data.uid, {\n emailVerified: data.email_verified,\n source_sign_in_provider: data.firebase.sign_in_provider,\n });\n\n const idAndRefreshTokens = await customForIdAndRefreshToken(customToken, {\n referer: opts.referer,\n });\n\n const decodedCustomIdToken = await verifyToken(idAndRefreshTokens.idToken, options);\n if (decodedCustomIdToken.errors) {\n throw decodedCustomIdToken.errors[0];\n }\n\n return {\n ...idAndRefreshTokens,\n customToken,\n auth_time: decodedCustomIdToken.data.auth_time,\n };\n }\n\n return {\n getUserData,\n customForIdAndRefreshToken,\n createCustomIdAndRefreshToken,\n refreshExpiredIdToken,\n };\n}\n"],"mappings":"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","names":["cert"]}
|
package/dist/constants.d.ts
CHANGED
|
@@ -17,10 +17,11 @@ export declare const constants: {
|
|
|
17
17
|
};
|
|
18
18
|
readonly Cookies: {
|
|
19
19
|
readonly Session: "__session";
|
|
20
|
-
readonly CsrfToken: "
|
|
20
|
+
readonly CsrfToken: "__terncf";
|
|
21
21
|
readonly IdToken: "TernSecure_[DEFAULT]";
|
|
22
22
|
readonly Refresh: "TernSecureID_[DEFAULT]";
|
|
23
23
|
readonly Custom: "__custom";
|
|
24
|
+
readonly TernAut: "tern_aut";
|
|
24
25
|
readonly Handshake: "__ternsecure_handshake";
|
|
25
26
|
readonly DevBrowser: "__ternsecure_db_jwt";
|
|
26
27
|
readonly RedirectCount: "__ternsecure_redirect_count";
|
|
@@ -58,6 +59,17 @@ export declare const constants: {
|
|
|
58
59
|
readonly ContentTypes: {
|
|
59
60
|
readonly Json: "application/json";
|
|
60
61
|
};
|
|
62
|
+
readonly QueryParameters: {
|
|
63
|
+
readonly TernSynced: "__tern_synced";
|
|
64
|
+
readonly SuffixedCookies: "suffixed_cookies";
|
|
65
|
+
readonly TernRedirectUrl: "__tern_redirect_url";
|
|
66
|
+
readonly DevBrowser: "__ternsecure_db_jwt";
|
|
67
|
+
readonly Handshake: "__ternsecure_handshake";
|
|
68
|
+
readonly HandshakeHelp: "__tern_help";
|
|
69
|
+
readonly LegacyDevBrowser: "__dev_session";
|
|
70
|
+
readonly HandshakeReason: "__tern_hs_reason";
|
|
71
|
+
readonly HandshakeNonce: "__ternsecure_handshake_nonce";
|
|
72
|
+
};
|
|
61
73
|
};
|
|
62
74
|
export type Constants = typeof constants;
|
|
63
75
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,6FACyD,CAAC;AAC7F,eAAO,MAAM,8BAA8B,0EAC8B,CAAC;AAE1E,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAClD,eAAO,MAAM,mBAAmB,QAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,6FACyD,CAAC;AAC7F,eAAO,MAAM,8BAA8B,0EAC8B,CAAC;AAE1E,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAClD,eAAO,MAAM,mBAAmB,QAAkB,CAAC;AAwEnD;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAMZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -54,15 +54,28 @@ var Attributes = {
|
|
|
54
54
|
};
|
|
55
55
|
var Cookies = {
|
|
56
56
|
Session: "__session",
|
|
57
|
-
CsrfToken: "
|
|
57
|
+
CsrfToken: "__terncf",
|
|
58
58
|
IdToken: "TernSecure_[DEFAULT]",
|
|
59
59
|
Refresh: "TernSecureID_[DEFAULT]",
|
|
60
60
|
Custom: "__custom",
|
|
61
|
+
TernAut: "tern_aut",
|
|
61
62
|
Handshake: "__ternsecure_handshake",
|
|
62
63
|
DevBrowser: "__ternsecure_db_jwt",
|
|
63
64
|
RedirectCount: "__ternsecure_redirect_count",
|
|
64
65
|
HandshakeNonce: "__ternsecure_handshake_nonce"
|
|
65
66
|
};
|
|
67
|
+
var QueryParameters = {
|
|
68
|
+
TernSynced: "__tern_synced",
|
|
69
|
+
SuffixedCookies: "suffixed_cookies",
|
|
70
|
+
TernRedirectUrl: "__tern_redirect_url",
|
|
71
|
+
// use the reference to Cookies to indicate that it's the same value
|
|
72
|
+
DevBrowser: Cookies.DevBrowser,
|
|
73
|
+
Handshake: Cookies.Handshake,
|
|
74
|
+
HandshakeHelp: "__tern_help",
|
|
75
|
+
LegacyDevBrowser: "__dev_session",
|
|
76
|
+
HandshakeReason: "__tern_hs_reason",
|
|
77
|
+
HandshakeNonce: Cookies.HandshakeNonce
|
|
78
|
+
};
|
|
66
79
|
var Headers2 = {
|
|
67
80
|
Accept: "accept",
|
|
68
81
|
AuthMessage: "x-ternsecure-auth-message",
|
|
@@ -99,7 +112,8 @@ var constants = {
|
|
|
99
112
|
Attributes,
|
|
100
113
|
Cookies,
|
|
101
114
|
Headers: Headers2,
|
|
102
|
-
ContentTypes
|
|
115
|
+
ContentTypes,
|
|
116
|
+
QueryParameters
|
|
103
117
|
};
|
|
104
118
|
|
|
105
119
|
// src/createRedirect.ts
|
|
@@ -233,16 +247,20 @@ function mapJwtPayloadToDecodedIdToken(payload) {
|
|
|
233
247
|
// src/tokens/authstate.ts
|
|
234
248
|
var AuthStatus = {
|
|
235
249
|
SignedIn: "signed-in",
|
|
236
|
-
SignedOut: "signed-out"
|
|
250
|
+
SignedOut: "signed-out",
|
|
251
|
+
Handshake: "handshake"
|
|
237
252
|
};
|
|
238
253
|
var AuthErrorReason = {
|
|
239
|
-
|
|
254
|
+
AuthTimeout: "auth-timeout",
|
|
255
|
+
SessionTokenAndAuthMissing: "session-token-and-aut-missing",
|
|
240
256
|
SessionTokenMissing: "session-token-missing",
|
|
241
257
|
SessionTokenExpired: "session-token-expired",
|
|
242
|
-
|
|
258
|
+
SessionTokenIATBeforeTernAUT: "session-token-iat-before-tern-aut",
|
|
243
259
|
SessionTokenNBF: "session-token-nbf",
|
|
244
260
|
SessionTokenIatInTheFuture: "session-token-iat-in-the-future",
|
|
245
|
-
|
|
261
|
+
SessionTokenWithoutTernAUT: "session-token-but-no-tern-uat",
|
|
262
|
+
TernAutWithoutSessionToken: "tern-aut-but-no-session-token",
|
|
263
|
+
SyncRequired: "sync-required",
|
|
246
264
|
UnexpectedError: "unexpected-error"
|
|
247
265
|
};
|
|
248
266
|
function createHasAuthorization(decodedIdToken) {
|
|
@@ -294,6 +312,7 @@ function signedIn(authCtx, sessionClaims, headers = new Headers(), token) {
|
|
|
294
312
|
const authObject = signedInAuthObject(token, sessionClaims);
|
|
295
313
|
return {
|
|
296
314
|
status: AuthStatus.SignedIn,
|
|
315
|
+
message: null,
|
|
297
316
|
reason: null,
|
|
298
317
|
signInUrl: authCtx.signInUrl || "",
|
|
299
318
|
signUpUrl: authCtx.signUpUrl || "",
|
|
@@ -318,6 +337,12 @@ function signedOut(authCtx, reason, message = "", headers = new Headers()) {
|
|
|
318
337
|
}
|
|
319
338
|
var decorateHeaders = (requestState) => {
|
|
320
339
|
const headers = new Headers(requestState.headers || {});
|
|
340
|
+
if (requestState.message) {
|
|
341
|
+
try {
|
|
342
|
+
headers.set(constants.Headers.AuthMessage, requestState.message);
|
|
343
|
+
} catch {
|
|
344
|
+
}
|
|
345
|
+
}
|
|
321
346
|
if (requestState.reason) {
|
|
322
347
|
try {
|
|
323
348
|
headers.set(constants.Headers.AuthReason, requestState.reason);
|
|
@@ -705,6 +730,9 @@ function mergePreDefinedOptions(userOptions = {}) {
|
|
|
705
730
|
};
|
|
706
731
|
}
|
|
707
732
|
|
|
733
|
+
// src/tokens/request.ts
|
|
734
|
+
var import_ms = require("@tern-secure/shared/ms");
|
|
735
|
+
|
|
708
736
|
// src/jwt/customJwt.ts
|
|
709
737
|
var import_jose = require("jose");
|
|
710
738
|
var CustomTokenError = class extends Error {
|
|
@@ -1041,44 +1069,33 @@ async function verifySignature(jwt, key) {
|
|
|
1041
1069
|
}
|
|
1042
1070
|
}
|
|
1043
1071
|
function ternDecodeJwt(token) {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
if (tokenParts.length !== 3) {
|
|
1049
|
-
return {
|
|
1050
|
-
errors: [
|
|
1051
|
-
new TokenVerificationError({
|
|
1052
|
-
reason: TokenVerificationErrorReason.TokenInvalid,
|
|
1053
|
-
message: "Invalid JWT format"
|
|
1054
|
-
})
|
|
1055
|
-
]
|
|
1056
|
-
};
|
|
1057
|
-
}
|
|
1058
|
-
const [rawHeader, rawPayload, rawSignature] = tokenParts;
|
|
1059
|
-
const signature = base64url.parse(rawSignature, { loose: true });
|
|
1060
|
-
const data = {
|
|
1061
|
-
header,
|
|
1062
|
-
payload,
|
|
1063
|
-
signature,
|
|
1064
|
-
raw: {
|
|
1065
|
-
header: rawHeader,
|
|
1066
|
-
payload: rawPayload,
|
|
1067
|
-
signature: rawSignature,
|
|
1068
|
-
text: token
|
|
1069
|
-
}
|
|
1070
|
-
};
|
|
1071
|
-
return { data };
|
|
1072
|
-
} catch (error) {
|
|
1072
|
+
const header = (0, import_jose3.decodeProtectedHeader)(token);
|
|
1073
|
+
const payload = (0, import_jose3.decodeJwt)(token);
|
|
1074
|
+
const tokenParts = (token || "").toString().split(".");
|
|
1075
|
+
if (tokenParts.length !== 3) {
|
|
1073
1076
|
return {
|
|
1074
1077
|
errors: [
|
|
1075
1078
|
new TokenVerificationError({
|
|
1076
1079
|
reason: TokenVerificationErrorReason.TokenInvalid,
|
|
1077
|
-
message:
|
|
1080
|
+
message: "Invalid JWT format"
|
|
1078
1081
|
})
|
|
1079
1082
|
]
|
|
1080
1083
|
};
|
|
1081
1084
|
}
|
|
1085
|
+
const [rawHeader, rawPayload, rawSignature] = tokenParts;
|
|
1086
|
+
const signature = base64url.parse(rawSignature, { loose: true });
|
|
1087
|
+
const data = {
|
|
1088
|
+
header,
|
|
1089
|
+
payload,
|
|
1090
|
+
signature,
|
|
1091
|
+
raw: {
|
|
1092
|
+
header: rawHeader,
|
|
1093
|
+
payload: rawPayload,
|
|
1094
|
+
signature: rawSignature,
|
|
1095
|
+
text: token
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
return { data };
|
|
1082
1099
|
}
|
|
1083
1100
|
async function verifyJwt(token, options) {
|
|
1084
1101
|
const { key } = options;
|
|
@@ -1326,9 +1343,14 @@ function getAuth(options) {
|
|
|
1326
1343
|
const idAndRefreshTokens = await customForIdAndRefreshToken(customToken, {
|
|
1327
1344
|
referer: opts.referer
|
|
1328
1345
|
});
|
|
1346
|
+
const decodedCustomIdToken = await verifyToken(idAndRefreshTokens.idToken, options);
|
|
1347
|
+
if (decodedCustomIdToken.errors) {
|
|
1348
|
+
throw decodedCustomIdToken.errors[0];
|
|
1349
|
+
}
|
|
1329
1350
|
return {
|
|
1330
1351
|
...idAndRefreshTokens,
|
|
1331
|
-
customToken
|
|
1352
|
+
customToken,
|
|
1353
|
+
auth_time: decodedCustomIdToken.data.auth_time
|
|
1332
1354
|
};
|
|
1333
1355
|
}
|
|
1334
1356
|
return {
|
|
@@ -1346,6 +1368,7 @@ var RequestProcessorContext = class {
|
|
|
1346
1368
|
this.options = options;
|
|
1347
1369
|
this.initHeaderValues();
|
|
1348
1370
|
this.initCookieValues();
|
|
1371
|
+
this.initHandshakeValues();
|
|
1349
1372
|
this.initUrlValues();
|
|
1350
1373
|
Object.assign(this, options);
|
|
1351
1374
|
this.ternUrl = this.ternSecureRequest.ternUrl;
|
|
@@ -1374,6 +1397,11 @@ var RequestProcessorContext = class {
|
|
|
1374
1397
|
this.refreshTokenInCookie = this.getCookie(`${defaultPrefix}${constants.Cookies.Refresh}`);
|
|
1375
1398
|
this.csrfTokenInCookie = this.getCookie(constants.Cookies.CsrfToken);
|
|
1376
1399
|
this.customTokenInCookie = this.getCookie(constants.Cookies.Custom);
|
|
1400
|
+
this.ternAuth = Number.parseInt(this.getCookie(constants.Cookies.TernAut) || "0", 10);
|
|
1401
|
+
}
|
|
1402
|
+
initHandshakeValues() {
|
|
1403
|
+
this.handshakeToken = this.getQueryParam(constants.QueryParameters.Handshake) || this.getCookie(constants.Cookies.Handshake);
|
|
1404
|
+
this.handshakeNonce = this.getQueryParam(constants.QueryParameters.HandshakeNonce) || this.getCookie(constants.Cookies.HandshakeNonce);
|
|
1377
1405
|
}
|
|
1378
1406
|
initUrlValues() {
|
|
1379
1407
|
this.method = this.ternSecureRequest.method;
|
|
@@ -1381,6 +1409,9 @@ var RequestProcessorContext = class {
|
|
|
1381
1409
|
this.endpoint = this.pathSegments[2];
|
|
1382
1410
|
this.subEndpoint = this.pathSegments[3];
|
|
1383
1411
|
}
|
|
1412
|
+
getQueryParam(name) {
|
|
1413
|
+
return this.ternSecureRequest.ternUrl.searchParams.get(name);
|
|
1414
|
+
}
|
|
1384
1415
|
getHeader(name) {
|
|
1385
1416
|
return this.ternSecureRequest.headers.get(name) || void 0;
|
|
1386
1417
|
}
|
|
@@ -1412,6 +1443,9 @@ var import_cookie2 = require("@tern-secure/shared/cookie");
|
|
|
1412
1443
|
function hasAuthorizationHeader(request) {
|
|
1413
1444
|
return request.headers.has("Authorization");
|
|
1414
1445
|
}
|
|
1446
|
+
function convertToSeconds(value) {
|
|
1447
|
+
return (0, import_ms.ms)(value) / 1e3;
|
|
1448
|
+
}
|
|
1415
1449
|
function isRequestForRefresh(error, context, request) {
|
|
1416
1450
|
return error.reason === TokenVerificationErrorReason.TokenExpired && !!context.refreshTokenInCookie && request.method === "GET";
|
|
1417
1451
|
}
|
|
@@ -1419,6 +1453,17 @@ async function authenticateRequest(request, options) {
|
|
|
1419
1453
|
const context = createRequestProcessor(createTernSecureRequest(request), options);
|
|
1420
1454
|
const { refreshTokenInCookie } = context;
|
|
1421
1455
|
const { refreshExpiredIdToken } = getAuth(options);
|
|
1456
|
+
function checkSessionTimeout(authTimeValue) {
|
|
1457
|
+
const defaultMaxAgeSeconds = convertToSeconds("5 days");
|
|
1458
|
+
const REAUTH_PERIOD_SECONDS = context.session?.maxAge ? convertToSeconds(context.session.maxAge) : defaultMaxAgeSeconds;
|
|
1459
|
+
const currentTime = Math.floor(Date.now() / 1e3);
|
|
1460
|
+
const authAge = currentTime - authTimeValue;
|
|
1461
|
+
console.log("Current time:", currentTime, "Auth age:", authAge, "Reauth period (s):", REAUTH_PERIOD_SECONDS);
|
|
1462
|
+
if (authTimeValue > 0 && authAge > REAUTH_PERIOD_SECONDS) {
|
|
1463
|
+
return signedOut(context, AuthErrorReason.AuthTimeout, "Authentication expired");
|
|
1464
|
+
}
|
|
1465
|
+
return null;
|
|
1466
|
+
}
|
|
1422
1467
|
async function refreshToken() {
|
|
1423
1468
|
if (!refreshTokenInCookie) {
|
|
1424
1469
|
return {
|
|
@@ -1440,10 +1485,10 @@ async function authenticateRequest(request, options) {
|
|
|
1440
1485
|
}
|
|
1441
1486
|
const headers = new Headers();
|
|
1442
1487
|
const { idToken } = refreshedData;
|
|
1443
|
-
const maxAge =
|
|
1488
|
+
const maxAge = 365 * 24 * 60 * 60;
|
|
1444
1489
|
const cookiePrefix = (0, import_cookie2.getCookiePrefix)();
|
|
1445
1490
|
const idTokenCookieName = (0, import_cookie2.getCookieName)(constants.Cookies.IdToken, cookiePrefix);
|
|
1446
|
-
const baseCookieAttributes =
|
|
1491
|
+
const baseCookieAttributes = `HttpOnly; Secure; SameSite=Strict; Max-Age=${maxAge}; Path=/`;
|
|
1447
1492
|
const idTokenCookie = `${idTokenCookieName}=${idToken}; ${baseCookieAttributes};`;
|
|
1448
1493
|
headers.append("Set-Cookie", idTokenCookie);
|
|
1449
1494
|
const { data: decoded, errors } = await verifyToken(idToken, options);
|
|
@@ -1455,7 +1500,78 @@ async function authenticateRequest(request, options) {
|
|
|
1455
1500
|
}
|
|
1456
1501
|
return { data: { decoded, token: idToken, headers }, error: null };
|
|
1457
1502
|
}
|
|
1503
|
+
async function handleLocalHandshakeWithErrorCheck(context2, reason, message, skipSessionCheck = false) {
|
|
1504
|
+
const hasRefreshTokenInCookie = !!context2.refreshTokenInCookie;
|
|
1505
|
+
if (!hasRefreshTokenInCookie) {
|
|
1506
|
+
return signedOut(context2, reason, "Refresh token missing in cookie");
|
|
1507
|
+
}
|
|
1508
|
+
if (reason === AuthErrorReason.TernAutWithoutSessionToken) {
|
|
1509
|
+
if (!skipSessionCheck) {
|
|
1510
|
+
const sessionTimeoutResult = checkSessionTimeout(context2.ternAuth);
|
|
1511
|
+
if (sessionTimeoutResult) {
|
|
1512
|
+
return sessionTimeoutResult;
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
const { data, error } = await handleRefresh();
|
|
1516
|
+
if (data) {
|
|
1517
|
+
return signedIn(context2, data.decoded, data.headers, data.token);
|
|
1518
|
+
}
|
|
1519
|
+
return signedOut(context2, reason, "Failed to refresh idToken");
|
|
1520
|
+
}
|
|
1521
|
+
if (reason === AuthErrorReason.SessionTokenWithoutTernAUT || reason === AuthErrorReason.SessionTokenIATBeforeTernAUT) {
|
|
1522
|
+
const { data, errors } = ternDecodeJwt(context2.idTokenInCookie);
|
|
1523
|
+
if (errors) {
|
|
1524
|
+
throw errors[0];
|
|
1525
|
+
}
|
|
1526
|
+
const authTime = data.payload.auth_time;
|
|
1527
|
+
if (!authTime || typeof authTime !== "number") {
|
|
1528
|
+
return signedOut(context2, reason, "Token missing auth_time");
|
|
1529
|
+
}
|
|
1530
|
+
if (!skipSessionCheck) {
|
|
1531
|
+
const sessionTimeoutResult = checkSessionTimeout(authTime);
|
|
1532
|
+
if (sessionTimeoutResult) {
|
|
1533
|
+
return sessionTimeoutResult;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
const { data: verifiedToken, errors: verifyErrors } = await verifyToken(context2.idTokenInCookie, options);
|
|
1537
|
+
if (verifyErrors) {
|
|
1538
|
+
throw verifyErrors[0];
|
|
1539
|
+
}
|
|
1540
|
+
const headers = new Headers();
|
|
1541
|
+
const oneYearInSeconds = 365 * 24 * 60 * 60;
|
|
1542
|
+
const ternAutCookie = `${constants.Cookies.TernAut}=${authTime}; Max-Age=${oneYearInSeconds}; Secure; SameSite=Strict; Path=/`;
|
|
1543
|
+
headers.append("Set-Cookie", ternAutCookie);
|
|
1544
|
+
return signedIn(context2, verifiedToken, headers, context2.idTokenInCookie);
|
|
1545
|
+
}
|
|
1546
|
+
return signedOut(context2, reason, message);
|
|
1547
|
+
}
|
|
1458
1548
|
async function authenticateRequestWithTokenInCookie() {
|
|
1549
|
+
const hasTernAuth = context.ternAuth;
|
|
1550
|
+
const hasIdTokenInCookie = !!context.idTokenInCookie;
|
|
1551
|
+
if (!hasTernAuth && !hasIdTokenInCookie) {
|
|
1552
|
+
return signedOut(context, AuthErrorReason.SessionTokenAndAuthMissing);
|
|
1553
|
+
}
|
|
1554
|
+
if (!hasTernAuth && hasIdTokenInCookie) {
|
|
1555
|
+
return await handleLocalHandshakeWithErrorCheck(context, AuthErrorReason.SessionTokenWithoutTernAUT, "");
|
|
1556
|
+
}
|
|
1557
|
+
if (hasTernAuth && !hasIdTokenInCookie) {
|
|
1558
|
+
return await handleLocalHandshakeWithErrorCheck(context, AuthErrorReason.TernAutWithoutSessionToken, "");
|
|
1559
|
+
}
|
|
1560
|
+
const sessionTimeoutResult = checkSessionTimeout(context.ternAuth);
|
|
1561
|
+
if (sessionTimeoutResult) {
|
|
1562
|
+
return sessionTimeoutResult;
|
|
1563
|
+
}
|
|
1564
|
+
const { data: decodedResult, errors: decodeErrors } = ternDecodeJwt(context.idTokenInCookie);
|
|
1565
|
+
if (decodeErrors) {
|
|
1566
|
+
return handleError(decodeErrors[0], "cookie");
|
|
1567
|
+
}
|
|
1568
|
+
const tokenIat = decodedResult.payload.iat;
|
|
1569
|
+
if (!tokenIat) {
|
|
1570
|
+
return signedOut(context, AuthErrorReason.SessionTokenMissing, "");
|
|
1571
|
+
}
|
|
1572
|
+
if (tokenIat < context.ternAuth) {
|
|
1573
|
+
return await handleLocalHandshakeWithErrorCheck(context, AuthErrorReason.SessionTokenIATBeforeTernAUT, "", true);
|
|
1574
|
+
}
|
|
1459
1575
|
try {
|
|
1460
1576
|
const { data, errors } = await verifyToken(context.idTokenInCookie, options);
|
|
1461
1577
|
if (errors) {
|
|
@@ -1466,6 +1582,7 @@ async function authenticateRequest(request, options) {
|
|
|
1466
1582
|
} catch (err) {
|
|
1467
1583
|
return handleError(err, "cookie");
|
|
1468
1584
|
}
|
|
1585
|
+
return signedOut(context, AuthErrorReason.UnexpectedError);
|
|
1469
1586
|
}
|
|
1470
1587
|
async function authenticateRequestWithTokenInHeader() {
|
|
1471
1588
|
const { sessionTokenInHeader } = context;
|