@tern-secure/backend 1.1.6 → 1.1.8
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/admin/package.json +5 -0
- package/dist/adapters/PostgresAdapter.d.ts +8 -0
- package/dist/adapters/PostgresAdapter.d.ts.map +1 -0
- package/dist/adapters/RedisAdapter.d.ts +10 -0
- package/dist/adapters/RedisAdapter.d.ts.map +1 -0
- package/dist/adapters/index.d.ts +13 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/types.d.ts +30 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/admin/gemini_sessionTernSecure.d.ts +10 -0
- package/dist/admin/gemini_sessionTernSecure.d.ts.map +1 -0
- package/dist/admin/index.d.ts +8 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +705 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/index.mjs +512 -0
- package/dist/admin/index.mjs.map +1 -0
- package/dist/admin/nextSessionTernSecure.d.ts +28 -0
- package/dist/admin/nextSessionTernSecure.d.ts.map +1 -0
- package/dist/admin/sessionTernSecure.d.ts +6 -0
- package/dist/admin/sessionTernSecure.d.ts.map +1 -0
- package/dist/admin/tenant.d.ts.map +1 -0
- package/dist/api/createBackendApi.d.ts +8 -0
- package/dist/api/createBackendApi.d.ts.map +1 -0
- package/dist/api/endpoints/SessionApi.d.ts +12 -0
- package/dist/api/endpoints/SessionApi.d.ts.map +1 -0
- package/dist/api/endpoints/index.d.ts +2 -0
- package/dist/api/endpoints/index.d.ts.map +1 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/request.d.ts +36 -0
- package/dist/api/request.d.ts.map +1 -0
- package/dist/chunk-JFOTE3Y5.mjs +157 -0
- package/dist/chunk-JFOTE3Y5.mjs.map +1 -0
- package/dist/chunk-WZYVAHZ3.mjs +318 -0
- package/dist/chunk-WZYVAHZ3.mjs.map +1 -0
- package/dist/constants.d.ts +63 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1307 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +839 -0
- package/dist/index.mjs.map +1 -0
- package/dist/instance/backendFireInstance.d.ts +7 -0
- package/dist/instance/backendFireInstance.d.ts.map +1 -0
- package/dist/instance/backendInstance.d.ts +20 -0
- package/dist/instance/backendInstance.d.ts.map +1 -0
- package/dist/instance/backendInstanceEdge.d.ts +13 -0
- package/dist/instance/backendInstanceEdge.d.ts.map +1 -0
- package/dist/jwt/algorithms.d.ts +3 -0
- package/dist/jwt/algorithms.d.ts.map +1 -0
- package/dist/jwt/cryptoKeys.d.ts +3 -0
- package/dist/jwt/cryptoKeys.d.ts.map +1 -0
- package/dist/jwt/guardReturn.d.ts +3 -0
- package/dist/jwt/guardReturn.d.ts.map +1 -0
- package/dist/jwt/index.d.ts +4 -0
- package/dist/jwt/index.d.ts.map +1 -0
- package/dist/jwt/index.js +332 -0
- package/dist/jwt/index.js.map +1 -0
- package/dist/jwt/index.mjs +139 -0
- package/dist/jwt/index.mjs.map +1 -0
- package/dist/jwt/jwt.d.ts +4 -0
- package/dist/jwt/jwt.d.ts.map +1 -0
- package/dist/jwt/signJwt.d.ts +5 -0
- package/dist/jwt/signJwt.d.ts.map +1 -0
- package/dist/jwt/types.d.ts +8 -0
- package/dist/jwt/types.d.ts.map +1 -0
- package/dist/jwt/verifyContent.d.ts +7 -0
- package/dist/jwt/verifyContent.d.ts.map +1 -0
- package/dist/jwt/verifyJwt.d.ts +12 -0
- package/dist/jwt/verifyJwt.d.ts.map +1 -0
- package/dist/runtime/browser/crypto.mjs +1 -0
- package/dist/runtime/node/crypto.js +1 -0
- package/dist/runtime/node/crypto.mjs +1 -0
- package/dist/runtime.d.ts +26 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/ternsecureauth.d.ts.map +1 -0
- package/dist/tokens/authstate.d.ts +61 -0
- package/dist/tokens/authstate.d.ts.map +1 -0
- package/dist/tokens/keys.d.ts +16 -0
- package/dist/tokens/keys.d.ts.map +1 -0
- package/dist/tokens/request.d.ts +16 -0
- package/dist/tokens/request.d.ts.map +1 -0
- package/dist/tokens/requestFire.d.ts +17 -0
- package/dist/tokens/requestFire.d.ts.map +1 -0
- package/dist/tokens/sessionConfig.d.ts +14 -0
- package/dist/tokens/sessionConfig.d.ts.map +1 -0
- package/dist/tokens/ternSecureRequest.d.ts +20 -0
- package/dist/tokens/ternSecureRequest.d.ts.map +1 -0
- package/dist/tokens/ternUrl.d.ts +15 -0
- package/dist/tokens/ternUrl.d.ts.map +1 -0
- package/dist/tokens/types.d.ts +41 -0
- package/dist/tokens/types.d.ts.map +1 -0
- package/dist/tokens/verify.d.ts +11 -0
- package/dist/tokens/verify.d.ts.map +1 -0
- package/dist/utils/admin-init.d.ts +13 -0
- package/dist/utils/admin-init.d.ts.map +1 -0
- package/dist/{types/utils → utils}/config.d.ts +1 -1
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/enableDebugLogging.d.ts +5 -0
- package/dist/utils/enableDebugLogging.d.ts.map +1 -0
- package/dist/utils/errors.d.ts +29 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/gemini_admin-init.d.ts +10 -0
- package/dist/utils/gemini_admin-init.d.ts.map +1 -0
- package/dist/utils/logger.d.ts +28 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/mapDecode.d.ts +4 -0
- package/dist/utils/mapDecode.d.ts.map +1 -0
- package/dist/utils/options.d.ts +5 -0
- package/dist/utils/options.d.ts.map +1 -0
- package/dist/utils/path.d.ts +4 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/redis.d.ts +10 -0
- package/dist/utils/redis.d.ts.map +1 -0
- package/dist/utils/rfc4648.d.ts +26 -0
- package/dist/utils/rfc4648.d.ts.map +1 -0
- package/jwt/package.json +5 -0
- package/package.json +59 -10
- package/dist/cjs/admin/sessionTernSecure.js +0 -256
- package/dist/cjs/admin/sessionTernSecure.js.map +0 -1
- package/dist/cjs/admin/tenant.js +0 -68
- package/dist/cjs/admin/tenant.js.map +0 -1
- package/dist/cjs/global.d.js +0 -2
- package/dist/cjs/global.d.js.map +0 -1
- package/dist/cjs/index.js +0 -48
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/ternsecureauth.js +0 -40
- package/dist/cjs/ternsecureauth.js.map +0 -1
- package/dist/cjs/utils/admin-init.js +0 -60
- package/dist/cjs/utils/admin-init.js.map +0 -1
- package/dist/cjs/utils/config.js +0 -113
- package/dist/cjs/utils/config.js.map +0 -1
- package/dist/esm/admin/sessionTernSecure.js +0 -226
- package/dist/esm/admin/sessionTernSecure.js.map +0 -1
- package/dist/esm/admin/tenant.js +0 -43
- package/dist/esm/admin/tenant.js.map +0 -1
- package/dist/esm/global.d.js +0 -1
- package/dist/esm/global.d.js.map +0 -1
- package/dist/esm/index.js +0 -24
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/ternsecureauth.js +0 -16
- package/dist/esm/ternsecureauth.js.map +0 -1
- package/dist/esm/utils/admin-init.js +0 -24
- package/dist/esm/utils/admin-init.js.map +0 -1
- package/dist/esm/utils/config.js +0 -84
- package/dist/esm/utils/config.js.map +0 -1
- package/dist/types/admin/sessionTernSecure.d.ts +0 -36
- package/dist/types/admin/sessionTernSecure.d.ts.map +0 -1
- package/dist/types/admin/tenant.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -5
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/ternsecureauth.d.ts.map +0 -1
- package/dist/types/utils/admin-init.d.ts +0 -5
- package/dist/types/utils/admin-init.d.ts.map +0 -1
- package/dist/types/utils/config.d.ts.map +0 -1
- /package/dist/{types/admin → admin}/tenant.d.ts +0 -0
- /package/dist/{types/ternsecureauth.d.ts → ternsecureauth.d.ts} +0 -0
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
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
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/admin/index.ts
|
|
31
|
+
var admin_exports = {};
|
|
32
|
+
__export(admin_exports, {
|
|
33
|
+
ClearNextSessionCookie: () => ClearNextSessionCookie,
|
|
34
|
+
CreateNextSessionCookie: () => CreateNextSessionCookie,
|
|
35
|
+
GetNextIdToken: () => GetNextIdToken,
|
|
36
|
+
GetNextServerSessionCookie: () => GetNextServerSessionCookie,
|
|
37
|
+
SetNextServerSession: () => SetNextServerSession,
|
|
38
|
+
SetNextServerToken: () => SetNextServerToken,
|
|
39
|
+
TernSecureTenantManager: () => TernSecureTenantManager,
|
|
40
|
+
VerifyNextTernIdToken: () => VerifyNextTernIdToken,
|
|
41
|
+
VerifyNextTernSessionCookie: () => VerifyNextTernSessionCookie,
|
|
42
|
+
adminTernSecureAuth: () => adminTernSecureAuth,
|
|
43
|
+
adminTernSecureDb: () => adminTernSecureDb,
|
|
44
|
+
authenticateRequest: () => authenticateRequest,
|
|
45
|
+
clearSessionCookie: () => clearSessionCookie,
|
|
46
|
+
createBackendInstance: () => createBackendInstance,
|
|
47
|
+
createSessionCookie: () => createSessionCookie,
|
|
48
|
+
createTenant: () => createTenant,
|
|
49
|
+
createTenantUser: () => createTenantUser,
|
|
50
|
+
initializeAdminConfig: () => initializeAdminConfig,
|
|
51
|
+
signedIn: () => signedIn
|
|
52
|
+
});
|
|
53
|
+
module.exports = __toCommonJS(admin_exports);
|
|
54
|
+
|
|
55
|
+
// src/admin/sessionTernSecure.ts
|
|
56
|
+
var import_errors = require("@tern-secure/shared/errors");
|
|
57
|
+
|
|
58
|
+
// src/tokens/sessionConfig.ts
|
|
59
|
+
var getSessionConfig = (options) => {
|
|
60
|
+
const cookieConfig = options?.cookies?.session_cookie;
|
|
61
|
+
return {
|
|
62
|
+
COOKIE_NAME: cookieConfig?.name,
|
|
63
|
+
DEFAULT_EXPIRES_IN_MS: cookieConfig?.attributes?.maxAge,
|
|
64
|
+
DEFAULT_EXPIRES_IN_SECONDS: Math.floor((cookieConfig?.attributes?.maxAge || 0) / 1e3),
|
|
65
|
+
REVOKE_REFRESH_TOKENS_ON_SIGNOUT: cookieConfig?.revokeRefreshTokensOnSignOut
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
var getCookieOptions = (options) => {
|
|
69
|
+
const cookieConfig = options?.cookies?.session_cookie;
|
|
70
|
+
return {
|
|
71
|
+
httpOnly: cookieConfig?.attributes?.httpOnly,
|
|
72
|
+
secure: cookieConfig?.attributes?.secure,
|
|
73
|
+
sameSite: cookieConfig?.attributes?.sameSite,
|
|
74
|
+
path: cookieConfig?.attributes?.path
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/utils/admin-init.ts
|
|
79
|
+
var import_firebase_admin = __toESM(require("firebase-admin"));
|
|
80
|
+
|
|
81
|
+
// src/utils/config.ts
|
|
82
|
+
var loadAdminConfig = () => ({
|
|
83
|
+
projectId: process.env.FIREBASE_PROJECT_ID || "",
|
|
84
|
+
clientEmail: process.env.FIREBASE_CLIENT_EMAIL || "",
|
|
85
|
+
privateKey: process.env.FIREBASE_PRIVATE_KEY || ""
|
|
86
|
+
});
|
|
87
|
+
var validateAdminConfig = (config) => {
|
|
88
|
+
const requiredFields = [
|
|
89
|
+
"projectId",
|
|
90
|
+
"clientEmail",
|
|
91
|
+
"privateKey"
|
|
92
|
+
];
|
|
93
|
+
const errors = [];
|
|
94
|
+
requiredFields.forEach((field) => {
|
|
95
|
+
if (!config[field]) {
|
|
96
|
+
errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
return {
|
|
100
|
+
isValid: errors.length === 0,
|
|
101
|
+
errors,
|
|
102
|
+
config
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
var initializeAdminConfig = () => {
|
|
106
|
+
const config = loadAdminConfig();
|
|
107
|
+
const validationResult = validateAdminConfig(config);
|
|
108
|
+
if (!validationResult.isValid) {
|
|
109
|
+
throw new Error(
|
|
110
|
+
`Firebase Admin configuration validation failed:
|
|
111
|
+
${validationResult.errors.join("\n")}`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return config;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// src/utils/admin-init.ts
|
|
118
|
+
if (!import_firebase_admin.default.apps.length) {
|
|
119
|
+
try {
|
|
120
|
+
const config = initializeAdminConfig();
|
|
121
|
+
import_firebase_admin.default.initializeApp({
|
|
122
|
+
credential: import_firebase_admin.default.credential.cert({
|
|
123
|
+
...config,
|
|
124
|
+
privateKey: config.privateKey.replace(/\\n/g, "\n")
|
|
125
|
+
})
|
|
126
|
+
});
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error("Firebase admin initialization error", error);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
var adminTernSecureAuth = import_firebase_admin.default.auth();
|
|
132
|
+
var adminTernSecureDb = import_firebase_admin.default.firestore();
|
|
133
|
+
var TernSecureTenantManager = import_firebase_admin.default.auth().tenantManager();
|
|
134
|
+
function getAuthForTenant(tenantId) {
|
|
135
|
+
if (tenantId) {
|
|
136
|
+
return TernSecureTenantManager.authForTenant(tenantId);
|
|
137
|
+
}
|
|
138
|
+
return import_firebase_admin.default.auth();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/admin/sessionTernSecure.ts
|
|
142
|
+
var SESSION_CONSTANTS = {
|
|
143
|
+
COOKIE_NAME: "_session_cookie",
|
|
144
|
+
//DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days
|
|
145
|
+
//DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5, // 5days
|
|
146
|
+
DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1e3,
|
|
147
|
+
// 5 minutes
|
|
148
|
+
DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,
|
|
149
|
+
REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
|
|
150
|
+
};
|
|
151
|
+
var COOKIE_OPTIONS = {
|
|
152
|
+
httpOnly: true,
|
|
153
|
+
secure: process.env.NODE_ENV === "production",
|
|
154
|
+
sameSite: "strict",
|
|
155
|
+
path: "/"
|
|
156
|
+
};
|
|
157
|
+
async function createSessionCookie(params, cookieStore, options) {
|
|
158
|
+
try {
|
|
159
|
+
const tenantAuth = getAuthForTenant(options?.tenantId);
|
|
160
|
+
const sessionConfig = getSessionConfig(options);
|
|
161
|
+
const cookieOptions = getCookieOptions(options);
|
|
162
|
+
let decodedToken;
|
|
163
|
+
let sessionCookie;
|
|
164
|
+
const idToken = typeof params === "string" ? params : params.idToken;
|
|
165
|
+
if (!idToken) {
|
|
166
|
+
const error = new Error("ID token is required for session creation");
|
|
167
|
+
console.error("[createSessionCookie] Missing ID token:", error);
|
|
168
|
+
return {
|
|
169
|
+
success: false,
|
|
170
|
+
message: "ID token is required",
|
|
171
|
+
error: "INVALID_TOKEN",
|
|
172
|
+
cookieSet: false
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
console.log("Verifying ID token for tenant:", options?.tenantId);
|
|
177
|
+
decodedToken = await tenantAuth.verifyIdToken(idToken);
|
|
178
|
+
} catch (verifyError) {
|
|
179
|
+
console.error(
|
|
180
|
+
"[createSessionCookie] ID token verification failed:",
|
|
181
|
+
verifyError
|
|
182
|
+
);
|
|
183
|
+
const authError = (0, import_errors.handleFirebaseAuthError)(verifyError);
|
|
184
|
+
return {
|
|
185
|
+
success: false,
|
|
186
|
+
message: authError.message,
|
|
187
|
+
error: authError.code,
|
|
188
|
+
cookieSet: false
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
if (!decodedToken) {
|
|
192
|
+
const error = new Error("Invalid ID token - verification returned null");
|
|
193
|
+
console.error(
|
|
194
|
+
"[createSessionCookie] Token verification returned null:",
|
|
195
|
+
error
|
|
196
|
+
);
|
|
197
|
+
return {
|
|
198
|
+
success: false,
|
|
199
|
+
message: "Invalid ID token",
|
|
200
|
+
error: "INVALID_TOKEN",
|
|
201
|
+
cookieSet: false
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
sessionCookie = await tenantAuth.createSessionCookie(idToken, {
|
|
206
|
+
expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_MS
|
|
207
|
+
});
|
|
208
|
+
} catch (sessionError) {
|
|
209
|
+
console.error(
|
|
210
|
+
"[createSessionCookie] Firebase session cookie creation failed:",
|
|
211
|
+
sessionError
|
|
212
|
+
);
|
|
213
|
+
const authError = (0, import_errors.handleFirebaseAuthError)(sessionError);
|
|
214
|
+
return {
|
|
215
|
+
success: false,
|
|
216
|
+
message: authError.message,
|
|
217
|
+
error: authError.code,
|
|
218
|
+
cookieSet: false
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
let cookieSetSuccessfully = false;
|
|
222
|
+
try {
|
|
223
|
+
cookieStore.set(SESSION_CONSTANTS.COOKIE_NAME, sessionCookie, {
|
|
224
|
+
maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
|
|
225
|
+
...COOKIE_OPTIONS
|
|
226
|
+
});
|
|
227
|
+
const verifySetCookie = await cookieStore.get(
|
|
228
|
+
SESSION_CONSTANTS.COOKIE_NAME
|
|
229
|
+
);
|
|
230
|
+
cookieSetSuccessfully = !!verifySetCookie?.value;
|
|
231
|
+
if (!cookieSetSuccessfully) {
|
|
232
|
+
const error = new Error("Session cookie was not set successfully");
|
|
233
|
+
console.error(
|
|
234
|
+
"[createSessionCookie] Cookie verification failed:",
|
|
235
|
+
error
|
|
236
|
+
);
|
|
237
|
+
throw error;
|
|
238
|
+
}
|
|
239
|
+
} catch (cookieError) {
|
|
240
|
+
console.error(
|
|
241
|
+
"[createSessionCookie] Failed to set session cookie:",
|
|
242
|
+
cookieError
|
|
243
|
+
);
|
|
244
|
+
return {
|
|
245
|
+
success: false,
|
|
246
|
+
message: "Failed to set session cookie",
|
|
247
|
+
error: "COOKIE_SET_FAILED",
|
|
248
|
+
cookieSet: false
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
console.log(
|
|
252
|
+
`[createSessionCookie] Session cookie created successfully for user: ${decodedToken.uid}`
|
|
253
|
+
);
|
|
254
|
+
return {
|
|
255
|
+
success: true,
|
|
256
|
+
message: "Session created successfully",
|
|
257
|
+
expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
|
|
258
|
+
cookieSet: cookieSetSuccessfully
|
|
259
|
+
};
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error("[createSessionCookie] Unexpected error:", error);
|
|
262
|
+
const authError = (0, import_errors.handleFirebaseAuthError)(error);
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
message: authError.message || "Failed to create session",
|
|
266
|
+
error: authError.code || "INTERNAL_ERROR",
|
|
267
|
+
cookieSet: false
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async function clearSessionCookie(cookieStore, options) {
|
|
272
|
+
try {
|
|
273
|
+
const adminAuth = getAuthForTenant(options?.tenantId);
|
|
274
|
+
const sessionCookie = await cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);
|
|
275
|
+
await cookieStore.delete(SESSION_CONSTANTS.COOKIE_NAME);
|
|
276
|
+
await cookieStore.delete("_session_token");
|
|
277
|
+
await cookieStore.delete("_session");
|
|
278
|
+
if (SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
|
|
279
|
+
try {
|
|
280
|
+
const decodedClaims = await adminAuth.verifySessionCookie(
|
|
281
|
+
sessionCookie.value
|
|
282
|
+
);
|
|
283
|
+
await adminAuth.revokeRefreshTokens(decodedClaims.sub);
|
|
284
|
+
console.log(
|
|
285
|
+
`[clearSessionCookie] Successfully revoked tokens for user: ${decodedClaims.sub}`
|
|
286
|
+
);
|
|
287
|
+
} catch (revokeError) {
|
|
288
|
+
console.error(
|
|
289
|
+
"[clearSessionCookie] Failed to revoke refresh tokens:",
|
|
290
|
+
revokeError
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
console.log("[clearSessionCookie] Session cookies cleared successfully");
|
|
295
|
+
return {
|
|
296
|
+
success: true,
|
|
297
|
+
message: "Session cleared successfully",
|
|
298
|
+
cookieSet: false
|
|
299
|
+
};
|
|
300
|
+
} catch (error) {
|
|
301
|
+
console.error("[clearSessionCookie] Unexpected error:", error);
|
|
302
|
+
const authError = (0, import_errors.handleFirebaseAuthError)(error);
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
message: authError.message || "Failed to clear session",
|
|
306
|
+
error: authError.code || "INTERNAL_ERROR",
|
|
307
|
+
cookieSet: false
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// src/admin/tenant.ts
|
|
313
|
+
async function createTenant(displayName, emailSignInConfig, multiFactorConfig) {
|
|
314
|
+
try {
|
|
315
|
+
const tenantConfig = {
|
|
316
|
+
displayName,
|
|
317
|
+
emailSignInConfig,
|
|
318
|
+
...multiFactorConfig && { multiFactorConfig }
|
|
319
|
+
};
|
|
320
|
+
const tenant = await TernSecureTenantManager.createTenant(tenantConfig);
|
|
321
|
+
return {
|
|
322
|
+
success: true,
|
|
323
|
+
tenantId: tenant.tenantId,
|
|
324
|
+
displayName: tenant.displayName
|
|
325
|
+
};
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.error("Error creating tenant:", error);
|
|
328
|
+
throw new Error("Failed to create tenant");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async function createTenantUser(email, password, tenantId) {
|
|
332
|
+
try {
|
|
333
|
+
const tenantAuth = TernSecureTenantManager.authForTenant(tenantId);
|
|
334
|
+
const userRecord = await tenantAuth.createUser({
|
|
335
|
+
email,
|
|
336
|
+
password,
|
|
337
|
+
emailVerified: false,
|
|
338
|
+
disabled: false
|
|
339
|
+
});
|
|
340
|
+
return {
|
|
341
|
+
success: true,
|
|
342
|
+
message: "Tenant user created successfully",
|
|
343
|
+
user: userRecord.uid
|
|
344
|
+
};
|
|
345
|
+
} catch (error) {
|
|
346
|
+
console.error("Error creating tenant user:", error);
|
|
347
|
+
throw new Error("Failed to create tenant user");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/admin/nextSessionTernSecure.ts
|
|
352
|
+
var import_errors2 = require("@tern-secure/shared/errors");
|
|
353
|
+
var import_headers = require("next/headers");
|
|
354
|
+
var SESSION_CONSTANTS2 = {
|
|
355
|
+
COOKIE_NAME: "_session_cookie",
|
|
356
|
+
DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1e3,
|
|
357
|
+
// 5 days
|
|
358
|
+
DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,
|
|
359
|
+
REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
|
|
360
|
+
};
|
|
361
|
+
async function CreateNextSessionCookie(idToken) {
|
|
362
|
+
try {
|
|
363
|
+
const expiresIn = 60 * 60 * 24 * 5 * 1e3;
|
|
364
|
+
const sessionCookie = await adminTernSecureAuth.createSessionCookie(idToken, {
|
|
365
|
+
expiresIn
|
|
366
|
+
});
|
|
367
|
+
const cookieStore = await (0, import_headers.cookies)();
|
|
368
|
+
cookieStore.set("_session_cookie", sessionCookie, {
|
|
369
|
+
maxAge: expiresIn,
|
|
370
|
+
httpOnly: true,
|
|
371
|
+
secure: process.env.NODE_ENV === "production",
|
|
372
|
+
path: "/"
|
|
373
|
+
});
|
|
374
|
+
return { success: true, message: "Session created" };
|
|
375
|
+
} catch (error) {
|
|
376
|
+
return { success: false, message: "Failed to create session" };
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async function GetNextServerSessionCookie() {
|
|
380
|
+
const cookieStore = await (0, import_headers.cookies)();
|
|
381
|
+
const sessionCookie = cookieStore.get("_session_cookie")?.value;
|
|
382
|
+
if (!sessionCookie) {
|
|
383
|
+
throw new Error("No session cookie found");
|
|
384
|
+
}
|
|
385
|
+
try {
|
|
386
|
+
const decondeClaims = await adminTernSecureAuth.verifySessionCookie(
|
|
387
|
+
sessionCookie,
|
|
388
|
+
true
|
|
389
|
+
);
|
|
390
|
+
return {
|
|
391
|
+
token: sessionCookie,
|
|
392
|
+
userId: decondeClaims.uid
|
|
393
|
+
};
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error("Error verifying session:", error);
|
|
396
|
+
throw new Error("Invalid Session");
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
async function GetNextIdToken() {
|
|
400
|
+
const cookieStore = await (0, import_headers.cookies)();
|
|
401
|
+
const token = cookieStore.get("_session_token")?.value;
|
|
402
|
+
if (!token) {
|
|
403
|
+
throw new Error("No session cookie found");
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const decodedClaims = await adminTernSecureAuth.verifyIdToken(token);
|
|
407
|
+
return {
|
|
408
|
+
token,
|
|
409
|
+
userId: decodedClaims.uid
|
|
410
|
+
};
|
|
411
|
+
} catch (error) {
|
|
412
|
+
console.error("Error verifying session:", error);
|
|
413
|
+
throw new Error("Invalid Session");
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
async function SetNextServerSession(token) {
|
|
417
|
+
try {
|
|
418
|
+
const cookieStore = await (0, import_headers.cookies)();
|
|
419
|
+
cookieStore.set("_session_token", token, {
|
|
420
|
+
httpOnly: true,
|
|
421
|
+
secure: process.env.NODE_ENV === "production",
|
|
422
|
+
sameSite: "strict",
|
|
423
|
+
maxAge: 60 * 60,
|
|
424
|
+
// 1 hour
|
|
425
|
+
path: "/"
|
|
426
|
+
});
|
|
427
|
+
return { success: true, message: "Session created" };
|
|
428
|
+
} catch {
|
|
429
|
+
return { success: false, message: "Failed to create session" };
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async function SetNextServerToken(token) {
|
|
433
|
+
try {
|
|
434
|
+
const cookieStore = await (0, import_headers.cookies)();
|
|
435
|
+
cookieStore.set("_tern", token, {
|
|
436
|
+
httpOnly: true,
|
|
437
|
+
secure: process.env.NODE_ENV === "production",
|
|
438
|
+
sameSite: "strict",
|
|
439
|
+
maxAge: 60 * 60,
|
|
440
|
+
// 1 hour
|
|
441
|
+
path: "/"
|
|
442
|
+
});
|
|
443
|
+
return { success: true, message: "Session created" };
|
|
444
|
+
} catch {
|
|
445
|
+
return { success: false, message: "Failed to create session" };
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
async function VerifyNextTernIdToken(token) {
|
|
449
|
+
try {
|
|
450
|
+
const decodedToken = await adminTernSecureAuth.verifyIdToken(token);
|
|
451
|
+
return {
|
|
452
|
+
...decodedToken,
|
|
453
|
+
valid: true
|
|
454
|
+
};
|
|
455
|
+
} catch (error) {
|
|
456
|
+
console.error("[VerifyNextTernIdToken] Error verifying session:", error);
|
|
457
|
+
const authError = (0, import_errors2.handleFirebaseAuthError)(error);
|
|
458
|
+
return {
|
|
459
|
+
valid: false,
|
|
460
|
+
error: authError
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
async function VerifyNextTernSessionCookie(session) {
|
|
465
|
+
try {
|
|
466
|
+
const res = await adminTernSecureAuth.verifySessionCookie(session);
|
|
467
|
+
console.warn(
|
|
468
|
+
"[VerifyNextTernSessionCookie] uid in Decoded Token:",
|
|
469
|
+
res.uid
|
|
470
|
+
);
|
|
471
|
+
return {
|
|
472
|
+
valid: true,
|
|
473
|
+
...res
|
|
474
|
+
};
|
|
475
|
+
} catch (error) {
|
|
476
|
+
console.error(
|
|
477
|
+
"[VerifyNextTernSessionCookie] Error verifying session:",
|
|
478
|
+
error
|
|
479
|
+
);
|
|
480
|
+
const authError = (0, import_errors2.handleFirebaseAuthError)(error);
|
|
481
|
+
return {
|
|
482
|
+
valid: false,
|
|
483
|
+
error: authError
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
async function ClearNextSessionCookie(tenantId) {
|
|
488
|
+
try {
|
|
489
|
+
console.log("[clearSessionCookie] Clearing session for tenant:", tenantId);
|
|
490
|
+
const tenantAuth = getAuthForTenant(tenantId);
|
|
491
|
+
const cookieStore = await (0, import_headers.cookies)();
|
|
492
|
+
const sessionCookie = cookieStore.get(SESSION_CONSTANTS2.COOKIE_NAME);
|
|
493
|
+
cookieStore.delete(SESSION_CONSTANTS2.COOKIE_NAME);
|
|
494
|
+
cookieStore.delete("_session_token");
|
|
495
|
+
cookieStore.delete("_session");
|
|
496
|
+
if (SESSION_CONSTANTS2.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
|
|
497
|
+
try {
|
|
498
|
+
const decodedClaims = await tenantAuth.verifySessionCookie(
|
|
499
|
+
sessionCookie.value
|
|
500
|
+
);
|
|
501
|
+
await tenantAuth.revokeRefreshTokens(decodedClaims.sub);
|
|
502
|
+
console.log(
|
|
503
|
+
`[clearSessionCookie] Successfully revoked tokens for user: ${decodedClaims.sub}`
|
|
504
|
+
);
|
|
505
|
+
} catch (revokeError) {
|
|
506
|
+
console.error(
|
|
507
|
+
"[ClearNextSessionCookie] Failed to revoke refresh tokens:",
|
|
508
|
+
revokeError
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return { success: true, message: "Session cleared successfully" };
|
|
513
|
+
} catch (error) {
|
|
514
|
+
console.error("Error clearing session:", error);
|
|
515
|
+
return { success: false, message: "Failed to clear session cookies" };
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/tokens/ternSecureRequest.ts
|
|
520
|
+
var import_cookie = require("cookie");
|
|
521
|
+
|
|
522
|
+
// src/constants.ts
|
|
523
|
+
var MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;
|
|
524
|
+
var DEFAULT_CACHE_DURATION = 3600 * 1e3;
|
|
525
|
+
var Attributes = {
|
|
526
|
+
AuthToken: "__ternsecureAuthToken",
|
|
527
|
+
AuthSignature: "__ternsecureAuthSignature",
|
|
528
|
+
AuthStatus: "__ternsecureAuthStatus",
|
|
529
|
+
AuthReason: "__ternsecureAuthReason",
|
|
530
|
+
AuthMessage: "__ternsecureAuthMessage",
|
|
531
|
+
TernSecureUrl: "__ternsecureUrl"
|
|
532
|
+
};
|
|
533
|
+
var Cookies = {
|
|
534
|
+
Session: "__session",
|
|
535
|
+
IdToken: "_tern",
|
|
536
|
+
SessionCookie: "_session_cookie",
|
|
537
|
+
SessionToken: "_session_token",
|
|
538
|
+
Refresh: "__refresh",
|
|
539
|
+
Handshake: "__ternsecure_handshake",
|
|
540
|
+
DevBrowser: "__ternsecure_db_jwt",
|
|
541
|
+
RedirectCount: "__ternsecure_redirect_count",
|
|
542
|
+
HandshakeNonce: "__ternsecure_handshake_nonce"
|
|
543
|
+
};
|
|
544
|
+
var Headers2 = {
|
|
545
|
+
Accept: "accept",
|
|
546
|
+
AuthMessage: "x-ternsecure-auth-message",
|
|
547
|
+
Authorization: "authorization",
|
|
548
|
+
AuthReason: "x-ternsecure-auth-reason",
|
|
549
|
+
AuthSignature: "x-ternsecure-auth-signature",
|
|
550
|
+
AuthStatus: "x-ternsecure-auth-status",
|
|
551
|
+
AuthToken: "x-ternsecure-auth-token",
|
|
552
|
+
CacheControl: "cache-control",
|
|
553
|
+
TernSecureRedirectTo: "x-ternsecure-redirect-to",
|
|
554
|
+
TernSecureRequestData: "x-ternsecure-request-data",
|
|
555
|
+
TernSecureUrl: "x-ternsecure-url",
|
|
556
|
+
CloudFrontForwardedProto: "cloudfront-forwarded-proto",
|
|
557
|
+
ContentType: "content-type",
|
|
558
|
+
ContentSecurityPolicy: "content-security-policy",
|
|
559
|
+
ContentSecurityPolicyReportOnly: "content-security-policy-report-only",
|
|
560
|
+
EnableDebug: "x-ternsecure-debug",
|
|
561
|
+
ForwardedHost: "x-forwarded-host",
|
|
562
|
+
ForwardedPort: "x-forwarded-port",
|
|
563
|
+
ForwardedProto: "x-forwarded-proto",
|
|
564
|
+
Host: "host",
|
|
565
|
+
Location: "location",
|
|
566
|
+
Nonce: "x-nonce",
|
|
567
|
+
Origin: "origin",
|
|
568
|
+
Referrer: "referer",
|
|
569
|
+
SecFetchDest: "sec-fetch-dest",
|
|
570
|
+
UserAgent: "user-agent",
|
|
571
|
+
ReportingEndpoints: "reporting-endpoints"
|
|
572
|
+
};
|
|
573
|
+
var ContentTypes = {
|
|
574
|
+
Json: "application/json"
|
|
575
|
+
};
|
|
576
|
+
var constants = {
|
|
577
|
+
Attributes,
|
|
578
|
+
Cookies,
|
|
579
|
+
Headers: Headers2,
|
|
580
|
+
ContentTypes
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// src/tokens/ternUrl.ts
|
|
584
|
+
var TernUrl = class extends URL {
|
|
585
|
+
isCrossOrigin(other) {
|
|
586
|
+
return this.origin !== new URL(other.toString()).origin;
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
var createTernUrl = (...args) => {
|
|
590
|
+
return new TernUrl(...args);
|
|
591
|
+
};
|
|
592
|
+
|
|
593
|
+
// src/tokens/ternSecureRequest.ts
|
|
594
|
+
var TernSecureRequest = class extends Request {
|
|
595
|
+
ternUrl;
|
|
596
|
+
cookies;
|
|
597
|
+
constructor(input, init) {
|
|
598
|
+
const url = typeof input !== "string" && "url" in input ? input.url : String(input);
|
|
599
|
+
super(url, init || typeof input === "string" ? void 0 : input);
|
|
600
|
+
this.ternUrl = this.deriveUrlFromHeaders(this);
|
|
601
|
+
this.cookies = this.parseCookies(this);
|
|
602
|
+
}
|
|
603
|
+
toJSON() {
|
|
604
|
+
return {
|
|
605
|
+
url: this.ternUrl.href,
|
|
606
|
+
method: this.method,
|
|
607
|
+
headers: JSON.stringify(Object.fromEntries(this.headers)),
|
|
608
|
+
ternUrl: this.ternUrl.toString(),
|
|
609
|
+
cookies: JSON.stringify(Object.fromEntries(this.cookies))
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
deriveUrlFromHeaders(req) {
|
|
613
|
+
const initialUrl = new URL(req.url);
|
|
614
|
+
const forwardedProto = req.headers.get(constants.Headers.ForwardedProto);
|
|
615
|
+
const forwardedHost = req.headers.get(constants.Headers.ForwardedHost);
|
|
616
|
+
const host = req.headers.get(constants.Headers.Host);
|
|
617
|
+
const protocol = initialUrl.protocol;
|
|
618
|
+
const resolvedHost = this.getFirstValueFromHeader(forwardedHost) ?? host;
|
|
619
|
+
const resolvedProtocol = this.getFirstValueFromHeader(forwardedProto) ?? protocol?.replace(/[:/]/, "");
|
|
620
|
+
const origin = resolvedHost && resolvedProtocol ? `${resolvedProtocol}://${resolvedHost}` : initialUrl.origin;
|
|
621
|
+
if (origin === initialUrl.origin) {
|
|
622
|
+
return createTernUrl(initialUrl);
|
|
623
|
+
}
|
|
624
|
+
return createTernUrl(initialUrl.pathname + initialUrl.search, origin);
|
|
625
|
+
}
|
|
626
|
+
getFirstValueFromHeader(value) {
|
|
627
|
+
return value?.split(",")[0];
|
|
628
|
+
}
|
|
629
|
+
parseCookies(req) {
|
|
630
|
+
const cookiesRecord = (0, import_cookie.parse)(
|
|
631
|
+
this.decodeCookieValue(req.headers.get("cookie") || "")
|
|
632
|
+
);
|
|
633
|
+
return new Map(Object.entries(cookiesRecord));
|
|
634
|
+
}
|
|
635
|
+
decodeCookieValue(str) {
|
|
636
|
+
return str ? str.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent) : str;
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
var createTernSecureRequest = (...args) => {
|
|
640
|
+
return args[0] instanceof TernSecureRequest ? args[0] : new TernSecureRequest(...args);
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
// src/instance/backendInstance.ts
|
|
644
|
+
var createBackendInstance = async (request) => {
|
|
645
|
+
const ternSecureRequest = createTernSecureRequest(request);
|
|
646
|
+
const requestState = await authenticateRequest(request);
|
|
647
|
+
return {
|
|
648
|
+
ternSecureRequest,
|
|
649
|
+
requestState
|
|
650
|
+
};
|
|
651
|
+
};
|
|
652
|
+
async function authenticateRequest(request) {
|
|
653
|
+
const sessionCookie = request.headers.get("cookie");
|
|
654
|
+
const sessionToken = sessionCookie?.split(";").find((c) => c.trim().startsWith("_session_cookie="))?.split("=")[1];
|
|
655
|
+
if (!sessionToken) {
|
|
656
|
+
throw new Error("No session token found");
|
|
657
|
+
}
|
|
658
|
+
const verificationResult = await VerifyNextTernSessionCookie(sessionToken);
|
|
659
|
+
if (!verificationResult.valid) {
|
|
660
|
+
throw new Error("Invalid session token");
|
|
661
|
+
}
|
|
662
|
+
return signedIn(
|
|
663
|
+
verificationResult,
|
|
664
|
+
new Headers(request.headers),
|
|
665
|
+
sessionToken
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
function signInAuthObject(session) {
|
|
669
|
+
return {
|
|
670
|
+
session,
|
|
671
|
+
userId: session.uid,
|
|
672
|
+
has: {}
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
function signedIn(session, headers = new Headers(), token) {
|
|
676
|
+
const authObject = signInAuthObject(session);
|
|
677
|
+
return {
|
|
678
|
+
auth: () => authObject,
|
|
679
|
+
token,
|
|
680
|
+
headers
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
684
|
+
0 && (module.exports = {
|
|
685
|
+
ClearNextSessionCookie,
|
|
686
|
+
CreateNextSessionCookie,
|
|
687
|
+
GetNextIdToken,
|
|
688
|
+
GetNextServerSessionCookie,
|
|
689
|
+
SetNextServerSession,
|
|
690
|
+
SetNextServerToken,
|
|
691
|
+
TernSecureTenantManager,
|
|
692
|
+
VerifyNextTernIdToken,
|
|
693
|
+
VerifyNextTernSessionCookie,
|
|
694
|
+
adminTernSecureAuth,
|
|
695
|
+
adminTernSecureDb,
|
|
696
|
+
authenticateRequest,
|
|
697
|
+
clearSessionCookie,
|
|
698
|
+
createBackendInstance,
|
|
699
|
+
createSessionCookie,
|
|
700
|
+
createTenant,
|
|
701
|
+
createTenantUser,
|
|
702
|
+
initializeAdminConfig,
|
|
703
|
+
signedIn
|
|
704
|
+
});
|
|
705
|
+
//# sourceMappingURL=index.js.map
|