@culturefy/shared 1.0.63 → 1.0.65
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/build/cjs/enums/secretKeys.enum.js +0 -1
- package/build/cjs/enums/secretKeys.enum.js.map +1 -1
- package/build/cjs/interfaces/user.js.map +1 -1
- package/build/cjs/middlewares/verify-middleware.js +72 -18
- package/build/cjs/middlewares/verify-middleware.js.map +1 -1
- package/build/cjs/repositories/multi-tenant.repository.js +82 -34
- package/build/cjs/repositories/multi-tenant.repository.js.map +1 -1
- package/build/cjs/repositories/tenant-base.repository.js +7 -1
- package/build/cjs/repositories/tenant-base.repository.js.map +1 -1
- package/build/cjs/utils/initializers.js +11 -5
- package/build/cjs/utils/initializers.js.map +1 -1
- package/build/esm/enums/secretKeys.enum.js +0 -1
- package/build/esm/enums/secretKeys.enum.js.map +1 -1
- package/build/esm/interfaces/user.js.map +1 -1
- package/build/esm/middlewares/verify-middleware.js +74 -20
- package/build/esm/middlewares/verify-middleware.js.map +1 -1
- package/build/esm/repositories/multi-tenant.repository.js +82 -34
- package/build/esm/repositories/multi-tenant.repository.js.map +1 -1
- package/build/esm/repositories/tenant-base.repository.js +7 -1
- package/build/esm/repositories/tenant-base.repository.js.map +1 -1
- package/build/esm/utils/initializers.js +11 -5
- package/build/esm/utils/initializers.js.map +1 -1
- package/build/src/enums/secretKeys.enum.d.ts +0 -1
- package/build/src/enums/secretKeys.enum.js +0 -1
- package/build/src/enums/secretKeys.enum.js.map +1 -1
- package/build/src/middlewares/verify-middleware.js +79 -36
- package/build/src/middlewares/verify-middleware.js.map +1 -1
- package/build/src/repositories/multi-tenant.repository.d.ts +1 -0
- package/build/src/repositories/multi-tenant.repository.js +83 -34
- package/build/src/repositories/multi-tenant.repository.js.map +1 -1
- package/build/src/repositories/tenant-base.repository.d.ts +1 -0
- package/build/src/repositories/tenant-base.repository.js +18 -0
- package/build/src/repositories/tenant-base.repository.js.map +1 -1
- package/build/src/utils/initializers.d.ts +1 -0
- package/build/src/utils/initializers.js +11 -5
- package/build/src/utils/initializers.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,7 +17,6 @@ let AzureSecretKeysEnum = exports.AzureSecretKeysEnum = /*#__PURE__*/function (A
|
|
|
17
17
|
// in-use,
|
|
18
18
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_AUTH"] = "DB-CONNECTION-STRING-AUTH";
|
|
19
19
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_USER"] = "DB-CONNECTION-STRING-USER";
|
|
20
|
-
AzureSecretKeysEnum["DB_CONNECTING_STRING_TENANT_BRIDGE"] = "DB-Connecting-String-Tenant-Bridge";
|
|
21
20
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_PAYMENT"] = "DB-CONNECTION-STRING-PAYMENT";
|
|
22
21
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_CORE"] = "DB-CONNECTION-STRING-CORE";
|
|
23
22
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_BILLING"] = "DB-CONNECTION-STRING-BILLING";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secretKeys.enum.js","names":["AzureSecretKeysEnum","exports"],"sources":["../../../src/enums/secretKeys.enum.ts"],"sourcesContent":["// Enum for secret keys\nexport enum AzureSecretKeysEnum {\n KEYCLOAK_ADMIN_CLIENT_SECRET = \"KEYCLOAK-ADMIN-CLIENT-SECRET\",\n KEYCLOAK_ADMIN_CLIENT_ID = \"KEYCLOAK-ADMIN-CLIENT-ID\",\n KEYCLOAK_BASE_URL = \"KEYCLOAK-BASE-URL\",\n STRIPE_PAYMENT_WEBHOOK_SECRET_KEY = \"Stripe-payment-webhook-secret-key\", // in-use\n STRIPE_PRODUCT_WEBHOOK_SECRET = \"Stripe-product-webhook-secret-key\", // in-use\n STRIPE_PRICE_WEBHOOK_SECRET = \"Stripe-price-webhook-secret-key\", // in-use\n EMAIL_SERVICE_URL = \"Email-Service-Url\", // in-use,\n DB_CONNECTING_STRING_AUTH = \"DB-CONNECTION-STRING-AUTH\",\n DB_CONNECTING_STRING_USER = \"DB-CONNECTION-STRING-USER\",\n
|
|
1
|
+
{"version":3,"file":"secretKeys.enum.js","names":["AzureSecretKeysEnum","exports"],"sources":["../../../src/enums/secretKeys.enum.ts"],"sourcesContent":["// Enum for secret keys\nexport enum AzureSecretKeysEnum {\n KEYCLOAK_ADMIN_CLIENT_SECRET = \"KEYCLOAK-ADMIN-CLIENT-SECRET\",\n KEYCLOAK_ADMIN_CLIENT_ID = \"KEYCLOAK-ADMIN-CLIENT-ID\",\n KEYCLOAK_BASE_URL = \"KEYCLOAK-BASE-URL\",\n STRIPE_PAYMENT_WEBHOOK_SECRET_KEY = \"Stripe-payment-webhook-secret-key\", // in-use\n STRIPE_PRODUCT_WEBHOOK_SECRET = \"Stripe-product-webhook-secret-key\", // in-use\n STRIPE_PRICE_WEBHOOK_SECRET = \"Stripe-price-webhook-secret-key\", // in-use\n EMAIL_SERVICE_URL = \"Email-Service-Url\", // in-use,\n DB_CONNECTING_STRING_AUTH = \"DB-CONNECTION-STRING-AUTH\",\n DB_CONNECTING_STRING_USER = \"DB-CONNECTION-STRING-USER\",\n DB_CONNECTING_STRING_PAYMENT = \"DB-CONNECTION-STRING-PAYMENT\",\n DB_CONNECTING_STRING_CORE = \"DB-CONNECTION-STRING-CORE\",\n DB_CONNECTING_STRING_BILLING = \"DB-CONNECTION-STRING-BILLING\",\n DB_CONNECTING_STRING_STAGING = \"DB-CONNECTION-STRING-STAGING\",\n DB_CONNECTING_STRING_BNT_DEV = \"DB-CONNECTION-STRING-BNT-DEV\",\n DB_CONNECTION_STRING_TENANT_BRIDGE = \"DB-CONNECTION-STRING-TENANT-BRIDGE\",\n SERVICE_BUS_CONNECTION_STRING = \"servicebus-connection-string\",\n STRIPE_CUSTOMER_SYNC_WEBHOOK_SECRET = \"stripe-customer-sync-webhook-secret-key\",\n STRIPE_INVOICE_SYNC_WEBHOOK_SECRET = \"stripe-invoice-sync-webhook-secret-key\",\n STRIPE_PRODUCT_SYNC_WEBHOOK_SECRET = \"stripe-product-sync-webhook-secret-key\",\n STRIPE_PRICE_SYNC_WEBHOOK_SECRET = \"stripe-price-sync-webhook-secret-key\",\n STRIPE_SECRET_KEY = \"Stripe-secret-key\",\n STRIPE_WEBHOOK_CUSTOMER_CREATED_SECRET_KEY = \"Stripe-Webhook-Customer-Created-Secret-Key\",\n STRIPE_SUBSCRIPTION_SYNC_WEBHOOK_SECRET = \"stripe-subscription-sync-webhook-secret-key\",\n FIREBASE_SERVICE_ACCOUNTS_VARIABLE = \"firebase_service_accounts_variable\",\n HMS_ACCESS_KEY=\"MEETING-HMS-ACCESS-KEY-APP-SECRET\",\n MEETING_ROOM_APP_SECRET=\"MEETING-ROOM-APP-SECRET\",\n BASE_DB_CLUSTER_CONNECTING_STRING_CHAT = \"BASE-DB-CLUSTER-CONNECTING-STRING-CHAT\",\n AUTH_SERVICE_AUTHENTICATION_URL = \"AUTH-SERVICE-AUTHENTICATION-URL\",\n GCP_PROJECT_ID=\"gcp-project-id\",\n PUBSUB_SERVICE_ACCOUNT_KEYS=\"pubsub-service-account-keys\",\n VAPI_TOKEN = \"vapi-token\",\n GITHUB_TOKEN = \"GITHUB-TOKEN\",\n GITHUB_WORKFLOW_URL = \"GITHUB-WORKFLOW-URL\",\n DB_CONNECTION_STRING_ENCRYPTION_KEY = \"DB-CONNECTION-STRING-ENCRYPTION-KEY\",\n}\n\n// AUTH-SERVICE-AUTHENTICATION-URL\n// https://culturefy-auth-staging.azurewebsites.net/api/verify\n\n// REFRESH-SESSION-URL"],"mappings":";;;;AAAA;AAAA,IACYA,mBAAmB,GAAAC,OAAA,CAAAD,mBAAA,0BAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAI4C;EAJ/DA,mBAAmB;EAKwC;EAL3DA,mBAAmB;EAMoC;EANvDA,mBAAmB;EAOY;EAP/BA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAnBA,mBAAmB;EAAA,OAAnBA,mBAAmB;AAAA,OAqC/B;AACA;AAEA","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.js","names":[],"sources":["../../../src/interfaces/user.ts"],"sourcesContent":["export interface ICreateUser {\n userId: string;\n email: string;\n businessId: string;\n}"],"mappings":"","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"user.js","names":[],"sources":["../../../src/interfaces/user.ts"],"sourcesContent":["export interface ICreateUser {\n userId: string;\n email: string;\n businessId: string;\n}\n"],"mappings":"","ignoreList":[]}
|
|
@@ -55,8 +55,24 @@ const parseCookieHeader = header => {
|
|
|
55
55
|
}
|
|
56
56
|
return out;
|
|
57
57
|
};
|
|
58
|
+
function isLocalRequest(origin, requestUrl) {
|
|
59
|
+
const hostCandidate = origin != null ? origin : requestUrl;
|
|
60
|
+
if (!hostCandidate) return false;
|
|
61
|
+
try {
|
|
62
|
+
const host = new URL(hostCandidate).hostname;
|
|
63
|
+
return host === "localhost" || host.startsWith("127.0.0.1");
|
|
64
|
+
} catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function getSessionMappingCookieName(appId, origin, requestUrl) {
|
|
69
|
+
if (isLocalRequest(origin, requestUrl)) {
|
|
70
|
+
return `session-v1.${appId}.mapping`;
|
|
71
|
+
}
|
|
72
|
+
return `__Secure-session-v1.${appId}.mapping`;
|
|
73
|
+
}
|
|
58
74
|
const verifyMw = async (req, ctx, next) => {
|
|
59
|
-
var _APP_MAP$appId, _p, _ref, _ref$state, _ref2, _tokenMapping$userId$, _tokenMapping$userId, _ref3, _p$sub, _ref4, _p$cfy_bid, _ref5, _p$email, _p$name, _ref6, _p$resource_access$
|
|
75
|
+
var _APP_MAP$appId, _req$headers$get, _p, _ref, _ref$state, _ref2, _tokenMapping$userId$, _tokenMapping$userId, _ref3, _p$sub, _ref4, _p$cfy_bid, _ref5, _p$email, _p$name, _ref6, _p$resource_access$to, _p$resource_access, _p$realm_access;
|
|
60
76
|
const appId = req.headers.get("app-id");
|
|
61
77
|
if (!appId || !(_constants.APP_MAP != null && (_APP_MAP$appId = _constants.APP_MAP[appId]) != null && _APP_MAP$appId.clientId)) {
|
|
62
78
|
return {
|
|
@@ -73,11 +89,12 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
73
89
|
})
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
|
-
const
|
|
92
|
+
const clientId = _constants.APP_MAP[appId].clientId;
|
|
77
93
|
|
|
78
94
|
// cookies
|
|
79
95
|
const cookies = parseCookieHeader(req.headers.get("cookie"));
|
|
80
|
-
|
|
96
|
+
const requestOrigin = (_req$headers$get = req.headers.get("origin")) != null ? _req$headers$get : undefined;
|
|
97
|
+
let mapping = cookies[getSessionMappingCookieName(appId, requestOrigin, req.url)] || cookies[`__Secure-session-v1.${appId}.mapping`] || cookies[`session-v1.${appId}.mapping`] || req.headers.get("x-session-mapping") || req.headers.get("x-token-mapping");
|
|
81
98
|
if (!mapping) {
|
|
82
99
|
return {
|
|
83
100
|
status: 401,
|
|
@@ -166,7 +183,22 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
166
183
|
};
|
|
167
184
|
}
|
|
168
185
|
const realm = tokenMapping.realmId;
|
|
169
|
-
const
|
|
186
|
+
const tokenClientId = tokenMapping.clientId;
|
|
187
|
+
if (!tokenClientId || tokenClientId !== clientId) {
|
|
188
|
+
return {
|
|
189
|
+
status: 403,
|
|
190
|
+
headers: {
|
|
191
|
+
"Content-Type": "application/json",
|
|
192
|
+
"Cache-Control": "no-store, no-cache, must-revalidate",
|
|
193
|
+
"Pragma": "no-cache",
|
|
194
|
+
"Vary": "Origin"
|
|
195
|
+
},
|
|
196
|
+
body: JSON.stringify({
|
|
197
|
+
status: "forbidden",
|
|
198
|
+
reason: "client_mismatch"
|
|
199
|
+
})
|
|
200
|
+
};
|
|
201
|
+
}
|
|
170
202
|
|
|
171
203
|
// decode/verify (lightweight; replace with your verifyJsonWebToken if you have it)
|
|
172
204
|
let p;
|
|
@@ -206,11 +238,11 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
206
238
|
// Refresh only when expired
|
|
207
239
|
if (typeof p.exp === "number" && p.exp <= now) {
|
|
208
240
|
// Delegate to refresh helper; it will handle setting cookies/state or returning an error
|
|
209
|
-
return await getNewRefreshToken(req, ctx, appId, realm,
|
|
241
|
+
return await getNewRefreshToken(req, ctx, appId, realm, tokenClientId, rt, mapping, p, next);
|
|
210
242
|
}
|
|
211
243
|
|
|
212
244
|
// audience checks
|
|
213
|
-
const audOk = Array.isArray(p.aud) && p.aud.includes(
|
|
245
|
+
const audOk = Array.isArray(p.aud) && p.aud.includes(tokenClientId) || typeof p.aud === "string" && (p.aud === tokenClientId || p.aud === "account") || p.azp === tokenClientId;
|
|
214
246
|
if (!audOk) {
|
|
215
247
|
return {
|
|
216
248
|
status: 403,
|
|
@@ -238,7 +270,7 @@ const verifyMw = async (req, ctx, next) => {
|
|
|
238
270
|
tenantId,
|
|
239
271
|
email: (_ref5 = (_p$email = p.email) != null ? _p$email : p.preferred_username) != null ? _ref5 : null,
|
|
240
272
|
name: (_p$name = p.name) != null ? _p$name : undefined,
|
|
241
|
-
roles: (_ref6 = (_p$resource_access$
|
|
273
|
+
roles: (_ref6 = (_p$resource_access$to = (_p$resource_access = p.resource_access) == null || (_p$resource_access = _p$resource_access[tokenClientId]) == null ? void 0 : _p$resource_access.roles) != null ? _p$resource_access$to : (_p$realm_access = p.realm_access) == null ? void 0 : _p$realm_access.roles) != null ? _ref6 : [],
|
|
242
274
|
exp: p.exp
|
|
243
275
|
};
|
|
244
276
|
return next();
|
|
@@ -261,15 +293,31 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
261
293
|
})
|
|
262
294
|
};
|
|
263
295
|
}
|
|
264
|
-
ctx.info("
|
|
296
|
+
ctx.info("Refreshing session token", {
|
|
265
297
|
realmId,
|
|
266
|
-
clientId
|
|
267
|
-
rt
|
|
298
|
+
clientId
|
|
268
299
|
});
|
|
269
300
|
|
|
270
301
|
// Call auth service to refresh
|
|
271
302
|
try {
|
|
272
|
-
var _req$headers$
|
|
303
|
+
var _req$headers$get2, _ref7, _ref7$state, _ref8, _updatedMapping$userI, _updatedMapping$userI2, _ref9, _p2$sub, _ref0, _p2$cfy_bid, _ref1, _p2$email, _p2$name, _ref10, _p2$resource_access$c, _p2$resource_access, _p2$realm_access;
|
|
304
|
+
if (!apiURL) {
|
|
305
|
+
ctx.error == null || ctx.error("Refresh session URL is not configured");
|
|
306
|
+
return {
|
|
307
|
+
status: 401,
|
|
308
|
+
headers: {
|
|
309
|
+
"Content-Type": "application/json",
|
|
310
|
+
"Cache-Control": "no-store, no-cache, must-revalidate",
|
|
311
|
+
"Pragma": "no-cache",
|
|
312
|
+
"Vary": "Origin"
|
|
313
|
+
},
|
|
314
|
+
body: JSON.stringify({
|
|
315
|
+
status: "unauthenticated",
|
|
316
|
+
reason: "refresh_not_configured"
|
|
317
|
+
})
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const requestOrigin = (_req$headers$get2 = req.headers.get("origin")) != null ? _req$headers$get2 : undefined;
|
|
273
321
|
const resp = await fetch(apiURL, {
|
|
274
322
|
method: "POST",
|
|
275
323
|
headers: {
|
|
@@ -282,8 +330,7 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
282
330
|
})
|
|
283
331
|
});
|
|
284
332
|
if (!resp.ok) {
|
|
285
|
-
|
|
286
|
-
ctx.warn == null || ctx.warn(`refresh call failed: ${resp.status} ${text}`);
|
|
333
|
+
ctx.warn == null || ctx.warn(`refresh call failed with status ${resp.status}`);
|
|
287
334
|
return {
|
|
288
335
|
status: 401,
|
|
289
336
|
headers: {
|
|
@@ -349,12 +396,15 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
349
396
|
|
|
350
397
|
const mappingCookieValue = Buffer.from(mapping).toString("base64");
|
|
351
398
|
const appConfig = _constants.APP_MAP[appId];
|
|
352
|
-
|
|
353
|
-
|
|
399
|
+
|
|
400
|
+
// 5
|
|
401
|
+
const mappedDomain = pickCookieDomain(appConfig, requestOrigin, req.url);
|
|
402
|
+
const localRequest = isLocalRequest(requestOrigin, req.url);
|
|
403
|
+
(0, _cookies.setCookieKV)(ctx, getSessionMappingCookieName(appId, requestOrigin, req.url), mappingCookieValue, {
|
|
354
404
|
// mapping must be readable by FE in your flow; keep httpOnly default if you prefer server-only
|
|
355
405
|
httpOnly: false,
|
|
356
|
-
secure:
|
|
357
|
-
sameSite: "None",
|
|
406
|
+
secure: !localRequest,
|
|
407
|
+
sameSite: localRequest ? "Lax" : "None",
|
|
358
408
|
maxAge: mappingMaxAge,
|
|
359
409
|
domain: mappedDomain
|
|
360
410
|
});
|
|
@@ -413,7 +463,11 @@ async function getNewRefreshToken(req, ctx, appId, realmId, clientId, rt, mappin
|
|
|
413
463
|
// Continue pipeline after refresh
|
|
414
464
|
return next();
|
|
415
465
|
} catch (e) {
|
|
416
|
-
ctx.error == null || ctx.error("refresh exception",
|
|
466
|
+
ctx.error == null || ctx.error("refresh exception", {
|
|
467
|
+
message: e == null ? void 0 : e.message,
|
|
468
|
+
name: e == null ? void 0 : e.name,
|
|
469
|
+
code: e == null ? void 0 : e.code
|
|
470
|
+
});
|
|
417
471
|
return {
|
|
418
472
|
status: 401,
|
|
419
473
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verify-middleware.js","names":["_constants","require","_jwtDecode","_enums","_cookies","_utils","_tokenMapping","apiURL","process","env","REFRESH_SESSION_URL","verifyMappingCache","createCache","pickCookieDomain","appConfig","origin","requestUrl","undefined","hostCandidate","host","URL","hostname","startsWith","_appConfig$cookie$dom","cookie","domain","local","endsWith","dev","staging","prod","parseCookieHeader","header","out","part","split","k","rest","trim","decodeURIComponent","join","verifyMw","req","ctx","next","_APP_MAP$appId","_p","_ref","_ref$state","_ref2","_tokenMapping$userId$","_tokenMapping$userId","_ref3","_p$sub","_ref4","_p$cfy_bid","_ref5","_p$email","_p$name","_ref6","_p$resource_access$cl","_p$resource_access","_p$realm_access","appId","headers","get","APP_MAP","clientId","status","body","JSON","stringify","reason","expectedClientId","cookies","mapping","base64Decode","dbUrl","getAzureVaultSecretByKey","AZURE_KEY_VAULT_NAME","AzureSecretKeysEnum","DB_CONNECTING_STRING_USER","tokenMappingService","TokenMappingService","tokenMappingRaw","getOrSet","fetched","getTokenMappingById","tokenMapping","parse","at","accessToken","rt","refreshToken","realm","realmId","p","jwtDecode","sid","now","Math","floor","Date","exp","getNewRefreshToken","audOk","Array","isArray","aud","includes","azp","state","tenantId","toString","auth","userId","sub","keycloakUserId","businessId","cfy_bid","email","preferred_username","name","roles","resource_access","realm_access","exports","info","_req$headers$get","_ref7","_ref7$state","_ref8","_updatedMapping$userI","_updatedMapping$userI2","_ref9","_p2$sub","_ref0","_p2$cfy_bid","_ref1","_p2$email","_p2$name","_ref10","_p2$resource_access$c","_p2$resource_access","_p2$realm_access","resp","fetch","method","refresh_token","ok","text","warn","payload","json","data","newAT","access_token","newRT","updatedMapping","updateTokenMapping","expiresAt","expires_in","delete","mappingMaxAge","refresh_expires_in","mappingCookieValue","Buffer","from","mappedDomain","url","setCookieKV","httpOnly","secure","sameSite","maxAge","p2","audOk2","tenantId2","e","error","value","console","log","message"],"sources":["../../../src/middlewares/verify-middleware.ts"],"sourcesContent":["import { IAppId } from \"../types/app\";\nimport { APP_MAP } from \"../constants\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { HttpRequest } from \"@azure/functions\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { setCookieKV } from \"../utils/cookies\";\nimport { IMiddleware } from \"../types/middleware\";\nimport { HttpResponseInit } from \"@azure/functions\";\nimport { createCache, getAzureVaultSecretByKey } from \"../utils\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { TokenMappingService } from \"../service/tokenMapping.service\";\n\nconst apiURL = process.env.REFRESH_SESSION_URL || '';\nconst verifyMappingCache = createCache(\"verify-mw\", 60);\n\nfunction pickCookieDomain(appConfig: (typeof APP_MAP)[IAppId] | undefined, origin?: string, requestUrl?: string): string | undefined {\n if (!appConfig) return undefined;\n const hostCandidate = origin ?? requestUrl;\n if (!hostCandidate) return undefined;\n try {\n const host = new URL(hostCandidate).hostname;\n if (host === \"localhost\" || host.startsWith(\"127.0.0.1\")) {\n return appConfig.cookie.domain.local ?? undefined;\n }\n // culturefy.app domains\n if (host.endsWith(\".dev.culturefy.app\") || host === \"dev.culturefy.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.culturefy.app\") || host === \"staging.culturefy.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".culturefy.app\")) {\n return appConfig.cookie.domain.prod;\n }\n // consultex.app domains\n if (host.endsWith(\".dev.consultex.app\") || host === \"dev.consultex.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.consultex.app\") || host === \"staging.consultex.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".consultex.app\")) {\n return appConfig.cookie.domain.prod;\n }\n } catch {\n return undefined;\n }\n return undefined;\n}\n\nconst parseCookieHeader = (header: string | null | undefined) => {\n const out: Record<string, string> = {};\n if (!header) return out;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (!k) continue;\n out[k] = decodeURIComponent(rest.join(\"=\") || \"\");\n }\n return out;\n};\n\nexport const verifyMw: IMiddleware = async (\n req: HttpRequest,\n ctx: InvocationContext,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> => {\n const appId = req.headers.get(\"app-id\") as IAppId | undefined;\n\n if (!appId || !APP_MAP?.[appId]?.clientId) {\n return {\n status: 400,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"bad_request\", reason: \"invalid_app\" })\n };\n }\n\n const expectedClientId = APP_MAP[appId].clientId;\n\n // cookies\n const cookies = parseCookieHeader(req.headers.get(\"cookie\"));\n\n let mapping: string | null = cookies[`__Secure-session-v1.${appId}.mapping`];\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_token_mapping\" })\n };\n }\n\n mapping = base64Decode(mapping);\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token_mapping\" })\n };\n }\n\n // Get database connection string\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const tokenMappingRaw = await verifyMappingCache.getOrSet(\n ctx,\n [mapping],\n async () => {\n const fetched = await tokenMappingService.getTokenMappingById(mapping);\n return fetched ? JSON.stringify(fetched) : \"\";\n },\n );\n const tokenMapping = tokenMappingRaw ? JSON.parse(tokenMappingRaw) : null;\n\n if (!tokenMapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"token_mapping_not_found\" })\n };\n }\n\n let at = tokenMapping.accessToken;\n let rt = tokenMapping.refreshToken;\n\n if (!at && !rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_tokens\" })\n };\n }\n\n const realm = tokenMapping.realmId;\n const clientId = tokenMapping.clientId;\n\n // decode/verify (lightweight; replace with your verifyJsonWebToken if you have it)\n let p: any;\n try {\n p = jwtDecode(at);\n } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token\" })\n };\n }\n\n if (!p?.sid) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"user_not_found\" })\n };\n }\n\n const now = Math.floor(Date.now() / 1000);\n // Refresh only when expired\n if (typeof p.exp === \"number\" && p.exp <= now) {\n // Delegate to refresh helper; it will handle setting cookies/state or returning an error\n return await getNewRefreshToken(req, ctx, appId, realm, clientId, rt, mapping, p, next);\n }\n\n // audience checks\n const audOk =\n (Array.isArray(p.aud) && p.aud.includes(clientId)) ||\n (typeof p.aud === \"string\" && (p.aud === clientId || p.aud === \"account\")) ||\n p.azp === clientId;\n\n if (!audOk) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n\n // pass data downstream\n (ctx as any).state ??= {};\n const tenantId = realm.toString();\n\n (ctx as any).state.auth = {\n appId,\n userId: tokenMapping.userId?.toString?.() ?? p.sub ?? null,\n keycloakUserId: p.sub ?? tokenMapping.keycloakUserId ?? null,\n businessId: p.cfy_bid ?? tenantId ?? null,\n tenantId,\n email: p.email ?? p.preferred_username ?? null,\n name: p.name ?? undefined,\n roles: p.resource_access?.[clientId]?.roles ?? p.realm_access?.roles ?? [],\n exp: p.exp,\n };\n\n return next();\n};\n\n\n\nasync function getNewRefreshToken(\n req: HttpRequest,\n ctx: InvocationContext,\n appId: IAppId,\n realmId: string,\n clientId: string,\n rt: string | undefined,\n mapping: string,\n p: any,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> {\n // Attempt server-side refresh using RT\n if (!rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"expired_no_rt\" })\n };\n }\n\n ctx.info(\"refreshing token payload ----------------------\", {\n realmId,\n clientId,\n rt\n });\n\n // Call auth service to refresh\n try {\n const resp = await fetch(apiURL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n realmId,\n clientId: clientId,\n refresh_token: rt\n })\n });\n\n if (!resp.ok) {\n const text = await resp.text();\n ctx.warn?.(`refresh call failed: ${resp.status} ${text}`);\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_failed\" })\n };\n }\n\n const payload = await resp.json();\n const data = payload?.data || {};\n\n const newAT = data.access_token as string | undefined;\n const newRT = data.refresh_token as string | undefined;\n\n if (!newAT || !newRT) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_refresh_response\" })\n };\n }\n\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const updatedMapping = await tokenMappingService.updateTokenMapping(mapping, {\n accessToken: newAT as string,\n refreshToken: newRT as string,\n // expires_in is a duration (seconds); store absolute expiry for later checks\n expiresAt: typeof data.expires_in === \"number\" ? new Date(Date.now() + data.expires_in * 1000) : undefined\n });\n\n // Invalidate cache to ensure next request gets fresh tokens\n await verifyMappingCache.delete(ctx, mapping);\n\n // Set refreshed mapping cookie for client session (AT/RT stay server-side in token mapping)\n const mappingMaxAge =\n typeof data.refresh_expires_in === \"number\"\n ? data.refresh_expires_in\n : typeof data.expires_in === \"number\"\n ? data.expires_in\n : 60 * 60 * 24; // fallback 24h\n\n const mappingCookieValue = Buffer.from(mapping).toString(\"base64\");\n const appConfig = APP_MAP[appId];\n const mappedDomain = pickCookieDomain(appConfig, req.headers.get(\"origin\") ?? undefined, req.url);\n \n setCookieKV(ctx, `__Secure-session-v1.${appId}.mapping`, mappingCookieValue, {\n // mapping must be readable by FE in your flow; keep httpOnly default if you prefer server-only\n httpOnly: false,\n secure: true,\n sameSite: \"None\",\n maxAge: mappingMaxAge,\n domain: mappedDomain\n });\n\n // Decode new AT and proceed\n let p2: any;\n try { p2 = jwtDecode(newAT); } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_new_token\" })\n };\n }\n\n const audOk2 =\n (Array.isArray(p2.aud) && p2.aud.includes(clientId)) ||\n (typeof p2.aud === \"string\" && (p2.aud === clientId || p2.aud === \"account\")) ||\n p2.azp === clientId;\n if (!audOk2) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n // Update downstream auth state with refreshed token\n (ctx as any).state ??= {};\n const tenantId2 = realmId.toString();\n (ctx as any).state.auth = {\n appId,\n userId: updatedMapping?.userId?.toString?.() ?? p2.sub ?? null,\n keycloakUserId: p2.sub ?? updatedMapping?.keycloakUserId ?? null,\n businessId: p2.cfy_bid ?? tenantId2 ?? null,\n tenantId: tenantId2,\n email: p2.email ?? p2.preferred_username ?? null,\n name: p2.name ?? undefined,\n roles: p2.resource_access?.[clientId]?.roles ?? p2.realm_access?.roles ?? [],\n exp: p2.exp,\n };\n\n // Continue pipeline after refresh\n return next();\n } catch (e) {\n ctx.error?.(\"refresh exception\", e as any);\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_exception\" })\n };\n }\n}\n\nfunction base64Decode(value: string): string | null {\n try {\n return Buffer.from(value, 'base64').toString();\n } catch (error: any) {\n console.log(\"Error decoding base64: \" + error.message);\n return null;\n }\n}"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"verify-middleware.js","names":["_constants","require","_jwtDecode","_enums","_cookies","_utils","_tokenMapping","apiURL","process","env","REFRESH_SESSION_URL","verifyMappingCache","createCache","pickCookieDomain","appConfig","origin","requestUrl","undefined","hostCandidate","host","URL","hostname","startsWith","_appConfig$cookie$dom","cookie","domain","local","endsWith","dev","staging","prod","parseCookieHeader","header","out","part","split","k","rest","trim","decodeURIComponent","join","isLocalRequest","getSessionMappingCookieName","appId","verifyMw","req","ctx","next","_APP_MAP$appId","_req$headers$get","_p","_ref","_ref$state","_ref2","_tokenMapping$userId$","_tokenMapping$userId","_ref3","_p$sub","_ref4","_p$cfy_bid","_ref5","_p$email","_p$name","_ref6","_p$resource_access$to","_p$resource_access","_p$realm_access","headers","get","APP_MAP","clientId","status","body","JSON","stringify","reason","cookies","requestOrigin","mapping","url","base64Decode","dbUrl","getAzureVaultSecretByKey","AZURE_KEY_VAULT_NAME","AzureSecretKeysEnum","DB_CONNECTING_STRING_USER","tokenMappingService","TokenMappingService","tokenMappingRaw","getOrSet","fetched","getTokenMappingById","tokenMapping","parse","at","accessToken","rt","refreshToken","realm","realmId","tokenClientId","p","jwtDecode","sid","now","Math","floor","Date","exp","getNewRefreshToken","audOk","Array","isArray","aud","includes","azp","state","tenantId","toString","auth","userId","sub","keycloakUserId","businessId","cfy_bid","email","preferred_username","name","roles","resource_access","realm_access","exports","info","_req$headers$get2","_ref7","_ref7$state","_ref8","_updatedMapping$userI","_updatedMapping$userI2","_ref9","_p2$sub","_ref0","_p2$cfy_bid","_ref1","_p2$email","_p2$name","_ref10","_p2$resource_access$c","_p2$resource_access","_p2$realm_access","error","resp","fetch","method","refresh_token","ok","warn","payload","json","data","newAT","access_token","newRT","updatedMapping","updateTokenMapping","expiresAt","expires_in","delete","mappingMaxAge","refresh_expires_in","mappingCookieValue","Buffer","from","mappedDomain","localRequest","setCookieKV","httpOnly","secure","sameSite","maxAge","p2","audOk2","tenantId2","e","message","code","value","console","log"],"sources":["../../../src/middlewares/verify-middleware.ts"],"sourcesContent":["import { IAppId } from \"../types/app\";\nimport { APP_MAP } from \"../constants\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { HttpRequest } from \"@azure/functions\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { setCookieKV } from \"../utils/cookies\";\nimport { IMiddleware } from \"../types/middleware\";\nimport { HttpResponseInit } from \"@azure/functions\";\nimport { createCache, getAzureVaultSecretByKey } from \"../utils\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { TokenMappingService } from \"../service/tokenMapping.service\";\n\nconst apiURL = process.env.REFRESH_SESSION_URL || '';\nconst verifyMappingCache = createCache(\"verify-mw\", 60);\n\nfunction pickCookieDomain(appConfig: (typeof APP_MAP)[IAppId] | undefined, origin?: string, requestUrl?: string): string | undefined {\n if (!appConfig) return undefined;\n const hostCandidate = origin ?? requestUrl;\n if (!hostCandidate) return undefined;\n try {\n const host = new URL(hostCandidate).hostname;\n if (host === \"localhost\" || host.startsWith(\"127.0.0.1\")) {\n return appConfig.cookie.domain.local ?? undefined;\n }\n // culturefy.app domains\n if (host.endsWith(\".dev.culturefy.app\") || host === \"dev.culturefy.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.culturefy.app\") || host === \"staging.culturefy.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".culturefy.app\")) {\n return appConfig.cookie.domain.prod;\n }\n // consultex.app domains\n if (host.endsWith(\".dev.consultex.app\") || host === \"dev.consultex.app\") {\n return appConfig.cookie.domain.dev;\n }\n if (host.endsWith(\".staging.consultex.app\") || host === \"staging.consultex.app\") {\n return appConfig.cookie.domain.staging;\n }\n if (host.endsWith(\".consultex.app\")) {\n return appConfig.cookie.domain.prod;\n }\n } catch {\n return undefined;\n }\n return undefined;\n}\n\nconst parseCookieHeader = (header: string | null | undefined) => {\n const out: Record<string, string> = {};\n if (!header) return out;\n for (const part of header.split(\";\")) {\n const [k, ...rest] = part.trim().split(\"=\");\n if (!k) continue;\n out[k] = decodeURIComponent(rest.join(\"=\") || \"\");\n }\n return out;\n};\n\nfunction isLocalRequest(origin?: string, requestUrl?: string): boolean {\n const hostCandidate = origin ?? requestUrl;\n if (!hostCandidate) return false;\n try {\n const host = new URL(hostCandidate).hostname;\n return host === \"localhost\" || host.startsWith(\"127.0.0.1\");\n } catch {\n return false;\n }\n}\n\nfunction getSessionMappingCookieName(appId: IAppId, origin?: string, requestUrl?: string): string {\n if (isLocalRequest(origin, requestUrl)) {\n return `session-v1.${appId}.mapping`;\n }\n return `__Secure-session-v1.${appId}.mapping`;\n}\n\nexport const verifyMw: IMiddleware = async (\n req: HttpRequest,\n ctx: InvocationContext,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> => {\n const appId = req.headers.get(\"app-id\") as IAppId | undefined;\n\n if (!appId || !APP_MAP?.[appId]?.clientId) {\n return {\n status: 400,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"bad_request\", reason: \"invalid_app\" })\n };\n }\n\n const clientId = APP_MAP[appId].clientId;\n\n // cookies\n const cookies = parseCookieHeader(req.headers.get(\"cookie\"));\n const requestOrigin = req.headers.get(\"origin\") ?? undefined;\n\n let mapping: string | null =\n cookies[getSessionMappingCookieName(appId, requestOrigin, req.url)] ||\n cookies[`__Secure-session-v1.${appId}.mapping`] ||\n cookies[`session-v1.${appId}.mapping`] ||\n req.headers.get(\"x-session-mapping\") ||\n req.headers.get(\"x-token-mapping\");\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_token_mapping\" })\n };\n }\n\n mapping = base64Decode(mapping);\n\n if (!mapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token_mapping\" })\n };\n }\n\n // Get database connection string\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const tokenMappingRaw = await verifyMappingCache.getOrSet(\n ctx,\n [mapping],\n async () => {\n const fetched = await tokenMappingService.getTokenMappingById(mapping);\n return fetched ? JSON.stringify(fetched) : \"\";\n },\n );\n const tokenMapping = tokenMappingRaw ? JSON.parse(tokenMappingRaw) : null;\n\n if (!tokenMapping) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"token_mapping_not_found\" })\n };\n }\n\n let at = tokenMapping.accessToken;\n let rt = tokenMapping.refreshToken;\n\n if (!at && !rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"no_tokens\" })\n };\n }\n\n const realm = tokenMapping.realmId;\n const tokenClientId = tokenMapping.clientId;\n\n if (!tokenClientId || tokenClientId !== clientId) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"client_mismatch\" })\n };\n }\n\n // decode/verify (lightweight; replace with your verifyJsonWebToken if you have it)\n let p: any;\n try {\n p = jwtDecode(at);\n } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_token\" })\n };\n }\n\n if (!p?.sid) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"user_not_found\" })\n };\n }\n\n const now = Math.floor(Date.now() / 1000);\n // Refresh only when expired\n if (typeof p.exp === \"number\" && p.exp <= now) {\n // Delegate to refresh helper; it will handle setting cookies/state or returning an error\n return await getNewRefreshToken(req, ctx, appId, realm, tokenClientId, rt, mapping, p, next);\n }\n\n // audience checks\n const audOk =\n (Array.isArray(p.aud) && p.aud.includes(tokenClientId)) ||\n (typeof p.aud === \"string\" && (p.aud === tokenClientId || p.aud === \"account\")) ||\n p.azp === tokenClientId;\n\n if (!audOk) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n\n // pass data downstream\n (ctx as any).state ??= {};\n const tenantId = realm.toString();\n\n (ctx as any).state.auth = {\n appId,\n userId: tokenMapping.userId?.toString?.() ?? p.sub ?? null,\n keycloakUserId: p.sub ?? tokenMapping.keycloakUserId ?? null,\n businessId: p.cfy_bid ?? tenantId ?? null,\n tenantId,\n email: p.email ?? p.preferred_username ?? null,\n name: p.name ?? undefined,\n roles: p.resource_access?.[tokenClientId]?.roles ?? p.realm_access?.roles ?? [],\n exp: p.exp,\n };\n\n return next();\n};\n\n\n\nasync function getNewRefreshToken(\n req: HttpRequest,\n ctx: InvocationContext,\n appId: IAppId,\n realmId: string,\n clientId: string,\n rt: string | undefined,\n mapping: string,\n p: any,\n next: () => Promise<HttpResponseInit>\n): Promise<HttpResponseInit> {\n // Attempt server-side refresh using RT\n if (!rt) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"expired_no_rt\" })\n };\n }\n\n ctx.info(\"Refreshing session token\", {\n realmId,\n clientId,\n });\n\n // Call auth service to refresh\n try {\n if (!apiURL) {\n ctx.error?.(\"Refresh session URL is not configured\");\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_not_configured\" })\n };\n }\n const requestOrigin = req.headers.get(\"origin\") ?? undefined;\n const resp = await fetch(apiURL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n realmId,\n clientId: clientId,\n refresh_token: rt\n })\n });\n\n if (!resp.ok) {\n ctx.warn?.(`refresh call failed with status ${resp.status}`);\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_failed\" })\n };\n }\n\n const payload = await resp.json();\n const data = payload?.data || {};\n\n const newAT = data.access_token as string | undefined;\n const newRT = data.refresh_token as string | undefined;\n\n if (!newAT || !newRT) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_refresh_response\" })\n };\n }\n\n const dbUrl = await getAzureVaultSecretByKey(\n ctx,\n process.env.AZURE_KEY_VAULT_NAME || \"\",\n AzureSecretKeysEnum.DB_CONNECTING_STRING_USER\n );\n\n if (!dbUrl) {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"database_connection_string_not_found\" })\n };\n }\n\n const tokenMappingService = new TokenMappingService(ctx, dbUrl);\n\n const updatedMapping = await tokenMappingService.updateTokenMapping(mapping, {\n accessToken: newAT,\n refreshToken: newRT as string,\n // expires_in is a duration (seconds); store absolute expiry for later checks\n expiresAt: typeof data.expires_in === \"number\" ? new Date(Date.now() + data.expires_in * 1000) : undefined\n });\n\n // Invalidate cache to ensure next request gets fresh tokens\n await verifyMappingCache.delete(ctx, mapping);\n\n // Set refreshed mapping cookie for client session (AT/RT stay server-side in token mapping)\n const mappingMaxAge =\n typeof data.refresh_expires_in === \"number\"\n ? data.refresh_expires_in\n : typeof data.expires_in === \"number\"\n ? data.expires_in\n : 60 * 60 * 24; // fallback 24h\n\n const mappingCookieValue = Buffer.from(mapping).toString(\"base64\");\n const appConfig = APP_MAP[appId];\n\n // 5\n const mappedDomain = pickCookieDomain(appConfig, requestOrigin, req.url);\n const localRequest = isLocalRequest(requestOrigin, req.url);\n\n setCookieKV(ctx, getSessionMappingCookieName(appId, requestOrigin, req.url), mappingCookieValue, {\n // mapping must be readable by FE in your flow; keep httpOnly default if you prefer server-only\n httpOnly: false,\n secure: !localRequest,\n sameSite: localRequest ? \"Lax\" : \"None\",\n maxAge: mappingMaxAge,\n domain: mappedDomain\n });\n\n // Decode new AT and proceed\n let p2: any;\n try { p2 = jwtDecode(newAT); } catch {\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"invalid_new_token\" })\n };\n }\n\n const audOk2 =\n (Array.isArray(p2.aud) && p2.aud.includes(clientId)) ||\n (typeof p2.aud === \"string\" && (p2.aud === clientId || p2.aud === \"account\")) ||\n p2.azp === clientId;\n if (!audOk2) {\n return {\n status: 403,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"forbidden\", reason: \"audience_mismatch\" })\n };\n }\n\n // Update downstream auth state with refreshed token\n (ctx as any).state ??= {};\n const tenantId2 = realmId.toString();\n (ctx as any).state.auth = {\n appId,\n userId: updatedMapping?.userId?.toString?.() ?? p2.sub ?? null,\n keycloakUserId: p2.sub ?? updatedMapping?.keycloakUserId ?? null,\n businessId: p2.cfy_bid ?? tenantId2 ?? null,\n tenantId: tenantId2,\n email: p2.email ?? p2.preferred_username ?? null,\n name: p2.name ?? undefined,\n roles: p2.resource_access?.[clientId]?.roles ?? p2.realm_access?.roles ?? [],\n exp: p2.exp,\n };\n\n // Continue pipeline after refresh\n return next();\n } catch (e: any) {\n ctx.error?.(\"refresh exception\", {\n message: e?.message,\n name: e?.name,\n code: e?.code,\n });\n return {\n status: 401,\n headers: { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store, no-cache, must-revalidate\", \"Pragma\": \"no-cache\", \"Vary\": \"Origin\" },\n body: JSON.stringify({ status: \"unauthenticated\", reason: \"refresh_exception\" })\n };\n }\n}\n\nfunction base64Decode(value: string): string | null {\n try {\n return Buffer.from(value, 'base64').toString();\n } catch (error: any) {\n console.log(\"Error decoding base64: \" + error.message);\n return null;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -5,8 +5,6 @@ exports.TenantModelRepository = exports.MultiTenantRepository = void 0;
|
|
|
5
5
|
exports.WithTenantDb = WithTenantDb;
|
|
6
6
|
var _mongoose = _interopRequireWildcard(require("mongoose"));
|
|
7
7
|
var crypto = _interopRequireWildcard(require("crypto"));
|
|
8
|
-
var _identity = require("@azure/identity");
|
|
9
|
-
var _keyvaultSecrets = require("@azure/keyvault-secrets");
|
|
10
8
|
var _enums = require("../enums");
|
|
11
9
|
var _cache = require("../utils/cache");
|
|
12
10
|
var _secrets = require("../utils/secrets");
|
|
@@ -57,11 +55,22 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
57
55
|
this.serviceDBType = serviceDBType != null ? serviceDBType : "main";
|
|
58
56
|
this.tenantBridgeConfig = {
|
|
59
57
|
tenantBridgeEnvKey: "TENANT_BRIDGE_DB_URI",
|
|
60
|
-
tenantBridgeSecretKey: _enums.AzureSecretKeysEnum.
|
|
58
|
+
tenantBridgeSecretKey: _enums.AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE,
|
|
61
59
|
...config
|
|
62
60
|
};
|
|
63
61
|
this.connectionPromise = this.ensureClientConnection();
|
|
64
62
|
}
|
|
63
|
+
getConnectionLogLabel(connectionString) {
|
|
64
|
+
const match = connectionString.match(/\/([^/?]+)(\?|$)/);
|
|
65
|
+
const dbName = (match == null ? void 0 : match[1]) || "unknown";
|
|
66
|
+
if (dbName.toLowerCase().includes("tenantbridge")) {
|
|
67
|
+
return "TenantBridge-DB";
|
|
68
|
+
}
|
|
69
|
+
if (dbName.toLowerCase().includes("user")) {
|
|
70
|
+
return "Auth-DB";
|
|
71
|
+
}
|
|
72
|
+
return `${dbName}-DB`;
|
|
73
|
+
}
|
|
65
74
|
getEncryptionIv() {
|
|
66
75
|
const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;
|
|
67
76
|
if (!iv) {
|
|
@@ -82,6 +91,7 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
82
91
|
if (hexValue.length === 16) {
|
|
83
92
|
return hexValue;
|
|
84
93
|
}
|
|
94
|
+
this.context.error(`${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`);
|
|
85
95
|
throw new Error(`${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`);
|
|
86
96
|
}
|
|
87
97
|
async getOrCreateCachedConnection(connectionString) {
|
|
@@ -89,7 +99,8 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
89
99
|
if (existing && existing.connection.readyState === 1) {
|
|
90
100
|
return existing;
|
|
91
101
|
}
|
|
92
|
-
this.
|
|
102
|
+
const dbLabel = this.getConnectionLogLabel(connectionString);
|
|
103
|
+
this.context.info(`Initializing database connection (${dbLabel})...`);
|
|
93
104
|
const instance = new _mongoose.default.Mongoose();
|
|
94
105
|
try {
|
|
95
106
|
await instance.connect(connectionString, {
|
|
@@ -97,11 +108,11 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
97
108
|
connectTimeoutMS: 10000,
|
|
98
109
|
socketTimeoutMS: 45000
|
|
99
110
|
});
|
|
100
|
-
this.context.info(`✅ MongoDB connected successfully ${
|
|
111
|
+
this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);
|
|
101
112
|
MultiTenantRepository.connections.set(connectionString, instance);
|
|
102
113
|
return instance;
|
|
103
114
|
} catch (err) {
|
|
104
|
-
this.context.error(`❌ MongoDB connection error for ${
|
|
115
|
+
this.context.error(`❌ MongoDB connection error for (${dbLabel})`, {
|
|
105
116
|
message: err.message,
|
|
106
117
|
name: err.name,
|
|
107
118
|
code: err.code,
|
|
@@ -123,7 +134,7 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
123
134
|
return localUri;
|
|
124
135
|
}
|
|
125
136
|
const vault = process.env.AZURE_KEY_VAULT_NAME || "";
|
|
126
|
-
const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || _enums.AzureSecretKeysEnum.
|
|
137
|
+
const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || _enums.AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE;
|
|
127
138
|
const dbUrl = await (0, _secrets.getAzureVaultSecretByKey)(this.context, vault, secretKey);
|
|
128
139
|
if (!dbUrl) {
|
|
129
140
|
throw new Error("TenantBridge database connection string not found");
|
|
@@ -131,37 +142,72 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
131
142
|
return dbUrl;
|
|
132
143
|
}
|
|
133
144
|
async getDbConnectionEncryptionKey() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
try {
|
|
146
|
+
if (this.dbConnectionEncryptionKey) {
|
|
147
|
+
return this.dbConnectionEncryptionKey;
|
|
148
|
+
}
|
|
149
|
+
const envKey = process.env.DB_CONNECTION_STRING_ENCRYPTION_KEY;
|
|
150
|
+
if (envKey) {
|
|
151
|
+
this.dbConnectionEncryptionKey = envKey;
|
|
152
|
+
return envKey;
|
|
153
|
+
}
|
|
154
|
+
const vault = process.env.AZURE_KEY_VAULT_NAME || "";
|
|
155
|
+
const key = await (0, _secrets.getAzureVaultSecretByKey)(this.context, vault, _enums.AzureSecretKeysEnum.DB_CONNECTION_STRING_ENCRYPTION_KEY);
|
|
156
|
+
if (!key) {
|
|
157
|
+
this.context.error("DB connection string encryption key not found in vault");
|
|
158
|
+
throw new Error("DB connection string encryption key not found in vault");
|
|
159
|
+
}
|
|
160
|
+
this.dbConnectionEncryptionKey = key;
|
|
161
|
+
return key;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
this.context.error(`Error getting DB connection string encryption key from vault: ${error}`);
|
|
164
|
+
throw new Error(`Error getting DB connection string encryption key from vault: ${error}`);
|
|
137
165
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
166
|
+
}
|
|
167
|
+
async decryptConnectionString(encryptedValue) {
|
|
168
|
+
if (!encryptedValue) {
|
|
169
|
+
this.context.error("Encrypted value not found");
|
|
170
|
+
throw new Error("Encrypted value not found");
|
|
142
171
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
throw new Error("AZURE_KEY_VAULT_NAME is required to fetch encryption key");
|
|
172
|
+
if (encryptedValue.startsWith("mongodb://")) {
|
|
173
|
+
return encryptedValue;
|
|
146
174
|
}
|
|
147
|
-
const
|
|
148
|
-
const credential = new _identity.DefaultAzureCredential();
|
|
149
|
-
const client = new _keyvaultSecrets.SecretClient(vaultUrl, credential);
|
|
150
|
-
const secret = await client.getSecret("DB-CONNECTION-STRING-ENCRYPTION-KEY");
|
|
151
|
-
const key = (_secret$value = secret.value) != null ? _secret$value : "";
|
|
175
|
+
const key = await this.getDbConnectionEncryptionKey();
|
|
152
176
|
if (!key) {
|
|
153
|
-
|
|
177
|
+
this.context.error("DB connection string encryption key not found during decryption");
|
|
178
|
+
throw new Error("DB connection string encryption key not found during decryption");
|
|
154
179
|
}
|
|
155
|
-
this.
|
|
156
|
-
return key;
|
|
157
|
-
}
|
|
158
|
-
async decryptConnectionString(encryptedValue) {
|
|
159
|
-
const key = await this.getDbConnectionEncryptionKey();
|
|
180
|
+
this.context.info(`Decrypting DB connection string with key: ${key}`);
|
|
160
181
|
const keyBuffer = this.normalizeEncryptionKey(key);
|
|
182
|
+
if (!keyBuffer) {
|
|
183
|
+
this.context.error("Key buffer not found");
|
|
184
|
+
throw new Error("Key buffer not found");
|
|
185
|
+
}
|
|
186
|
+
this.context.info(`Decrypting DB connection string with key buffer: ${keyBuffer}`);
|
|
161
187
|
const ivBuffer = this.getEncryptionIv();
|
|
188
|
+
if (!ivBuffer) {
|
|
189
|
+
this.context.error("IV buffer not found");
|
|
190
|
+
throw new Error("IV buffer not found");
|
|
191
|
+
}
|
|
192
|
+
this.context.info(`Decrypting DB connection string with IV buffer: ${ivBuffer}`);
|
|
162
193
|
const decipher = crypto.createDecipheriv("aes-128-cbc", keyBuffer, ivBuffer);
|
|
194
|
+
if (!decipher) {
|
|
195
|
+
this.context.error("Decipher not found");
|
|
196
|
+
throw new Error("Decipher not found");
|
|
197
|
+
}
|
|
198
|
+
this.context.info(`Decrypting DB connection string with decipher: ${decipher}`);
|
|
163
199
|
let decrypted = decipher.update(encryptedValue, "base64", "utf8");
|
|
200
|
+
if (!decrypted) {
|
|
201
|
+
this.context.error("Decrypted value not found");
|
|
202
|
+
throw new Error("Decrypted value not found");
|
|
203
|
+
}
|
|
204
|
+
this.context.info(`Decrypting DB connection string with decrypted value: ${decrypted}`);
|
|
164
205
|
decrypted += decipher.final("utf8");
|
|
206
|
+
if (!decrypted) {
|
|
207
|
+
this.context.error("Decrypted value not found");
|
|
208
|
+
throw new Error("Decrypted value not found");
|
|
209
|
+
}
|
|
210
|
+
this.context.info(`Decrypting DB connection string with decrypted value: ${decrypted}`);
|
|
165
211
|
return decrypted;
|
|
166
212
|
}
|
|
167
213
|
normalizeEncryptionKey(key) {
|
|
@@ -177,9 +223,13 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
177
223
|
if (hexKey.length === 16) {
|
|
178
224
|
return hexKey;
|
|
179
225
|
}
|
|
226
|
+
this.context.error(`DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`);
|
|
180
227
|
throw new Error(`DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`);
|
|
181
228
|
}
|
|
182
229
|
async getClientDbConnectionString(businessId, appId, serviceDBType) {
|
|
230
|
+
if (!appId) {
|
|
231
|
+
throw new Error("appId is required to resolve tenant client database");
|
|
232
|
+
}
|
|
183
233
|
const resolvedServiceDbType = serviceDBType != null ? serviceDBType : "main";
|
|
184
234
|
const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();
|
|
185
235
|
const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);
|
|
@@ -187,16 +237,14 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
187
237
|
const filter = {
|
|
188
238
|
businessId: this.toObjectId(businessId, "businessId")
|
|
189
239
|
};
|
|
190
|
-
|
|
191
|
-
filter.appId = appId;
|
|
192
|
-
}
|
|
240
|
+
filter.appId = appId;
|
|
193
241
|
filter.serviceDBType = resolvedServiceDbType;
|
|
194
242
|
const configMapping = await ConfigMapping.findOne(filter).lean().exec();
|
|
195
243
|
if (!(configMapping != null && configMapping.connectionString)) {
|
|
196
244
|
throw new Error("Config mapping not found for this business");
|
|
197
245
|
}
|
|
198
246
|
const decryptedConnectionString = await this.decryptConnectionString(configMapping.connectionString);
|
|
199
|
-
this.context.info(
|
|
247
|
+
this.context.info("Resolved tenant database mapping from TenantBridge");
|
|
200
248
|
return decryptedConnectionString;
|
|
201
249
|
}
|
|
202
250
|
getConnection() {
|
|
@@ -223,9 +271,9 @@ let MultiTenantRepository = exports.MultiTenantRepository = (_dec = (0, _cache.C
|
|
|
223
271
|
if (!existing) return;
|
|
224
272
|
try {
|
|
225
273
|
await existing.disconnect();
|
|
226
|
-
this.context.info(`✅ Disconnected from database
|
|
274
|
+
this.context.info(`✅ Disconnected from database (${this.getConnectionLogLabel(connectionString)})`);
|
|
227
275
|
} catch (error) {
|
|
228
|
-
this.context.error(`❌ Error disconnecting from database
|
|
276
|
+
this.context.error(`❌ Error disconnecting from database (${this.getConnectionLogLabel(connectionString)})`, error);
|
|
229
277
|
} finally {
|
|
230
278
|
MultiTenantRepository.connections.delete(connectionString);
|
|
231
279
|
}
|