@tern-secure/backend 1.2.0-canary.v20251003134325 → 1.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/admin/index.js +7 -3
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +531 -22
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/nextSessionTernSecure.d.ts.map +1 -1
- package/dist/auth/getauth.d.ts +16 -2
- package/dist/auth/getauth.d.ts.map +1 -1
- package/dist/auth/index.js +166 -213
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +4 -51
- package/dist/auth/index.mjs.map +1 -1
- package/dist/{chunk-4SGWLAJG.mjs → chunk-3ZLDOHI2.mjs} +4 -68
- package/dist/chunk-3ZLDOHI2.mjs.map +1 -0
- package/dist/{chunk-WZYVAHZ3.mjs → chunk-SVZUAXAW.mjs} +115 -1
- package/dist/chunk-SVZUAXAW.mjs.map +1 -0
- package/dist/chunk-VSYYHCUV.mjs +71 -0
- package/dist/chunk-VSYYHCUV.mjs.map +1 -0
- package/dist/{chunk-YKIA5EBF.mjs → chunk-YGNTGJTP.mjs} +94 -4
- package/dist/chunk-YGNTGJTP.mjs.map +1 -0
- package/dist/fireRestApi/endpoints/TokenApi.d.ts +6 -3
- package/dist/fireRestApi/endpoints/TokenApi.d.ts.map +1 -1
- package/dist/fireRestApi/request.d.ts +3 -3
- package/dist/fireRestApi/request.d.ts.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +405 -103
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +130 -18
- package/dist/index.mjs.map +1 -1
- package/dist/jwt/customJwt.d.ts +11 -0
- package/dist/jwt/customJwt.d.ts.map +1 -0
- package/dist/jwt/index.d.ts +1 -0
- package/dist/jwt/index.d.ts.map +1 -1
- package/dist/jwt/index.js +104 -0
- package/dist/jwt/index.js.map +1 -1
- package/dist/jwt/index.mjs +7 -1
- package/dist/jwt/index.mjs.map +1 -1
- package/dist/tokens/cookie.d.ts +5 -0
- package/dist/tokens/cookie.d.ts.map +1 -0
- package/dist/tokens/request.d.ts.map +1 -1
- package/dist/tokens/types.d.ts +1 -12
- package/dist/tokens/types.d.ts.map +1 -1
- package/dist/utils/errors.d.ts +12 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/options.d.ts +3 -3
- package/dist/utils/options.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-4SGWLAJG.mjs.map +0 -1
- package/dist/chunk-NEPV6OWI.mjs +0 -550
- package/dist/chunk-NEPV6OWI.mjs.map +0 -1
- package/dist/chunk-WZYVAHZ3.mjs.map +0 -1
- package/dist/chunk-YKIA5EBF.mjs.map +0 -1
- package/dist/tokens/sessionConfig.d.ts +0 -14
- package/dist/tokens/sessionConfig.d.ts.map +0 -1
package/dist/auth/getauth.d.ts
CHANGED
|
@@ -8,8 +8,22 @@ export interface CustomTokens {
|
|
|
8
8
|
refreshToken: string;
|
|
9
9
|
customToken: string;
|
|
10
10
|
}
|
|
11
|
+
interface CustomForIdAndRefreshTokenOptions {
|
|
12
|
+
tenantId?: string;
|
|
13
|
+
appCheckToken?: string;
|
|
14
|
+
referer?: string;
|
|
15
|
+
}
|
|
16
|
+
type AuthResult<T = any> = {
|
|
17
|
+
data: T;
|
|
18
|
+
error: null;
|
|
19
|
+
} | {
|
|
20
|
+
data: null;
|
|
21
|
+
error: any;
|
|
22
|
+
};
|
|
11
23
|
export declare function getAuth(options: AuthenticateRequestOptions): {
|
|
12
|
-
customForIdAndRefreshToken: (customToken: string) => Promise<IdAndRefreshTokens>;
|
|
13
|
-
createCustomIdAndRefreshToken: (idToken: string) => Promise<CustomTokens>;
|
|
24
|
+
customForIdAndRefreshToken: (customToken: string, opts: CustomForIdAndRefreshTokenOptions) => Promise<IdAndRefreshTokens>;
|
|
25
|
+
createCustomIdAndRefreshToken: (idToken: string, opts: CustomForIdAndRefreshTokenOptions) => Promise<CustomTokens>;
|
|
26
|
+
refreshExpiredIdToken: (refreshToken: string, opts: CustomForIdAndRefreshTokenOptions) => Promise<AuthResult>;
|
|
14
27
|
};
|
|
28
|
+
export {};
|
|
15
29
|
//# sourceMappingURL=getauth.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getauth.d.ts","sourceRoot":"","sources":["../../src/auth/getauth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAGlE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;
|
|
1
|
+
{"version":3,"file":"getauth.d.ts","sourceRoot":"","sources":["../../src/auth/getauth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAGlE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,iCAAiC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAkBD,KAAK,UAAU,CAAC,CAAC,GAAG,GAAG,IAAI;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC;AAgBjF,wBAAgB,OAAO,CAAC,OAAO,EAAE,0BAA0B;8CAoC1C,MAAM,QACb,iCAAiC,KACtC,OAAO,CAAC,kBAAkB,CAAC;6CA4BnB,MAAM,QACT,iCAAiC,KACtC,OAAO,CAAC,YAAY,CAAC;0CA9DR,MAAM,QACd,iCAAiC,KACtC,OAAO,CAAC,UAAU,CAAC;EAuFvB"}
|
package/dist/auth/index.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// src/auth/index.ts
|
|
@@ -34,190 +24,103 @@ __export(auth_exports, {
|
|
|
34
24
|
});
|
|
35
25
|
module.exports = __toCommonJS(auth_exports);
|
|
36
26
|
|
|
37
|
-
// src/
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
var CACHE_CONTROL_REGEX = /max-age=(\d+)/;
|
|
45
|
-
var Attributes = {
|
|
46
|
-
AuthToken: "__ternsecureAuthToken",
|
|
47
|
-
AuthSignature: "__ternsecureAuthSignature",
|
|
48
|
-
AuthStatus: "__ternsecureAuthStatus",
|
|
49
|
-
AuthReason: "__ternsecureAuthReason",
|
|
50
|
-
AuthMessage: "__ternsecureAuthMessage",
|
|
51
|
-
TernSecureUrl: "__ternsecureUrl"
|
|
52
|
-
};
|
|
53
|
-
var Cookies = {
|
|
54
|
-
Session: "__session",
|
|
55
|
-
CsrfToken: "__session_terncf",
|
|
56
|
-
IdToken: "FIREBASE_[DEFAULT]",
|
|
57
|
-
Refresh: "FIREBASEID_[DEFAULT]",
|
|
58
|
-
Custom: "__custom",
|
|
59
|
-
Handshake: "__ternsecure_handshake",
|
|
60
|
-
DevBrowser: "__ternsecure_db_jwt",
|
|
61
|
-
RedirectCount: "__ternsecure_redirect_count",
|
|
62
|
-
HandshakeNonce: "__ternsecure_handshake_nonce"
|
|
63
|
-
};
|
|
64
|
-
var Headers2 = {
|
|
65
|
-
Accept: "accept",
|
|
66
|
-
AuthMessage: "x-ternsecure-auth-message",
|
|
67
|
-
Authorization: "authorization",
|
|
68
|
-
AuthReason: "x-ternsecure-auth-reason",
|
|
69
|
-
AuthSignature: "x-ternsecure-auth-signature",
|
|
70
|
-
AuthStatus: "x-ternsecure-auth-status",
|
|
71
|
-
AuthToken: "x-ternsecure-auth-token",
|
|
72
|
-
CacheControl: "cache-control",
|
|
73
|
-
TernSecureRedirectTo: "x-ternsecure-redirect-to",
|
|
74
|
-
TernSecureRequestData: "x-ternsecure-request-data",
|
|
75
|
-
TernSecureUrl: "x-ternsecure-url",
|
|
76
|
-
CloudFrontForwardedProto: "cloudfront-forwarded-proto",
|
|
77
|
-
ContentType: "content-type",
|
|
78
|
-
ContentSecurityPolicy: "content-security-policy",
|
|
79
|
-
ContentSecurityPolicyReportOnly: "content-security-policy-report-only",
|
|
80
|
-
EnableDebug: "x-ternsecure-debug",
|
|
81
|
-
ForwardedHost: "x-forwarded-host",
|
|
82
|
-
ForwardedPort: "x-forwarded-port",
|
|
83
|
-
ForwardedProto: "x-forwarded-proto",
|
|
84
|
-
Host: "host",
|
|
85
|
-
Location: "location",
|
|
86
|
-
Nonce: "x-nonce",
|
|
87
|
-
Origin: "origin",
|
|
88
|
-
Referrer: "referer",
|
|
89
|
-
SecFetchDest: "sec-fetch-dest",
|
|
90
|
-
UserAgent: "user-agent",
|
|
91
|
-
ReportingEndpoints: "reporting-endpoints"
|
|
92
|
-
};
|
|
93
|
-
var ContentTypes = {
|
|
94
|
-
Json: "application/json"
|
|
95
|
-
};
|
|
96
|
-
var constants = {
|
|
97
|
-
Attributes,
|
|
98
|
-
Cookies,
|
|
99
|
-
Headers: Headers2,
|
|
100
|
-
ContentTypes
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// src/utils/admin-init.ts
|
|
104
|
-
var import_firebase_admin = __toESM(require("firebase-admin"));
|
|
105
|
-
|
|
106
|
-
// src/utils/config.ts
|
|
107
|
-
var loadAdminConfig = () => ({
|
|
108
|
-
projectId: process.env.FIREBASE_PROJECT_ID || "",
|
|
109
|
-
clientEmail: process.env.FIREBASE_CLIENT_EMAIL || "",
|
|
110
|
-
privateKey: process.env.FIREBASE_PRIVATE_KEY || ""
|
|
111
|
-
});
|
|
112
|
-
var validateAdminConfig = (config) => {
|
|
113
|
-
const requiredFields = [
|
|
114
|
-
"projectId",
|
|
115
|
-
"clientEmail",
|
|
116
|
-
"privateKey"
|
|
117
|
-
];
|
|
118
|
-
const errors = [];
|
|
119
|
-
requiredFields.forEach((field) => {
|
|
120
|
-
if (!config[field]) {
|
|
121
|
-
errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
return {
|
|
125
|
-
isValid: errors.length === 0,
|
|
126
|
-
errors,
|
|
127
|
-
config
|
|
128
|
-
};
|
|
129
|
-
};
|
|
130
|
-
var initializeAdminConfig = () => {
|
|
131
|
-
const config = loadAdminConfig();
|
|
132
|
-
const validationResult = validateAdminConfig(config);
|
|
133
|
-
if (!validationResult.isValid) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
`Firebase Admin configuration validation failed:
|
|
136
|
-
${validationResult.errors.join("\n")}`
|
|
137
|
-
);
|
|
27
|
+
// src/jwt/customJwt.ts
|
|
28
|
+
var import_jose = require("jose");
|
|
29
|
+
var CustomTokenError = class extends Error {
|
|
30
|
+
constructor(message, code) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.code = code;
|
|
33
|
+
this.name = "CustomTokenError";
|
|
138
34
|
}
|
|
139
|
-
return config;
|
|
140
35
|
};
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
36
|
+
var RESERVED_CLAIMS = [
|
|
37
|
+
"acr",
|
|
38
|
+
"amr",
|
|
39
|
+
"at_hash",
|
|
40
|
+
"aud",
|
|
41
|
+
"auth_time",
|
|
42
|
+
"azp",
|
|
43
|
+
"cnf",
|
|
44
|
+
"c_hash",
|
|
45
|
+
"exp",
|
|
46
|
+
"firebase",
|
|
47
|
+
"iat",
|
|
48
|
+
"iss",
|
|
49
|
+
"jti",
|
|
50
|
+
"nbf",
|
|
51
|
+
"nonce",
|
|
52
|
+
"sub"
|
|
53
|
+
];
|
|
54
|
+
async function createCustomTokenJwt(uid, developerClaims) {
|
|
144
55
|
try {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
56
|
+
const privateKey = process.env.FIREBASE_PRIVATE_KEY;
|
|
57
|
+
const clientEmail = process.env.FIREBASE_CLIENT_EMAIL;
|
|
58
|
+
if (!privateKey || !clientEmail) {
|
|
59
|
+
return {
|
|
60
|
+
errors: [
|
|
61
|
+
new CustomTokenError(
|
|
62
|
+
"Missing FIREBASE_PRIVATE_KEY or FIREBASE_CLIENT_EMAIL environment variables",
|
|
63
|
+
"MISSING_ENV_VARS"
|
|
64
|
+
)
|
|
65
|
+
]
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (!uid || typeof uid !== "string") {
|
|
69
|
+
return {
|
|
70
|
+
errors: [new CustomTokenError("uid must be a non-empty string", "INVALID_UID")]
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (uid.length > 128) {
|
|
74
|
+
return {
|
|
75
|
+
errors: [new CustomTokenError("uid must not exceed 128 characters", "UID_TOO_LONG")]
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (developerClaims) {
|
|
79
|
+
for (const claim of Object.keys(developerClaims)) {
|
|
80
|
+
if (RESERVED_CLAIMS.includes(claim)) {
|
|
81
|
+
return {
|
|
82
|
+
errors: [new CustomTokenError(`Custom claim '${claim}' is reserved`, "RESERVED_CLAIM")]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const expiresIn = 3600;
|
|
88
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
89
|
+
const parsedPrivateKey = await (0, import_jose.importPKCS8)(privateKey.replace(/\\n/g, "\n"), "RS256");
|
|
90
|
+
const payload = {
|
|
91
|
+
iss: clientEmail,
|
|
92
|
+
sub: clientEmail,
|
|
93
|
+
aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit",
|
|
94
|
+
iat: now,
|
|
95
|
+
exp: now + expiresIn,
|
|
96
|
+
uid,
|
|
97
|
+
...developerClaims
|
|
98
|
+
};
|
|
99
|
+
const jwt = await new import_jose.SignJWT(payload).setProtectedHeader({ alg: "RS256", typ: "JWT" }).setIssuedAt(now).setExpirationTime(now + expiresIn).setIssuer(clientEmail).setSubject(clientEmail).setAudience(
|
|
100
|
+
"https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
|
|
101
|
+
).sign(parsedPrivateKey);
|
|
102
|
+
return {
|
|
103
|
+
data: jwt
|
|
104
|
+
};
|
|
152
105
|
} catch (error) {
|
|
153
|
-
|
|
106
|
+
const message = error instanceof Error ? error.message : "Unknown error occurred";
|
|
107
|
+
return {
|
|
108
|
+
errors: [
|
|
109
|
+
new CustomTokenError(`Failed to create custom token: ${message}`, "TOKEN_CREATION_FAILED")
|
|
110
|
+
]
|
|
111
|
+
};
|
|
154
112
|
}
|
|
155
113
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (tenantId) {
|
|
161
|
-
return TernSecureTenantManager.authForTenant(tenantId);
|
|
162
|
-
}
|
|
163
|
-
return import_firebase_admin.default.auth();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// src/admin/sessionTernSecure.ts
|
|
167
|
-
var SESSION_CONSTANTS = {
|
|
168
|
-
COOKIE_NAME: "_session_cookie",
|
|
169
|
-
//DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days
|
|
170
|
-
//DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5, // 5days
|
|
171
|
-
DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1e3,
|
|
172
|
-
// 5 minutes
|
|
173
|
-
DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,
|
|
174
|
-
REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
|
|
175
|
-
};
|
|
176
|
-
var COOKIE_OPTIONS = {
|
|
177
|
-
httpOnly: true,
|
|
178
|
-
secure: process.env.NODE_ENV === "production",
|
|
179
|
-
sameSite: "strict",
|
|
180
|
-
path: "/"
|
|
181
|
-
};
|
|
182
|
-
var DEFAULT_COOKIE_CONFIG = {
|
|
183
|
-
DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1e3,
|
|
184
|
-
// 5 minutes
|
|
185
|
-
DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,
|
|
186
|
-
REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
|
|
187
|
-
};
|
|
188
|
-
var DEFAULT_COOKIE_OPTIONS = {
|
|
189
|
-
httpOnly: true,
|
|
190
|
-
secure: process.env.NODE_ENV === "production",
|
|
191
|
-
sameSite: "strict",
|
|
192
|
-
path: "/"
|
|
193
|
-
};
|
|
194
|
-
async function createCustomTokenClaims(uid, developerClaims) {
|
|
195
|
-
const adminAuth = getAuthForTenant();
|
|
196
|
-
try {
|
|
197
|
-
const customToken = await adminAuth.createCustomToken(uid, developerClaims);
|
|
198
|
-
return customToken;
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.error("[createCustomToken] Error creating custom token:", error);
|
|
201
|
-
return "";
|
|
114
|
+
async function createCustomToken(uid, developerClaims) {
|
|
115
|
+
const { data, errors } = await createCustomTokenJwt(uid, developerClaims);
|
|
116
|
+
if (errors) {
|
|
117
|
+
throw errors[0];
|
|
202
118
|
}
|
|
119
|
+
return data;
|
|
203
120
|
}
|
|
204
121
|
|
|
205
|
-
// src/admin/nextSessionTernSecure.ts
|
|
206
|
-
var import_errors2 = require("@tern-secure/shared/errors");
|
|
207
|
-
var import_headers = require("next/headers");
|
|
208
|
-
var SESSION_CONSTANTS2 = {
|
|
209
|
-
COOKIE_NAME: constants.Cookies.Session,
|
|
210
|
-
DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1e3,
|
|
211
|
-
// 5 days
|
|
212
|
-
DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,
|
|
213
|
-
REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
// src/tokens/ternSecureRequest.ts
|
|
217
|
-
var import_cookie = require("cookie");
|
|
218
|
-
|
|
219
122
|
// src/jwt/verifyJwt.ts
|
|
220
|
-
var
|
|
123
|
+
var import_jose3 = require("jose");
|
|
221
124
|
|
|
222
125
|
// src/utils/errors.ts
|
|
223
126
|
var TokenVerificationErrorReason = {
|
|
@@ -264,7 +167,7 @@ function mapJwtPayloadToDecodedIdToken(payload) {
|
|
|
264
167
|
// src/utils/rfc4648.ts
|
|
265
168
|
var base64url = {
|
|
266
169
|
parse(string, opts) {
|
|
267
|
-
return
|
|
170
|
+
return parse(string, base64UrlEncoding, opts);
|
|
268
171
|
},
|
|
269
172
|
stringify(data, opts) {
|
|
270
173
|
return stringify(data, base64UrlEncoding, opts);
|
|
@@ -274,7 +177,7 @@ var base64UrlEncoding = {
|
|
|
274
177
|
chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
|
|
275
178
|
bits: 6
|
|
276
179
|
};
|
|
277
|
-
function
|
|
180
|
+
function parse(string, encoding, opts = {}) {
|
|
278
181
|
if (!encoding.codes) {
|
|
279
182
|
encoding.codes = {};
|
|
280
183
|
for (let i = 0; i < encoding.chars.length; ++i) {
|
|
@@ -338,10 +241,10 @@ function stringify(data, encoding, opts = {}) {
|
|
|
338
241
|
}
|
|
339
242
|
|
|
340
243
|
// src/jwt/cryptoKeys.ts
|
|
341
|
-
var
|
|
244
|
+
var import_jose2 = require("jose");
|
|
342
245
|
async function importKey(key, algorithm) {
|
|
343
246
|
if (typeof key === "object") {
|
|
344
|
-
const result = await (0,
|
|
247
|
+
const result = await (0, import_jose2.importJWK)(key, algorithm);
|
|
345
248
|
if (result instanceof Uint8Array) {
|
|
346
249
|
throw new Error("Unexpected Uint8Array result from JWK import");
|
|
347
250
|
}
|
|
@@ -349,13 +252,13 @@ async function importKey(key, algorithm) {
|
|
|
349
252
|
}
|
|
350
253
|
const keyString = key.trim();
|
|
351
254
|
if (keyString.includes("-----BEGIN CERTIFICATE-----")) {
|
|
352
|
-
return await (0,
|
|
255
|
+
return await (0, import_jose2.importX509)(keyString, algorithm);
|
|
353
256
|
}
|
|
354
257
|
if (keyString.includes("-----BEGIN PUBLIC KEY-----")) {
|
|
355
|
-
return await (0,
|
|
258
|
+
return await (0, import_jose2.importSPKI)(keyString, algorithm);
|
|
356
259
|
}
|
|
357
260
|
try {
|
|
358
|
-
return await (0,
|
|
261
|
+
return await (0, import_jose2.importSPKI)(keyString, algorithm);
|
|
359
262
|
} catch (error) {
|
|
360
263
|
throw new Error(
|
|
361
264
|
`Unsupported key format. Supported formats: X.509 certificate (PEM), SPKI (PEM), JWK (JSON object or string). Error: ${error}`
|
|
@@ -438,7 +341,7 @@ async function verifySignature(jwt, key) {
|
|
|
438
341
|
const joseAlgorithm = header.alg || "RS256";
|
|
439
342
|
try {
|
|
440
343
|
const publicKey = await importKey(key, joseAlgorithm);
|
|
441
|
-
const { payload } = await (0,
|
|
344
|
+
const { payload } = await (0, import_jose3.jwtVerify)(raw.text, publicKey);
|
|
442
345
|
return { data: payload };
|
|
443
346
|
} catch (error) {
|
|
444
347
|
return {
|
|
@@ -453,8 +356,8 @@ async function verifySignature(jwt, key) {
|
|
|
453
356
|
}
|
|
454
357
|
function ternDecodeJwt(token) {
|
|
455
358
|
try {
|
|
456
|
-
const header = (0,
|
|
457
|
-
const payload = (0,
|
|
359
|
+
const header = (0, import_jose3.decodeProtectedHeader)(token);
|
|
360
|
+
const payload = (0, import_jose3.decodeJwt)(token);
|
|
458
361
|
const tokenParts = (token || "").toString().split(".");
|
|
459
362
|
if (tokenParts.length !== 3) {
|
|
460
363
|
return {
|
|
@@ -522,6 +425,12 @@ async function verifyJwt(token, options) {
|
|
|
522
425
|
return { data: decodedIdToken };
|
|
523
426
|
}
|
|
524
427
|
|
|
428
|
+
// src/constants.ts
|
|
429
|
+
var GOOGLE_PUBLIC_KEYS_URL = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
|
|
430
|
+
var MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;
|
|
431
|
+
var DEFAULT_CACHE_DURATION = 3600 * 1e3;
|
|
432
|
+
var CACHE_CONTROL_REGEX = /max-age=(\d+)/;
|
|
433
|
+
|
|
525
434
|
// src/tokens/keys.ts
|
|
526
435
|
var cache = {};
|
|
527
436
|
var lastUpdatedAt = 0;
|
|
@@ -648,38 +557,81 @@ async function verifyToken(token, options) {
|
|
|
648
557
|
}
|
|
649
558
|
|
|
650
559
|
// src/auth/getauth.ts
|
|
560
|
+
var API_KEY_ERROR = "API Key is required";
|
|
561
|
+
var NO_DATA_ERROR = "No token data received";
|
|
562
|
+
function parseFirebaseResponse(data) {
|
|
563
|
+
if (typeof data === "string") {
|
|
564
|
+
try {
|
|
565
|
+
return JSON.parse(data);
|
|
566
|
+
} catch (error) {
|
|
567
|
+
throw new Error(`Failed to parse Firebase response: ${error}`);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return data;
|
|
571
|
+
}
|
|
651
572
|
function getAuth(options) {
|
|
652
|
-
const { apiKey
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
573
|
+
const { apiKey } = options;
|
|
574
|
+
const firebaseApiKey = options.firebaseConfig?.apiKey;
|
|
575
|
+
const effectiveApiKey = apiKey || firebaseApiKey;
|
|
576
|
+
async function refreshExpiredIdToken(refreshToken, opts) {
|
|
577
|
+
if (!effectiveApiKey) {
|
|
578
|
+
return { data: null, error: new Error(API_KEY_ERROR) };
|
|
656
579
|
}
|
|
657
|
-
const response = await options.apiClient?.tokens.
|
|
658
|
-
|
|
659
|
-
|
|
580
|
+
const response = await options.apiClient?.tokens.refreshToken(effectiveApiKey, {
|
|
581
|
+
refresh_token: refreshToken,
|
|
582
|
+
request_origin: opts.referer
|
|
660
583
|
});
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
584
|
+
if (!response?.data) {
|
|
585
|
+
return {
|
|
586
|
+
data: null,
|
|
587
|
+
error: new Error(NO_DATA_ERROR)
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
const parsedData = parseFirebaseResponse(response.data);
|
|
591
|
+
return {
|
|
592
|
+
data: {
|
|
593
|
+
idToken: parsedData.id_token,
|
|
594
|
+
refreshToken: parsedData.refresh_token
|
|
595
|
+
},
|
|
596
|
+
error: null
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
async function customForIdAndRefreshToken(customToken, opts) {
|
|
600
|
+
if (!effectiveApiKey) {
|
|
601
|
+
throw new Error("API Key is required to create custom token");
|
|
602
|
+
}
|
|
603
|
+
const response = await options.apiClient?.tokens.exchangeCustomForIdAndRefreshTokens(
|
|
604
|
+
effectiveApiKey,
|
|
605
|
+
{
|
|
606
|
+
token: customToken,
|
|
607
|
+
returnSecureToken: true
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
referer: opts.referer
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
if (!response?.data) {
|
|
614
|
+
throw new Error("No data received from Firebase token exchange");
|
|
615
|
+
}
|
|
616
|
+
const parsedData = parseFirebaseResponse(response.data);
|
|
664
617
|
return {
|
|
665
|
-
idToken:
|
|
666
|
-
refreshToken:
|
|
618
|
+
idToken: parsedData.idToken,
|
|
619
|
+
refreshToken: parsedData.refreshToken
|
|
667
620
|
};
|
|
668
621
|
}
|
|
669
|
-
async function createCustomIdAndRefreshToken(idToken) {
|
|
622
|
+
async function createCustomIdAndRefreshToken(idToken, opts) {
|
|
670
623
|
const decoded = await verifyToken(idToken, options);
|
|
671
624
|
const { data, errors } = decoded;
|
|
672
625
|
if (errors) {
|
|
673
|
-
console.error("Token Verification failed:", errors);
|
|
674
626
|
throw errors[0];
|
|
675
627
|
}
|
|
676
|
-
const customToken = await
|
|
628
|
+
const customToken = await createCustomToken(data.uid, {
|
|
677
629
|
emailVerified: data.email_verified,
|
|
678
630
|
source_sign_in_provider: data.firebase.sign_in_provider
|
|
679
631
|
});
|
|
680
|
-
const idAndRefreshTokens = await customForIdAndRefreshToken(
|
|
681
|
-
|
|
682
|
-
);
|
|
632
|
+
const idAndRefreshTokens = await customForIdAndRefreshToken(customToken, {
|
|
633
|
+
referer: opts.referer
|
|
634
|
+
});
|
|
683
635
|
return {
|
|
684
636
|
...idAndRefreshTokens,
|
|
685
637
|
customToken
|
|
@@ -687,7 +639,8 @@ function getAuth(options) {
|
|
|
687
639
|
}
|
|
688
640
|
return {
|
|
689
641
|
customForIdAndRefreshToken,
|
|
690
|
-
createCustomIdAndRefreshToken
|
|
642
|
+
createCustomIdAndRefreshToken,
|
|
643
|
+
refreshExpiredIdToken
|
|
691
644
|
};
|
|
692
645
|
}
|
|
693
646
|
// Annotate the CommonJS export names for ESM import in node:
|