@adatechnology/auth-keycloak 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
8
  var __commonJS = (cb, mod) => function __require() {
8
9
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
10
  };
@@ -28,21 +29,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
29
  mod
29
30
  ));
30
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
- var __decorateClass = (decorators, target, key, kind) => {
32
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
33
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
34
- if (decorator = decorators[i])
35
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
36
- if (kind && result) __defProp(target, key, result);
37
- return result;
38
- };
39
- var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
40
32
 
41
33
  // ../shared/dist/types.js
42
34
  var require_types = __commonJS({
43
35
  "../shared/dist/types.js"(exports2) {
44
36
  "use strict";
45
- Object.defineProperty(exports2, "__esModule", { value: true });
37
+ Object.defineProperty(exports2, "__esModule", {
38
+ value: true
39
+ });
46
40
  }
47
41
  });
48
42
 
@@ -50,15 +44,19 @@ var require_types = __commonJS({
50
44
  var require_utils = __commonJS({
51
45
  "../shared/dist/utils.js"(exports2) {
52
46
  "use strict";
53
- Object.defineProperty(exports2, "__esModule", { value: true });
47
+ Object.defineProperty(exports2, "__esModule", {
48
+ value: true
49
+ });
54
50
  exports2.noop = noop;
55
51
  exports2.prefixWith = prefixWith;
56
52
  function noop() {
57
53
  return void 0;
58
54
  }
55
+ __name(noop, "noop");
59
56
  function prefixWith(prefix, value) {
60
57
  return `${prefix}-${value}`;
61
58
  }
59
+ __name(prefixWith, "prefixWith");
62
60
  }
63
61
  });
64
62
 
@@ -66,23 +64,26 @@ var require_utils = __commonJS({
66
64
  var require_base_app_error = __commonJS({
67
65
  "../shared/dist/errors/base-app-error.js"(exports2) {
68
66
  "use strict";
69
- Object.defineProperty(exports2, "__esModule", { value: true });
67
+ Object.defineProperty(exports2, "__esModule", {
68
+ value: true
69
+ });
70
70
  exports2.BaseAppError = void 0;
71
- var BaseAppError5 = class extends Error {
71
+ var _a;
72
+ var BaseAppError5 = (_a = class extends Error {
72
73
  code;
73
74
  status;
74
75
  context;
75
76
  constructor(params) {
76
- var _a;
77
+ var _a2;
77
78
  super(params.message);
78
79
  this.name = new.target.name;
79
80
  this.status = params.status;
80
81
  this.code = params.code;
81
82
  this.context = params.context;
82
83
  const capturable = Error;
83
- (_a = capturable.captureStackTrace) == null ? void 0 : _a.call(capturable, this, this.constructor);
84
+ (_a2 = capturable.captureStackTrace) == null ? void 0 : _a2.call(capturable, this, this.constructor);
84
85
  }
85
- };
86
+ }, __name(_a, "BaseAppError"), _a);
86
87
  exports2.BaseAppError = BaseAppError5;
87
88
  }
88
89
  });
@@ -91,7 +92,9 @@ var require_base_app_error = __commonJS({
91
92
  var require_errors_constants = __commonJS({
92
93
  "../shared/dist/errors/errors.constants.js"(exports2) {
93
94
  "use strict";
94
- Object.defineProperty(exports2, "__esModule", { value: true });
95
+ Object.defineProperty(exports2, "__esModule", {
96
+ value: true
97
+ });
95
98
  exports2.SHARED_INTERNAL_FRAME_RE = exports2.SHARED_ERROR_MESSAGES = exports2.SHARED_ERRORS = void 0;
96
99
  exports2.SHARED_ERRORS = {
97
100
  DEFAULT_STATUS: 502,
@@ -117,19 +120,21 @@ var require_error_mapper_service = __commonJS({
117
120
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
118
121
  return c > 3 && r && Object.defineProperty(target, key, r), r;
119
122
  };
120
- Object.defineProperty(exports2, "__esModule", { value: true });
123
+ Object.defineProperty(exports2, "__esModule", {
124
+ value: true
125
+ });
121
126
  exports2.ErrorMapperService = void 0;
122
127
  var common_1 = require("@nestjs/common");
123
128
  var base_app_error_1 = require_base_app_error();
124
129
  var errors_constants_1 = require_errors_constants();
125
- var ErrorMapperService = class ErrorMapperService {
130
+ var _a;
131
+ var ErrorMapperService = (_a = class {
126
132
  /**
127
133
  * Map an upstream/internal error to a BaseAppError with normalized fields.
128
134
  * Keeps a small context to help tracing origin without leaking secrets.
129
135
  */
130
136
  mapUpstreamError(err) {
131
- if (err instanceof base_app_error_1.BaseAppError)
132
- return err;
137
+ if (err instanceof base_app_error_1.BaseAppError) return err;
133
138
  try {
134
139
  const obj = err ?? void 0;
135
140
  const context = {};
@@ -138,8 +143,7 @@ var require_error_mapper_service = __commonJS({
138
143
  if (frames.length) {
139
144
  context.stack = frames;
140
145
  const origin = frames.find((f) => !this.isInternalFrame(f.file));
141
- if (origin)
142
- context.origin = origin;
146
+ if (origin) context.origin = origin;
143
147
  }
144
148
  }
145
149
  if (obj && typeof obj.config === "object" && obj.config !== null) {
@@ -179,7 +183,9 @@ var require_error_mapper_service = __commonJS({
179
183
  return new base_app_error_1.BaseAppError({
180
184
  message: errors_constants_1.SHARED_ERROR_MESSAGES.MAPPING_FAILURE,
181
185
  status: errors_constants_1.SHARED_ERRORS.INTERNAL_STATUS,
182
- context: { original: String(err) }
186
+ context: {
187
+ original: String(err)
188
+ }
183
189
  });
184
190
  }
185
191
  }
@@ -194,17 +200,21 @@ var require_error_mapper_service = __commonJS({
194
200
  const file = m[2];
195
201
  const lineNum = parseInt(m[3], 10);
196
202
  const colNum = parseInt(m[4], 10);
197
- frames.push({ fn, file, line: lineNum, column: colNum });
203
+ frames.push({
204
+ fn,
205
+ file,
206
+ line: lineNum,
207
+ column: colNum
208
+ });
198
209
  }
199
210
  }
200
211
  return frames;
201
212
  }
202
213
  isInternalFrame(file) {
203
- if (!file)
204
- return false;
214
+ if (!file) return false;
205
215
  return errors_constants_1.SHARED_INTERNAL_FRAME_RE.test(file);
206
216
  }
207
- };
217
+ }, __name(_a, "ErrorMapperService"), _a);
208
218
  exports2.ErrorMapperService = ErrorMapperService;
209
219
  exports2.ErrorMapperService = ErrorMapperService = __decorate([
210
220
  (0, common_1.Injectable)()
@@ -216,23 +226,28 @@ var require_error_mapper_service = __commonJS({
216
226
  var require_errors = __commonJS({
217
227
  "../shared/dist/errors/index.js"(exports2) {
218
228
  "use strict";
219
- var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
229
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
220
230
  if (k2 === void 0) k2 = k;
221
231
  var desc = Object.getOwnPropertyDescriptor(m, k);
222
232
  if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
223
- desc = { enumerable: true, get: function() {
224
- return m[k];
225
- } };
233
+ desc = {
234
+ enumerable: true,
235
+ get: /* @__PURE__ */ __name(function() {
236
+ return m[k];
237
+ }, "get")
238
+ };
226
239
  }
227
240
  Object.defineProperty(o, k2, desc);
228
- }) : (function(o, m, k, k2) {
241
+ } : function(o, m, k, k2) {
229
242
  if (k2 === void 0) k2 = k;
230
243
  o[k2] = m[k];
231
- }));
232
- var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
233
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
244
+ });
245
+ var __exportStar = exports2 && exports2.__exportStar || function(m, exports1) {
246
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports1, p)) __createBinding(exports1, m, p);
234
247
  };
235
- Object.defineProperty(exports2, "__esModule", { value: true });
248
+ Object.defineProperty(exports2, "__esModule", {
249
+ value: true
250
+ });
236
251
  __exportStar(require_base_app_error(), exports2);
237
252
  __exportStar(require_error_mapper_service(), exports2);
238
253
  }
@@ -242,23 +257,28 @@ var require_errors = __commonJS({
242
257
  var require_dist = __commonJS({
243
258
  "../shared/dist/index.js"(exports2) {
244
259
  "use strict";
245
- var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
260
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
246
261
  if (k2 === void 0) k2 = k;
247
262
  var desc = Object.getOwnPropertyDescriptor(m, k);
248
263
  if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
249
- desc = { enumerable: true, get: function() {
250
- return m[k];
251
- } };
264
+ desc = {
265
+ enumerable: true,
266
+ get: /* @__PURE__ */ __name(function() {
267
+ return m[k];
268
+ }, "get")
269
+ };
252
270
  }
253
271
  Object.defineProperty(o, k2, desc);
254
- }) : (function(o, m, k, k2) {
272
+ } : function(o, m, k, k2) {
255
273
  if (k2 === void 0) k2 = k;
256
274
  o[k2] = m[k];
257
- }));
258
- var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
259
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
275
+ });
276
+ var __exportStar = exports2 && exports2.__exportStar || function(m, exports1) {
277
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports1, p)) __createBinding(exports1, m, p);
260
278
  };
261
- Object.defineProperty(exports2, "__esModule", { value: true });
279
+ Object.defineProperty(exports2, "__esModule", {
280
+ value: true
281
+ });
262
282
  __exportStar(require_types(), exports2);
263
283
  __exportStar(require_utils(), exports2);
264
284
  __exportStar(require_errors(), exports2);
@@ -268,11 +288,15 @@ var require_dist = __commonJS({
268
288
  // src/index.ts
269
289
  var index_exports = {};
270
290
  __export(index_exports, {
291
+ AccessToken: () => AccessToken,
271
292
  ApiAuthGuard: () => ApiAuthGuard,
272
293
  AuthUser: () => AuthUser,
273
294
  B2BGuard: () => B2BGuard,
295
+ B2BRoles: () => B2BRoles,
274
296
  B2CGuard: () => B2CGuard,
297
+ B2CRoles: () => B2CRoles,
275
298
  BearerTokenGuard: () => BearerTokenGuard,
299
+ CallerToken: () => CallerToken,
276
300
  KEYCLOAK_CLIENT: () => KEYCLOAK_CLIENT,
277
301
  KEYCLOAK_CONFIG: () => KEYCLOAK_CONFIG,
278
302
  KEYCLOAK_HTTP_INTERCEPTOR: () => KEYCLOAK_HTTP_INTERCEPTOR,
@@ -280,17 +304,25 @@ __export(index_exports, {
280
304
  KeycloakError: () => KeycloakError,
281
305
  KeycloakModule: () => KeycloakModule,
282
306
  Roles: () => Roles,
283
- RolesGuard: () => RolesGuard
307
+ RolesGuard: () => RolesGuard,
308
+ TokenRoles: () => TokenRoles
284
309
  });
285
310
  module.exports = __toCommonJS(index_exports);
286
311
 
287
312
  // src/keycloak.module.ts
288
- var import_common6 = require("@nestjs/common");
313
+ var import_common9 = require("@nestjs/common");
289
314
  var import_core2 = require("@nestjs/core");
290
315
  var import_http_client3 = require("@adatechnology/http-client");
291
316
  var import_logger3 = require("@adatechnology/logger");
292
317
  var import_cache3 = require("@adatechnology/cache");
293
318
 
319
+ // src/api-auth.guard.ts
320
+ var import_common4 = require("@nestjs/common");
321
+ var import_shared3 = __toESM(require_dist());
322
+
323
+ // src/b2b.guard.ts
324
+ var import_common2 = require("@nestjs/common");
325
+
294
326
  // src/bearer-token.guard.ts
295
327
  var import_common = require("@nestjs/common");
296
328
  var import_logger = require("@adatechnology/logger");
@@ -306,7 +338,7 @@ var KEYCLOAK_PROVIDER = "KEYCLOAK_PROVIDER";
306
338
  // package.json
307
339
  var package_default = {
308
340
  name: "@adatechnology/auth-keycloak",
309
- version: "0.1.1",
341
+ version: "0.1.3",
310
342
  publishConfig: {
311
343
  access: "public"
312
344
  },
@@ -334,6 +366,7 @@ var package_default = {
334
366
  devDependencies: {
335
367
  "@adatechnology/shared": "workspace:*",
336
368
  "@esbuild-plugins/tsconfig-paths": "^0.1.2",
369
+ "@swc/core": "^1.15.24",
337
370
  tsup: "^8.5.1",
338
371
  typescript: "^5.2.0"
339
372
  }
@@ -363,7 +396,26 @@ var ROLES_ERROR_CODE = {
363
396
  };
364
397
 
365
398
  // src/bearer-token.guard.ts
366
- var BearerTokenGuard = class {
399
+ function _ts_decorate(decorators, target, key, desc) {
400
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
401
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
402
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
403
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
404
+ }
405
+ __name(_ts_decorate, "_ts_decorate");
406
+ function _ts_metadata(k, v) {
407
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
408
+ }
409
+ __name(_ts_metadata, "_ts_metadata");
410
+ function _ts_param(paramIndex, decorator) {
411
+ return function(target, key) {
412
+ decorator(target, key, paramIndex);
413
+ };
414
+ }
415
+ __name(_ts_param, "_ts_param");
416
+ var _BearerTokenGuard = class _BearerTokenGuard {
417
+ keycloakClient;
418
+ logger;
367
419
  constructor(keycloakClient, logger) {
368
420
  this.keycloakClient = keycloakClient;
369
421
  this.logger = logger;
@@ -420,12 +472,16 @@ var BearerTokenGuard = class {
420
472
  isValid = await this.keycloakClient.validateToken(token);
421
473
  } catch (err) {
422
474
  const detail = err instanceof Error ? err.message : String(err);
423
- this.log("error", `${method} - Token validation failed`, method, { detail });
475
+ this.log("error", `${method} - Token validation failed`, method, {
476
+ detail
477
+ });
424
478
  throw new import_shared.BaseAppError({
425
479
  message: "Token validation failed",
426
480
  status: HTTP_STATUS.UNAUTHORIZED,
427
481
  code: BEARER_ERROR_CODE.TOKEN_VALIDATION_FAILED,
428
- context: { detail }
482
+ context: {
483
+ detail
484
+ }
429
485
  });
430
486
  }
431
487
  if (!isValid) {
@@ -441,23 +497,199 @@ var BearerTokenGuard = class {
441
497
  return true;
442
498
  }
443
499
  };
444
- BearerTokenGuard = __decorateClass([
500
+ __name(_BearerTokenGuard, "BearerTokenGuard");
501
+ var BearerTokenGuard = _BearerTokenGuard;
502
+ BearerTokenGuard = _ts_decorate([
445
503
  (0, import_common.Injectable)(),
446
- __decorateParam(0, (0, import_common.Optional)()),
447
- __decorateParam(0, (0, import_common.Inject)(KEYCLOAK_CLIENT)),
448
- __decorateParam(1, (0, import_common.Optional)()),
449
- __decorateParam(1, (0, import_common.Inject)(import_logger.LOGGER_PROVIDER))
504
+ _ts_param(0, (0, import_common.Optional)()),
505
+ _ts_param(0, (0, import_common.Inject)(KEYCLOAK_CLIENT)),
506
+ _ts_param(1, (0, import_common.Optional)()),
507
+ _ts_param(1, (0, import_common.Inject)(import_logger.LOGGER_PROVIDER)),
508
+ _ts_metadata("design:type", Function),
509
+ _ts_metadata("design:paramtypes", [
510
+ typeof KeycloakClientInterface === "undefined" ? Object : KeycloakClientInterface,
511
+ typeof LoggerProviderInterface === "undefined" ? Object : LoggerProviderInterface
512
+ ])
450
513
  ], BearerTokenGuard);
451
514
 
515
+ // src/b2b.guard.ts
516
+ function _ts_decorate2(decorators, target, key, desc) {
517
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
518
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
519
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
520
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
521
+ }
522
+ __name(_ts_decorate2, "_ts_decorate");
523
+ function _ts_metadata2(k, v) {
524
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
525
+ }
526
+ __name(_ts_metadata2, "_ts_metadata");
527
+ var _B2BGuard = class _B2BGuard {
528
+ bearerTokenGuard;
529
+ constructor(bearerTokenGuard) {
530
+ this.bearerTokenGuard = bearerTokenGuard;
531
+ }
532
+ canActivate(context) {
533
+ return Promise.resolve(this.bearerTokenGuard.canActivate(context));
534
+ }
535
+ };
536
+ __name(_B2BGuard, "B2BGuard");
537
+ var B2BGuard = _B2BGuard;
538
+ B2BGuard = _ts_decorate2([
539
+ (0, import_common2.Injectable)(),
540
+ _ts_metadata2("design:type", Function),
541
+ _ts_metadata2("design:paramtypes", [
542
+ typeof BearerTokenGuard === "undefined" ? Object : BearerTokenGuard
543
+ ])
544
+ ], B2BGuard);
545
+
546
+ // src/b2c.guard.ts
547
+ var import_common3 = require("@nestjs/common");
548
+ var import_shared2 = __toESM(require_dist());
549
+
550
+ // src/keycloak.headers.ts
551
+ var state = {
552
+ headers: {
553
+ b2cToken: parseEnvHeader("KEYCLOAK_B2C_TOKEN_HEADER", "x-access-token"),
554
+ b2bToken: parseEnvHeader("KEYCLOAK_B2B_TOKEN_HEADER", "authorization")
555
+ },
556
+ claims: {
557
+ userId: parseEnvClaims("KEYCLOAK_USER_ID_CLAIM", [
558
+ "sub"
559
+ ]),
560
+ callerId: parseEnvClaims("KEYCLOAK_CALLER_ID_CLAIM", [
561
+ "azp"
562
+ ])
563
+ }
564
+ };
565
+ function configureTokenHeaders(cfg) {
566
+ if (cfg.b2cToken) state.headers.b2cToken = cfg.b2cToken.toLowerCase();
567
+ if (cfg.b2bToken) state.headers.b2bToken = cfg.b2bToken.toLowerCase();
568
+ }
569
+ __name(configureTokenHeaders, "configureTokenHeaders");
570
+ function configureTokenClaims(cfg) {
571
+ if (cfg.userId) state.claims.userId = normalizeClaims(cfg.userId);
572
+ if (cfg.callerId) state.claims.callerId = normalizeClaims(cfg.callerId);
573
+ }
574
+ __name(configureTokenClaims, "configureTokenClaims");
575
+ function getB2CTokenHeader() {
576
+ return state.headers.b2cToken;
577
+ }
578
+ __name(getB2CTokenHeader, "getB2CTokenHeader");
579
+ function getB2BTokenHeader() {
580
+ return state.headers.b2bToken;
581
+ }
582
+ __name(getB2BTokenHeader, "getB2BTokenHeader");
583
+ function getUserIdClaims() {
584
+ return state.claims.userId;
585
+ }
586
+ __name(getUserIdClaims, "getUserIdClaims");
587
+ function getCallerIdClaims() {
588
+ return state.claims.callerId;
589
+ }
590
+ __name(getCallerIdClaims, "getCallerIdClaims");
591
+ function parseEnvHeader(key, fallback) {
592
+ return (process.env[key] ?? fallback).toLowerCase();
593
+ }
594
+ __name(parseEnvHeader, "parseEnvHeader");
595
+ function parseEnvClaims(key, fallback) {
596
+ const raw = process.env[key];
597
+ if (!raw) return fallback;
598
+ return raw.split(",").map((c) => c.trim()).filter(Boolean);
599
+ }
600
+ __name(parseEnvClaims, "parseEnvClaims");
601
+ function normalizeClaims(value) {
602
+ if (Array.isArray(value)) return value.filter(Boolean);
603
+ return value.split(",").map((c) => c.trim()).filter(Boolean);
604
+ }
605
+ __name(normalizeClaims, "normalizeClaims");
606
+
607
+ // src/b2c.guard.ts
608
+ function _ts_decorate3(decorators, target, key, desc) {
609
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
610
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
611
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
612
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
613
+ }
614
+ __name(_ts_decorate3, "_ts_decorate");
615
+ var _B2CGuard = class _B2CGuard {
616
+ canActivate(context) {
617
+ var _a;
618
+ const request = context.switchToHttp().getRequest();
619
+ const accessToken = (_a = request.headers) == null ? void 0 : _a[getB2CTokenHeader()];
620
+ if (accessToken) return true;
621
+ throw new import_shared2.BaseAppError({
622
+ message: "Missing X-Access-Token header. Route requires Kong-forwarded user authentication.",
623
+ status: HTTP_STATUS.UNAUTHORIZED,
624
+ code: BEARER_ERROR_CODE.MISSING_TOKEN,
625
+ context: {}
626
+ });
627
+ }
628
+ };
629
+ __name(_B2CGuard, "B2CGuard");
630
+ var B2CGuard = _B2CGuard;
631
+ B2CGuard = _ts_decorate3([
632
+ (0, import_common3.Injectable)()
633
+ ], B2CGuard);
634
+
635
+ // src/api-auth.guard.ts
636
+ function _ts_decorate4(decorators, target, key, desc) {
637
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
638
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
639
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
640
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
641
+ }
642
+ __name(_ts_decorate4, "_ts_decorate");
643
+ function _ts_metadata3(k, v) {
644
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
645
+ }
646
+ __name(_ts_metadata3, "_ts_metadata");
647
+ var _ApiAuthGuard = class _ApiAuthGuard {
648
+ b2bGuard;
649
+ b2cGuard;
650
+ constructor(b2bGuard, b2cGuard) {
651
+ this.b2bGuard = b2bGuard;
652
+ this.b2cGuard = b2cGuard;
653
+ }
654
+ async canActivate(context) {
655
+ var _a, _b;
656
+ const request = context.switchToHttp().getRequest();
657
+ const accessToken = (_a = request.headers) == null ? void 0 : _a[getB2CTokenHeader()];
658
+ if (accessToken) {
659
+ return this.b2cGuard.canActivate(context);
660
+ }
661
+ const authHeader = (_b = request.headers) == null ? void 0 : _b[getB2BTokenHeader()];
662
+ if (authHeader == null ? void 0 : authHeader.toLowerCase().startsWith("bearer ")) {
663
+ return this.b2bGuard.canActivate(context);
664
+ }
665
+ throw new import_shared3.BaseAppError({
666
+ message: "Unauthorized: missing X-Access-Token (Kong/B2C) or Authorization header (B2B)",
667
+ status: HTTP_STATUS.UNAUTHORIZED,
668
+ code: BEARER_ERROR_CODE.MISSING_TOKEN,
669
+ context: {}
670
+ });
671
+ }
672
+ };
673
+ __name(_ApiAuthGuard, "ApiAuthGuard");
674
+ var ApiAuthGuard = _ApiAuthGuard;
675
+ ApiAuthGuard = _ts_decorate4([
676
+ (0, import_common4.Injectable)(),
677
+ _ts_metadata3("design:type", Function),
678
+ _ts_metadata3("design:paramtypes", [
679
+ typeof B2BGuard === "undefined" ? Object : B2BGuard,
680
+ typeof B2CGuard === "undefined" ? Object : B2CGuard
681
+ ])
682
+ ], ApiAuthGuard);
683
+
452
684
  // src/keycloak.client.ts
453
- var import_common2 = require("@nestjs/common");
685
+ var import_common5 = require("@nestjs/common");
454
686
  var import_http_client2 = require("@adatechnology/http-client");
455
687
  var import_logger2 = require("@adatechnology/logger");
456
688
  var import_cache = require("@adatechnology/cache");
457
689
  var import_cache2 = require("@adatechnology/cache");
458
690
 
459
691
  // src/errors/keycloak-error.ts
460
- var KeycloakError = class _KeycloakError extends Error {
692
+ var _KeycloakError = class _KeycloakError extends Error {
461
693
  statusCode;
462
694
  details;
463
695
  keycloakError;
@@ -470,8 +702,27 @@ var KeycloakError = class _KeycloakError extends Error {
470
702
  Object.setPrototypeOf(this, _KeycloakError.prototype);
471
703
  }
472
704
  };
705
+ __name(_KeycloakError, "KeycloakError");
706
+ var KeycloakError = _KeycloakError;
473
707
 
474
708
  // src/keycloak.client.ts
709
+ function _ts_decorate5(decorators, target, key, desc) {
710
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
711
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
712
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
713
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
714
+ }
715
+ __name(_ts_decorate5, "_ts_decorate");
716
+ function _ts_metadata4(k, v) {
717
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
718
+ }
719
+ __name(_ts_metadata4, "_ts_metadata");
720
+ function _ts_param2(paramIndex, decorator) {
721
+ return function(target, key) {
722
+ decorator(target, key, paramIndex);
723
+ };
724
+ }
725
+ __name(_ts_param2, "_ts_param");
475
726
  function extractErrorInfo(err) {
476
727
  var _a, _b, _c, _d, _e;
477
728
  const statusCode = (err == null ? void 0 : err.status) ?? ((_a = err == null ? void 0 : err.response) == null ? void 0 : _a.status);
@@ -496,15 +747,19 @@ function extractErrorInfo(err) {
496
747
  keycloakError: keycloakError ?? (errorCode ? `NETWORK_ERROR_${String(errorCode)}` : void 0)
497
748
  };
498
749
  }
499
- var KeycloakClient = class {
750
+ __name(extractErrorInfo, "extractErrorInfo");
751
+ var _KeycloakClient = class _KeycloakClient {
752
+ config;
753
+ httpProvider;
754
+ logger;
755
+ cacheProvider;
756
+ tokenPromise = null;
500
757
  constructor(config, httpProvider, logger, cacheProvider) {
501
758
  this.config = config;
502
759
  this.httpProvider = httpProvider;
503
760
  this.logger = logger;
504
761
  this.cacheProvider = cacheProvider ?? new import_cache.InMemoryCacheProvider(logger);
505
762
  }
506
- cacheProvider;
507
- tokenPromise = null;
508
763
  log(level, message, libMethod, meta) {
509
764
  if (!this.logger) return;
510
765
  const loggerCtx = (0, import_logger2.getContext)();
@@ -566,21 +821,29 @@ var KeycloakClient = class {
566
821
  if (this.config.credentials.clientSecret) {
567
822
  body.append("client_secret", this.config.credentials.clientSecret);
568
823
  }
569
- body.append("scope", KeycloakClient.scopesToString(this.config.scopes));
824
+ body.append("scope", _KeycloakClient.scopesToString(this.config.scopes));
570
825
  try {
571
826
  const response = await this.httpProvider.post({
572
827
  url: tokenUrl,
573
828
  data: body,
574
829
  config: {
575
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
576
- logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
830
+ headers: {
831
+ "Content-Type": "application/x-www-form-urlencoded"
832
+ },
833
+ logContext: {
834
+ className: LOG_CONTEXT.KEYCLOAK_CLIENT,
835
+ methodName: method
836
+ }
577
837
  }
578
838
  });
579
839
  this.log("info", `${method} - Success for user: ${username}`, method);
580
840
  return response.data;
581
841
  } catch (err) {
582
842
  const { statusCode, details, keycloakError } = extractErrorInfo(err);
583
- this.log("error", `${method} - Failed for user: ${username}`, method, { statusCode, keycloakError });
843
+ this.log("error", `${method} - Failed for user: ${username}`, method, {
844
+ statusCode,
845
+ keycloakError
846
+ });
584
847
  throw new KeycloakError("Failed to obtain token with credentials", {
585
848
  statusCode,
586
849
  details,
@@ -602,7 +865,7 @@ var KeycloakClient = class {
602
865
  if (this.config.credentials.username && this.config.credentials.password) {
603
866
  data.append("username", this.config.credentials.username);
604
867
  data.append("password", this.config.credentials.password);
605
- data.append("scope", KeycloakClient.scopesToString(this.config.scopes));
868
+ data.append("scope", _KeycloakClient.scopesToString(this.config.scopes));
606
869
  }
607
870
  }
608
871
  try {
@@ -610,15 +873,23 @@ var KeycloakClient = class {
610
873
  url: tokenUrl,
611
874
  data,
612
875
  config: {
613
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
614
- logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
876
+ headers: {
877
+ "Content-Type": "application/x-www-form-urlencoded"
878
+ },
879
+ logContext: {
880
+ className: LOG_CONTEXT.KEYCLOAK_CLIENT,
881
+ methodName: method
882
+ }
615
883
  }
616
884
  });
617
885
  this.log("debug", `${method} - Success`, method);
618
886
  return response.data;
619
887
  } catch (err) {
620
888
  const { statusCode, details, keycloakError } = extractErrorInfo(err);
621
- this.log("error", `${method} - Failed`, method, { statusCode, keycloakError });
889
+ this.log("error", `${method} - Failed`, method, {
890
+ statusCode,
891
+ keycloakError
892
+ });
622
893
  throw new KeycloakError("Failed to request token", {
623
894
  statusCode,
624
895
  details,
@@ -642,8 +913,13 @@ var KeycloakClient = class {
642
913
  url: tokenUrl,
643
914
  data,
644
915
  config: {
645
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
646
- logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
916
+ headers: {
917
+ "Content-Type": "application/x-www-form-urlencoded"
918
+ },
919
+ logContext: {
920
+ className: LOG_CONTEXT.KEYCLOAK_CLIENT,
921
+ methodName: method
922
+ }
647
923
  }
648
924
  });
649
925
  const ttlSeconds = this.config.tokenCacheTtl ? Math.floor(this.config.tokenCacheTtl / 1e3) : response.data.expires_in - 60;
@@ -652,7 +928,10 @@ var KeycloakClient = class {
652
928
  return response.data;
653
929
  } catch (err) {
654
930
  const { statusCode, details, keycloakError } = extractErrorInfo(err);
655
- this.log("error", `${method} - Failed`, method, { statusCode, keycloakError });
931
+ this.log("error", `${method} - Failed`, method, {
932
+ statusCode,
933
+ keycloakError
934
+ });
656
935
  throw new KeycloakError("Failed to refresh token", {
657
936
  statusCode,
658
937
  details,
@@ -676,8 +955,13 @@ var KeycloakClient = class {
676
955
  url: introspectUrl,
677
956
  data,
678
957
  config: {
679
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
680
- logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
958
+ headers: {
959
+ "Content-Type": "application/x-www-form-urlencoded"
960
+ },
961
+ logContext: {
962
+ className: LOG_CONTEXT.KEYCLOAK_CLIENT,
963
+ methodName: method
964
+ }
681
965
  }
682
966
  });
683
967
  const active = ((_a = response.data) == null ? void 0 : _a.active) === true;
@@ -685,7 +969,10 @@ var KeycloakClient = class {
685
969
  return active;
686
970
  } catch (error) {
687
971
  const { statusCode, details, keycloakError } = extractErrorInfo(error);
688
- this.log("error", `${method} - Failed`, method, { statusCode, keycloakError });
972
+ this.log("error", `${method} - Failed`, method, {
973
+ statusCode,
974
+ keycloakError
975
+ });
689
976
  throw new KeycloakError("Token introspection failed", {
690
977
  statusCode,
691
978
  details,
@@ -701,15 +988,23 @@ var KeycloakClient = class {
701
988
  const response = await this.httpProvider.get({
702
989
  url: userInfoUrl,
703
990
  config: {
704
- headers: { Authorization: `Bearer ${token}` },
705
- logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
991
+ headers: {
992
+ Authorization: `Bearer ${token}`
993
+ },
994
+ logContext: {
995
+ className: LOG_CONTEXT.KEYCLOAK_CLIENT,
996
+ methodName: method
997
+ }
706
998
  }
707
999
  });
708
1000
  this.log("debug", `${method} - Success`, method);
709
1001
  return response.data;
710
1002
  } catch (err) {
711
1003
  const { statusCode, details, keycloakError } = extractErrorInfo(err);
712
- this.log("error", `${method} - Failed`, method, { statusCode, keycloakError });
1004
+ this.log("error", `${method} - Failed`, method, {
1005
+ statusCode,
1006
+ keycloakError
1007
+ });
713
1008
  throw new KeycloakError("Failed to retrieve userinfo", {
714
1009
  statusCode,
715
1010
  details,
@@ -725,18 +1020,38 @@ var KeycloakClient = class {
725
1020
  return Array.isArray(scopes) ? scopes.join(" ") : String(scopes);
726
1021
  }
727
1022
  };
728
- KeycloakClient = __decorateClass([
729
- (0, import_common2.Injectable)(),
730
- __decorateParam(1, (0, import_common2.Inject)(import_http_client2.HTTP_PROVIDER)),
731
- __decorateParam(2, (0, import_common2.Optional)()),
732
- __decorateParam(2, (0, import_common2.Inject)(import_logger2.LOGGER_PROVIDER)),
733
- __decorateParam(3, (0, import_common2.Optional)()),
734
- __decorateParam(3, (0, import_common2.Inject)(import_cache2.CACHE_PROVIDER))
1023
+ __name(_KeycloakClient, "KeycloakClient");
1024
+ var KeycloakClient = _KeycloakClient;
1025
+ KeycloakClient = _ts_decorate5([
1026
+ (0, import_common5.Injectable)(),
1027
+ _ts_param2(1, (0, import_common5.Inject)(import_http_client2.HTTP_PROVIDER)),
1028
+ _ts_param2(2, (0, import_common5.Optional)()),
1029
+ _ts_param2(2, (0, import_common5.Inject)(import_logger2.LOGGER_PROVIDER)),
1030
+ _ts_param2(3, (0, import_common5.Optional)()),
1031
+ _ts_param2(3, (0, import_common5.Inject)(import_cache2.CACHE_PROVIDER)),
1032
+ _ts_metadata4("design:type", Function),
1033
+ _ts_metadata4("design:paramtypes", [
1034
+ typeof KeycloakConfig === "undefined" ? Object : KeycloakConfig,
1035
+ typeof HttpProviderInterface === "undefined" ? Object : HttpProviderInterface,
1036
+ typeof import_logger2.LoggerProviderInterface === "undefined" ? Object : import_logger2.LoggerProviderInterface,
1037
+ typeof CacheProviderInterface === "undefined" ? Object : CacheProviderInterface
1038
+ ])
735
1039
  ], KeycloakClient);
736
1040
 
737
1041
  // src/keycloak.http.interceptor.ts
738
- var import_common3 = require("@nestjs/common");
739
- var KeycloakHttpInterceptor = class {
1042
+ var import_common6 = require("@nestjs/common");
1043
+ function _ts_decorate6(decorators, target, key, desc) {
1044
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1045
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1046
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1047
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1048
+ }
1049
+ __name(_ts_decorate6, "_ts_decorate");
1050
+ function _ts_metadata5(k, v) {
1051
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1052
+ }
1053
+ __name(_ts_metadata5, "_ts_metadata");
1054
+ var _KeycloakHttpInterceptor = class _KeycloakHttpInterceptor {
740
1055
  constructor() {
741
1056
  }
742
1057
  intercept(context, next) {
@@ -746,141 +1061,259 @@ var KeycloakHttpInterceptor = class {
746
1061
  return next.handle();
747
1062
  }
748
1063
  };
749
- KeycloakHttpInterceptor = __decorateClass([
750
- (0, import_common3.Injectable)()
1064
+ __name(_KeycloakHttpInterceptor, "KeycloakHttpInterceptor");
1065
+ var KeycloakHttpInterceptor = _KeycloakHttpInterceptor;
1066
+ KeycloakHttpInterceptor = _ts_decorate6([
1067
+ (0, import_common6.Injectable)(),
1068
+ _ts_metadata5("design:type", Function),
1069
+ _ts_metadata5("design:paramtypes", [])
751
1070
  ], KeycloakHttpInterceptor);
752
1071
 
753
1072
  // src/roles.guard.ts
754
- var import_common5 = require("@nestjs/common");
1073
+ var import_common8 = require("@nestjs/common");
755
1074
  var import_core = require("@nestjs/core");
756
1075
 
757
1076
  // src/roles.decorator.ts
758
- var import_common4 = require("@nestjs/common");
1077
+ var import_common7 = require("@nestjs/common");
759
1078
  var ROLES_META_KEY = "roles";
1079
+ var B2C_ROLES_META_KEY = "roles:b2c";
1080
+ var B2B_ROLES_META_KEY = "roles:b2b";
1081
+ var TOKEN_ROLES_META_KEY = "roles:token";
760
1082
  function Roles(...args) {
1083
+ return (0, import_common7.SetMetadata)(ROLES_META_KEY, normalizeRolesOptions(args));
1084
+ }
1085
+ __name(Roles, "Roles");
1086
+ function B2CRoles(...args) {
1087
+ return (0, import_common7.SetMetadata)(B2C_ROLES_META_KEY, normalizeRolesOptions(args));
1088
+ }
1089
+ __name(B2CRoles, "B2CRoles");
1090
+ function B2BRoles(...args) {
1091
+ return (0, import_common7.SetMetadata)(B2B_ROLES_META_KEY, normalizeRolesOptions(args));
1092
+ }
1093
+ __name(B2BRoles, "B2BRoles");
1094
+ function normalizeRolesOptions(args) {
761
1095
  let payload;
762
1096
  if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0])) {
763
1097
  payload = args[0];
764
1098
  } else {
765
- const roles = [].concat(
766
- ...args.map((a) => Array.isArray(a) ? a : String(a))
767
- );
768
- payload = { roles };
1099
+ const roles = [].concat(...args.map((a) => Array.isArray(a) ? a : String(a)));
1100
+ payload = {
1101
+ roles
1102
+ };
769
1103
  }
770
1104
  payload.mode = payload.mode ?? "any";
771
1105
  payload.type = payload.type ?? "both";
772
- return (0, import_common4.SetMetadata)(ROLES_META_KEY, payload);
1106
+ return payload;
1107
+ }
1108
+ __name(normalizeRolesOptions, "normalizeRolesOptions");
1109
+ function TokenRoles(options) {
1110
+ const normalized = {
1111
+ ...options,
1112
+ header: options.header.toLowerCase(),
1113
+ mode: options.mode ?? "any",
1114
+ // auto-detect bearer stripping: true when header is 'authorization'
1115
+ bearer: options.bearer ?? options.header.toLowerCase() === "authorization"
1116
+ };
1117
+ return (0, import_common7.SetMetadata)(TOKEN_ROLES_META_KEY, [
1118
+ normalized
1119
+ ]);
773
1120
  }
1121
+ __name(TokenRoles, "TokenRoles");
774
1122
 
775
1123
  // src/roles.guard.ts
776
- var import_shared2 = __toESM(require_dist());
777
- var RolesGuard = class {
1124
+ var import_shared4 = __toESM(require_dist());
1125
+ function _ts_decorate7(decorators, target, key, desc) {
1126
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1127
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1128
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1129
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1130
+ }
1131
+ __name(_ts_decorate7, "_ts_decorate");
1132
+ function _ts_metadata6(k, v) {
1133
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1134
+ }
1135
+ __name(_ts_metadata6, "_ts_metadata");
1136
+ function _ts_param3(paramIndex, decorator) {
1137
+ return function(target, key) {
1138
+ decorator(target, key, paramIndex);
1139
+ };
1140
+ }
1141
+ __name(_ts_param3, "_ts_param");
1142
+ var _RolesGuard = class _RolesGuard {
1143
+ reflector;
1144
+ config;
778
1145
  constructor(reflector, config) {
779
1146
  this.reflector = reflector;
780
1147
  this.config = config;
781
1148
  }
782
1149
  canActivate(context) {
783
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
784
- const meta = this.reflector.get(ROLES_META_KEY, context.getHandler()) || this.reflector.get(ROLES_META_KEY, context.getClass());
785
- if (!meta || !meta.roles || meta.roles.length === 0) return true;
1150
+ var _a, _b, _c, _d, _e, _f;
786
1151
  const req = context.switchToHttp().getRequest();
787
- const required = meta.roles;
788
- const availableRoles = /* @__PURE__ */ new Set();
789
- const kongRolesHeader = ((_a = req.headers) == null ? void 0 : _a["x-user-roles"]) || ((_b = req.headers) == null ? void 0 : _b["X-User-Roles"]);
790
- if (kongRolesHeader) {
791
- kongRolesHeader.split(",").map((r) => r.trim()).filter(Boolean).forEach((r) => availableRoles.add(r));
792
- } else {
793
- const authHeader = ((_c = req.headers) == null ? void 0 : _c.authorization) || ((_d = req.headers) == null ? void 0 : _d.Authorization);
794
- const token = authHeader ? String(authHeader).split(" ")[1] : (_e = req.query) == null ? void 0 : _e.token;
795
- if (!token) {
796
- throw new import_shared2.BaseAppError({
797
- message: "Authorization token not provided",
798
- status: HTTP_STATUS.FORBIDDEN,
799
- code: ROLES_ERROR_CODE.MISSING_TOKEN,
800
- context: {}
801
- });
802
- }
803
- const payload = this.decodeJwtPayload(token);
804
- if (((_f = payload == null ? void 0 : payload.realm_access) == null ? void 0 : _f.roles) && Array.isArray(payload.realm_access.roles)) {
805
- payload.realm_access.roles.forEach((r) => availableRoles.add(r));
806
- }
807
- const clientId = (_h = (_g = this.config) == null ? void 0 : _g.credentials) == null ? void 0 : _h.clientId;
808
- if (clientId && ((_j = (_i = payload == null ? void 0 : payload.resource_access) == null ? void 0 : _i[clientId]) == null ? void 0 : _j.roles)) {
809
- payload.resource_access[clientId].roles.forEach(
810
- (r) => availableRoles.add(r)
811
- );
1152
+ const b2cMeta = this.getMeta(B2C_ROLES_META_KEY, context);
1153
+ const b2bMeta = this.getMeta(B2B_ROLES_META_KEY, context);
1154
+ const genericMeta = this.getMeta(ROLES_META_KEY, context);
1155
+ const tokenRules = this.reflector.getAllAndMerge(TOKEN_ROLES_META_KEY, [
1156
+ context.getHandler(),
1157
+ context.getClass()
1158
+ ]) ?? [];
1159
+ if (!b2cMeta && !b2bMeta && !genericMeta && tokenRules.length === 0) return true;
1160
+ if (b2cMeta) {
1161
+ const token = (_a = req.headers) == null ? void 0 : _a[getB2CTokenHeader()];
1162
+ const roles = token ? this.extractRoles(token, "b2c") : /* @__PURE__ */ new Set();
1163
+ this.assertRoles(roles, b2cMeta, "B2C (user)");
1164
+ }
1165
+ if (b2bMeta) {
1166
+ const raw = (_b = req.headers) == null ? void 0 : _b[getB2BTokenHeader()];
1167
+ const token = raw == null ? void 0 : raw.split(" ")[1];
1168
+ const roles = token ? this.extractRoles(token, "b2b") : /* @__PURE__ */ new Set();
1169
+ this.assertRoles(roles, b2bMeta, "B2B (service)");
1170
+ }
1171
+ if (genericMeta) {
1172
+ const accessToken = (_c = req.headers) == null ? void 0 : _c[getB2CTokenHeader()];
1173
+ if (accessToken) {
1174
+ const roles = this.extractRoles(accessToken, "b2c");
1175
+ this.assertRoles(roles, genericMeta, "B2C (user)");
1176
+ } else {
1177
+ const raw = (_d = req.headers) == null ? void 0 : _d[getB2BTokenHeader()];
1178
+ const token = (raw == null ? void 0 : raw.split(" ")[1]) ?? ((_e = req.query) == null ? void 0 : _e.token);
1179
+ if (!token) {
1180
+ throw new import_shared4.BaseAppError({
1181
+ message: "Authorization token not provided",
1182
+ status: HTTP_STATUS.FORBIDDEN,
1183
+ code: ROLES_ERROR_CODE.MISSING_TOKEN,
1184
+ context: {}
1185
+ });
1186
+ }
1187
+ const roles = this.extractRoles(token, "b2b");
1188
+ this.assertRoles(roles, genericMeta, "B2B (service)");
812
1189
  }
813
- if (meta.type === "both" && (payload == null ? void 0 : payload.resource_access)) {
814
- Object.values(payload.resource_access).forEach((entry) => {
815
- if ((entry == null ? void 0 : entry.roles) && Array.isArray(entry.roles)) {
816
- entry.roles.forEach((r) => availableRoles.add(r));
817
- }
818
- });
1190
+ }
1191
+ for (const rule of tokenRules) {
1192
+ const raw = (_f = req.headers) == null ? void 0 : _f[rule.header];
1193
+ const token = rule.bearer ? raw == null ? void 0 : raw.split(" ")[1] : raw;
1194
+ const roles = token ? this.extractRoles(token, "b2c") : /* @__PURE__ */ new Set();
1195
+ this.assertRoles(roles, {
1196
+ roles: rule.roles,
1197
+ mode: rule.mode ?? "any"
1198
+ }, `header:${rule.header}`);
1199
+ }
1200
+ return true;
1201
+ }
1202
+ // ── Helpers ───────────────────────────────────────────────────────────────
1203
+ getMeta(key, ctx) {
1204
+ return this.reflector.get(key, ctx.getHandler()) || this.reflector.get(key, ctx.getClass()) || void 0;
1205
+ }
1206
+ extractRoles(token, source) {
1207
+ var _a, _b, _c, _d;
1208
+ const payload = this.decodeJwtPayload(token);
1209
+ const roles = /* @__PURE__ */ new Set();
1210
+ if (((_a = payload == null ? void 0 : payload.realm_access) == null ? void 0 : _a.roles) && Array.isArray(payload.realm_access.roles)) {
1211
+ payload.realm_access.roles.forEach((r) => roles.add(r));
1212
+ }
1213
+ if (source === "b2b" && (payload == null ? void 0 : payload.resource_access)) {
1214
+ const clientId = (_c = (_b = this.config) == null ? void 0 : _b.credentials) == null ? void 0 : _c.clientId;
1215
+ if (clientId && ((_d = payload.resource_access[clientId]) == null ? void 0 : _d.roles)) {
1216
+ payload.resource_access[clientId].roles.forEach((r) => roles.add(r));
819
1217
  }
820
1218
  }
821
- const hasMatch = required.map((r) => availableRoles.has(r));
822
- const result = meta.mode === "all" ? hasMatch.every(Boolean) : hasMatch.some(Boolean);
823
- if (!result) {
824
- throw new import_shared2.BaseAppError({
825
- message: "Insufficient roles",
1219
+ return roles;
1220
+ }
1221
+ assertRoles(available, meta, label) {
1222
+ const hasMatch = meta.roles.map((r) => available.has(r));
1223
+ const passed = meta.mode === "all" ? hasMatch.every(Boolean) : hasMatch.some(Boolean);
1224
+ if (!passed) {
1225
+ throw new import_shared4.BaseAppError({
1226
+ message: `Insufficient roles for ${label} token`,
826
1227
  status: HTTP_STATUS.FORBIDDEN,
827
1228
  code: ROLES_ERROR_CODE.INSUFFICIENT_ROLES,
828
- context: { required }
1229
+ context: {
1230
+ required: meta.roles,
1231
+ source: label
1232
+ }
829
1233
  });
830
1234
  }
831
- return true;
832
1235
  }
833
1236
  decodeJwtPayload(token) {
834
1237
  try {
835
1238
  const parts = token.split(".");
836
1239
  if (parts.length < 2) return {};
837
- const payload = parts[1];
1240
+ const padded = parts[1].replace(/-/g, "+").replace(/_/g, "/");
838
1241
  const BufferCtor = globalThis.Buffer;
839
1242
  if (!BufferCtor) return {};
840
- const decoded = BufferCtor.from(payload, "base64").toString("utf8");
841
- return JSON.parse(decoded);
1243
+ return JSON.parse(BufferCtor.from(padded, "base64").toString("utf8"));
842
1244
  } catch {
843
1245
  return {};
844
1246
  }
845
1247
  }
846
1248
  };
847
- RolesGuard = __decorateClass([
848
- (0, import_common5.Injectable)(),
849
- __decorateParam(0, (0, import_common5.Inject)(import_core.Reflector)),
850
- __decorateParam(1, (0, import_common5.Optional)()),
851
- __decorateParam(1, (0, import_common5.Inject)(KEYCLOAK_CONFIG))
1249
+ __name(_RolesGuard, "RolesGuard");
1250
+ var RolesGuard = _RolesGuard;
1251
+ RolesGuard = _ts_decorate7([
1252
+ (0, import_common8.Injectable)(),
1253
+ _ts_param3(0, (0, import_common8.Inject)(import_core.Reflector)),
1254
+ _ts_param3(1, (0, import_common8.Optional)()),
1255
+ _ts_param3(1, (0, import_common8.Inject)(KEYCLOAK_CONFIG)),
1256
+ _ts_metadata6("design:type", Function),
1257
+ _ts_metadata6("design:paramtypes", [
1258
+ typeof import_core.Reflector === "undefined" ? Object : import_core.Reflector,
1259
+ typeof KeycloakConfig === "undefined" ? Object : KeycloakConfig
1260
+ ])
852
1261
  ], RolesGuard);
853
1262
 
854
1263
  // src/keycloak.module.ts
855
- var KeycloakModule = class {
1264
+ function _ts_decorate8(decorators, target, key, desc) {
1265
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1266
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1267
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1268
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1269
+ }
1270
+ __name(_ts_decorate8, "_ts_decorate");
1271
+ var _KeycloakModule = class _KeycloakModule {
856
1272
  static forRoot(config, httpConfig) {
1273
+ if (config.headers) configureTokenHeaders(config.headers);
1274
+ if (config.claims) configureTokenClaims(config.claims);
857
1275
  return {
858
- module: KeycloakModule,
1276
+ module: _KeycloakModule,
859
1277
  global: true,
860
1278
  imports: [
861
- import_http_client3.HttpModule.forRoot(
862
- httpConfig || { baseURL: config.baseUrl, timeout: 5e3 },
863
- {
864
- logging: {
865
- enabled: true,
866
- includeBody: true,
867
- context: "KeycloakHttpClient",
868
- environments: ["development", "test"]
869
- }
1279
+ import_http_client3.HttpModule.forRoot(httpConfig || {
1280
+ baseURL: config.baseUrl,
1281
+ timeout: 5e3
1282
+ }, {
1283
+ logging: {
1284
+ enabled: true,
1285
+ includeBody: true,
1286
+ context: "KeycloakHttpClient",
1287
+ environments: [
1288
+ "development",
1289
+ "test"
1290
+ ]
870
1291
  }
871
- )
1292
+ })
872
1293
  ],
873
1294
  providers: [
874
- { provide: import_core2.Reflector, useClass: import_core2.Reflector },
875
- { provide: KEYCLOAK_CONFIG, useValue: config },
1295
+ {
1296
+ provide: import_core2.Reflector,
1297
+ useClass: import_core2.Reflector
1298
+ },
1299
+ {
1300
+ provide: KEYCLOAK_CONFIG,
1301
+ useValue: config
1302
+ },
876
1303
  {
877
1304
  provide: KEYCLOAK_CLIENT,
878
- useFactory: (cfg, httpProvider, logger, cacheProvider) => new KeycloakClient(cfg, httpProvider, logger, cacheProvider),
1305
+ useFactory: /* @__PURE__ */ __name((cfg, httpProvider, logger, cacheProvider) => new KeycloakClient(cfg, httpProvider, logger, cacheProvider), "useFactory"),
879
1306
  inject: [
880
1307
  KEYCLOAK_CONFIG,
881
1308
  import_http_client3.HTTP_PROVIDER,
882
- { token: import_logger3.LOGGER_PROVIDER, optional: true },
883
- { token: import_cache3.CACHE_PROVIDER, optional: true }
1309
+ {
1310
+ token: import_logger3.LOGGER_PROVIDER,
1311
+ optional: true
1312
+ },
1313
+ {
1314
+ token: import_cache3.CACHE_PROVIDER,
1315
+ optional: true
1316
+ }
884
1317
  ]
885
1318
  },
886
1319
  {
@@ -889,10 +1322,13 @@ var KeycloakModule = class {
889
1322
  },
890
1323
  {
891
1324
  provide: KEYCLOAK_HTTP_INTERCEPTOR,
892
- useFactory: () => new KeycloakHttpInterceptor()
1325
+ useFactory: /* @__PURE__ */ __name(() => new KeycloakHttpInterceptor(), "useFactory")
893
1326
  },
894
1327
  RolesGuard,
895
- BearerTokenGuard
1328
+ BearerTokenGuard,
1329
+ B2CGuard,
1330
+ B2BGuard,
1331
+ ApiAuthGuard
896
1332
  ],
897
1333
  exports: [
898
1334
  import_core2.Reflector,
@@ -901,98 +1337,137 @@ var KeycloakModule = class {
901
1337
  KEYCLOAK_HTTP_INTERCEPTOR,
902
1338
  KEYCLOAK_CONFIG,
903
1339
  RolesGuard,
904
- BearerTokenGuard
1340
+ BearerTokenGuard,
1341
+ B2CGuard,
1342
+ B2BGuard,
1343
+ ApiAuthGuard
905
1344
  ]
906
1345
  };
907
1346
  }
908
1347
  };
909
- KeycloakModule = __decorateClass([
910
- (0, import_common6.Module)({})
1348
+ __name(_KeycloakModule, "KeycloakModule");
1349
+ var KeycloakModule = _KeycloakModule;
1350
+ KeycloakModule = _ts_decorate8([
1351
+ (0, import_common9.Module)({})
911
1352
  ], KeycloakModule);
912
1353
 
913
- // src/b2b.guard.ts
914
- var import_common7 = require("@nestjs/common");
915
- var B2BGuard = class {
916
- constructor(bearerTokenGuard) {
917
- this.bearerTokenGuard = bearerTokenGuard;
1354
+ // src/auth-user.decorator.ts
1355
+ var import_common10 = require("@nestjs/common");
1356
+ var AuthUser = (0, import_common10.createParamDecorator)((param, ctx) => {
1357
+ var _a;
1358
+ const request = ctx.switchToHttp().getRequest();
1359
+ const { header, claims } = resolveB2CParam(param);
1360
+ const raw = (_a = request.headers) == null ? void 0 : _a[header];
1361
+ const token = Array.isArray(raw) ? raw[0] : raw;
1362
+ if (!token) return "";
1363
+ return decodeJwtClaims(String(token), claims) ?? "";
1364
+ });
1365
+ var CallerToken = (0, import_common10.createParamDecorator)((param, ctx) => {
1366
+ var _a;
1367
+ const request = ctx.switchToHttp().getRequest();
1368
+ const { header, claims } = resolveB2BParam(param);
1369
+ const raw = (_a = request.headers) == null ? void 0 : _a[header];
1370
+ const token = raw == null ? void 0 : raw.split(" ")[1];
1371
+ if (!token) return "";
1372
+ return decodeJwtClaims(token, claims) ?? "";
1373
+ });
1374
+ var AccessToken = (0, import_common10.createParamDecorator)((header, ctx) => {
1375
+ var _a;
1376
+ const request = ctx.switchToHttp().getRequest();
1377
+ const h = (header == null ? void 0 : header.toLowerCase()) ?? getB2CTokenHeader();
1378
+ const raw = (_a = request.headers) == null ? void 0 : _a[h];
1379
+ return Array.isArray(raw) ? raw[0] : raw ?? "";
1380
+ });
1381
+ function resolveB2CParam(param) {
1382
+ var _a;
1383
+ if (!param) {
1384
+ return {
1385
+ header: getB2CTokenHeader(),
1386
+ claims: getUserIdClaims()
1387
+ };
918
1388
  }
919
- canActivate(context) {
920
- return Promise.resolve(this.bearerTokenGuard.canActivate(context));
1389
+ if (typeof param === "string") {
1390
+ return {
1391
+ header: getB2CTokenHeader(),
1392
+ claims: [
1393
+ param
1394
+ ]
1395
+ };
921
1396
  }
922
- };
923
- B2BGuard = __decorateClass([
924
- (0, import_common7.Injectable)()
925
- ], B2BGuard);
926
-
927
- // src/b2c.guard.ts
928
- var import_common8 = require("@nestjs/common");
929
- var import_shared3 = __toESM(require_dist());
930
- var B2CGuard = class {
931
- canActivate(context) {
932
- var _a, _b;
933
- const request = context.switchToHttp().getRequest();
934
- const userId = ((_a = request.headers) == null ? void 0 : _a["x-user-id"]) ?? ((_b = request.headers) == null ? void 0 : _b["X-User-Id"]);
935
- if (userId) return true;
936
- throw new import_shared3.BaseAppError({
937
- message: "Missing Kong identity headers (X-User-Id). Route requires user authentication via Kong.",
938
- status: HTTP_STATUS.UNAUTHORIZED,
939
- code: BEARER_ERROR_CODE.MISSING_TOKEN,
940
- context: {}
941
- });
1397
+ if (Array.isArray(param)) {
1398
+ return {
1399
+ header: getB2CTokenHeader(),
1400
+ claims: param
1401
+ };
942
1402
  }
943
- };
944
- B2CGuard = __decorateClass([
945
- (0, import_common8.Injectable)()
946
- ], B2CGuard);
947
-
948
- // src/api-auth.guard.ts
949
- var import_common9 = require("@nestjs/common");
950
- var import_shared4 = __toESM(require_dist());
951
- var ApiAuthGuard = class {
952
- constructor(b2bGuard, b2cGuard) {
953
- this.b2bGuard = b2bGuard;
954
- this.b2cGuard = b2cGuard;
1403
+ return {
1404
+ header: ((_a = param.header) == null ? void 0 : _a.toLowerCase()) ?? getB2CTokenHeader(),
1405
+ claims: param.claim ? normalizeClaims2(param.claim) : getUserIdClaims()
1406
+ };
1407
+ }
1408
+ __name(resolveB2CParam, "resolveB2CParam");
1409
+ function resolveB2BParam(param) {
1410
+ var _a;
1411
+ if (!param) {
1412
+ return {
1413
+ header: getB2BTokenHeader(),
1414
+ claims: getCallerIdClaims()
1415
+ };
955
1416
  }
956
- async canActivate(context) {
957
- var _a, _b, _c, _d;
958
- const request = context.switchToHttp().getRequest();
959
- const authHeader = ((_a = request.headers) == null ? void 0 : _a.authorization) ?? ((_b = request.headers) == null ? void 0 : _b.Authorization);
960
- if (authHeader == null ? void 0 : authHeader.toLowerCase().startsWith("bearer ")) {
961
- return this.b2bGuard.canActivate(context);
962
- }
963
- const userId = ((_c = request.headers) == null ? void 0 : _c["x-user-id"]) ?? ((_d = request.headers) == null ? void 0 : _d["X-User-Id"]);
964
- if (userId) {
965
- return this.b2cGuard.canActivate(context);
966
- }
967
- throw new import_shared4.BaseAppError({
968
- message: "Unauthorized: missing Authorization header (B2B) or Kong identity headers (B2C)",
969
- status: HTTP_STATUS.UNAUTHORIZED,
970
- code: BEARER_ERROR_CODE.MISSING_TOKEN,
971
- context: {}
972
- });
1417
+ if (typeof param === "string") {
1418
+ return {
1419
+ header: getB2BTokenHeader(),
1420
+ claims: [
1421
+ param
1422
+ ]
1423
+ };
973
1424
  }
974
- };
975
- ApiAuthGuard = __decorateClass([
976
- (0, import_common9.Injectable)()
977
- ], ApiAuthGuard);
978
-
979
- // src/auth-user.decorator.ts
980
- var import_common10 = require("@nestjs/common");
981
- var AuthUser = (0, import_common10.createParamDecorator)(
982
- (_data, ctx) => {
983
- var _a, _b;
984
- const request = ctx.switchToHttp().getRequest();
985
- const raw = ((_a = request.headers) == null ? void 0 : _a["x-user-id"]) ?? ((_b = request.headers) == null ? void 0 : _b["X-User-Id"]);
986
- return Array.isArray(raw) ? raw[0] : raw ?? "";
1425
+ if (Array.isArray(param)) {
1426
+ return {
1427
+ header: getB2BTokenHeader(),
1428
+ claims: param
1429
+ };
987
1430
  }
988
- );
1431
+ return {
1432
+ header: ((_a = param.header) == null ? void 0 : _a.toLowerCase()) ?? getB2BTokenHeader(),
1433
+ claims: param.claim ? normalizeClaims2(param.claim) : getCallerIdClaims()
1434
+ };
1435
+ }
1436
+ __name(resolveB2BParam, "resolveB2BParam");
1437
+ function normalizeClaims2(value) {
1438
+ if (Array.isArray(value)) return value.filter(Boolean);
1439
+ return value.split(",").map((c) => c.trim()).filter(Boolean);
1440
+ }
1441
+ __name(normalizeClaims2, "normalizeClaims");
1442
+ function decodeJwtClaims(token, claims) {
1443
+ try {
1444
+ const parts = token.split(".");
1445
+ if (parts.length < 2) return void 0;
1446
+ const padded = parts[1].replace(/-/g, "+").replace(/_/g, "/");
1447
+ const BufferCtor = globalThis.Buffer;
1448
+ if (!BufferCtor) return void 0;
1449
+ const payload = JSON.parse(BufferCtor.from(padded, "base64").toString("utf8"));
1450
+ for (const claim of claims) {
1451
+ const value = payload[claim];
1452
+ if (typeof value === "string" && value.length > 0) return value;
1453
+ }
1454
+ return void 0;
1455
+ } catch {
1456
+ return void 0;
1457
+ }
1458
+ }
1459
+ __name(decodeJwtClaims, "decodeJwtClaims");
989
1460
  // Annotate the CommonJS export names for ESM import in node:
990
1461
  0 && (module.exports = {
1462
+ AccessToken,
991
1463
  ApiAuthGuard,
992
1464
  AuthUser,
993
1465
  B2BGuard,
1466
+ B2BRoles,
994
1467
  B2CGuard,
1468
+ B2CRoles,
995
1469
  BearerTokenGuard,
1470
+ CallerToken,
996
1471
  KEYCLOAK_CLIENT,
997
1472
  KEYCLOAK_CONFIG,
998
1473
  KEYCLOAK_HTTP_INTERCEPTOR,
@@ -1000,5 +1475,6 @@ var AuthUser = (0, import_common10.createParamDecorator)(
1000
1475
  KeycloakError,
1001
1476
  KeycloakModule,
1002
1477
  Roles,
1003
- RolesGuard
1478
+ RolesGuard,
1479
+ TokenRoles
1004
1480
  });