@decaf-ts/integrations 0.2.0 → 0.2.2

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.
Files changed (49) hide show
  1. package/dist/integrations.cjs +1 -1
  2. package/dist/integrations.cjs.map +1 -1
  3. package/dist/integrations.js +1 -1
  4. package/dist/integrations.js.map +1 -1
  5. package/lib/cjs/index.cjs +3 -3
  6. package/lib/cjs/nest/authService.cjs +53 -2
  7. package/lib/cjs/nest/authService.cjs.map +1 -1
  8. package/lib/cjs/nest/index.cjs +2 -0
  9. package/lib/cjs/nest/index.cjs.map +1 -1
  10. package/lib/cjs/nest/keycloakAuthHandler.cjs +49 -23
  11. package/lib/cjs/nest/keycloakAuthHandler.cjs.map +1 -1
  12. package/lib/cjs/nest/keycloakModule.cjs +5 -3
  13. package/lib/cjs/nest/keycloakModule.cjs.map +1 -1
  14. package/lib/cjs/nest/logging.cjs +41 -0
  15. package/lib/cjs/nest/logging.cjs.map +1 -0
  16. package/lib/cjs/nest/utils.cjs +24 -0
  17. package/lib/cjs/nest/utils.cjs.map +1 -1
  18. package/lib/cjs/utils.cjs +1 -1
  19. package/lib/esm/index.js +3 -3
  20. package/lib/esm/nest/authService.js +54 -3
  21. package/lib/esm/nest/authService.js.map +1 -1
  22. package/lib/esm/nest/index.js +2 -0
  23. package/lib/esm/nest/index.js.map +1 -1
  24. package/lib/esm/nest/keycloakAuthHandler.js +49 -23
  25. package/lib/esm/nest/keycloakAuthHandler.js.map +1 -1
  26. package/lib/esm/nest/keycloakModule.js +5 -3
  27. package/lib/esm/nest/keycloakModule.js.map +1 -1
  28. package/lib/esm/nest/logging.js +38 -0
  29. package/lib/esm/nest/logging.js.map +1 -0
  30. package/lib/esm/nest/utils.js +23 -0
  31. package/lib/esm/nest/utils.js.map +1 -1
  32. package/lib/esm/utils.js +1 -1
  33. package/lib/types/index.d.cts +2 -2
  34. package/lib/types/index.d.mts +2 -2
  35. package/lib/types/nest/authService.d.cts +55 -2
  36. package/lib/types/nest/authService.d.mts +55 -2
  37. package/lib/types/nest/index.d.cts +2 -0
  38. package/lib/types/nest/index.d.mts +2 -0
  39. package/lib/types/nest/keycloakAuthHandler.d.cts +51 -5
  40. package/lib/types/nest/keycloakAuthHandler.d.mts +51 -5
  41. package/lib/types/nest/keycloakModule.d.cts +3 -3
  42. package/lib/types/nest/keycloakModule.d.mts +3 -3
  43. package/lib/types/nest/logging.d.cts +1 -0
  44. package/lib/types/nest/logging.d.mts +1 -0
  45. package/lib/types/nest/types.d.cts +23 -18
  46. package/lib/types/nest/types.d.mts +23 -18
  47. package/lib/types/nest/utils.d.cts +9 -0
  48. package/lib/types/nest/utils.d.mts +9 -0
  49. package/package.json +32 -3
@@ -1 +1 @@
1
- {"version":3,"file":"keycloakAuthHandler.js","sourceRoot":"","sources":["../../../src/nest/keycloakAuthHandler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,mBAAgB;AAEpE,MAAM,OAAO,mBAAmB;IAC9B,YAA6B,cAAc,IAAI,WAAW,EAAE;QAA/B,gBAAW,GAAX,WAAW,CAAoB;IAAG,CAAC;IAEhE,KAAK,CAAC,SAAS,CAAC,OAAiC;QAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAmB,CAAC;QAErE,IAAI,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO;QAChD,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO;QAErE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;QAE5D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,IAAI,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAE7E,OAAO,CAAC,qBAAqB,CAAC,GAAG;YAC/B,KAAK;YACL,IAAI,EAAE,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,kBAAkB;YACjD,GAAG,EAAE,YAAY;SAClB,CAAC;IACJ,CAAC;CACF;AAED,SAAS,QAAQ,CAAC,GAAoB;IACpC,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,6BAA6B,CAAC;QACzD,GAAG,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,CAAuB,CAAC;IACxD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,OAAO,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7E,CAAC"}
1
+ {"version":3,"file":"keycloakAuthHandler.js","sourceRoot":"","sources":["../../../src/nest/keycloakAuthHandler.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,gBAAgB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAY,MAAM,2BAA2B,CAAC;AAElE,OAAO,EAAE,WAAW,EAA2B,yBAAsB;AAErE,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,cAAc,GACf,mBAAgB;AAejB,MAAM,OAAO,mBAAoB,SAAQ,WAIxC;IACC;;;;;;OAMG;IACH,YACE,WAAyB,EACzB,kBAAuC;QAEvC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW;YACd,WAAW,IAAI,IAAI,WAAW,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IAC7D,CAAC;IAIS,eAAe,CAAC,GAA6B;QACrD,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,EAAE,CAAC,UAAU,EAAmB,CAAC;QAEjE,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAClD,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;QAE5D,iDAAiD;QACjD,MAAM,OAAO,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,YAAY,GAAG,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,OAAO,EAAE,KAAK,IAAI,OAAO,EAAE,kBAAkB,CAAC;QAE3D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC/D,CAAC;IAED;;;;OAIG;IACgB,KAAK,CAAC,QAAQ,CAC/B,IAAsB,EACtB,UAAgC,EAChC,KAA2B,EAC3B,GAAG,IAA6B;QAEhC,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,MAAM,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;IACzD,CAAC;CACF;AAED,SAAS,aAAa,CAAC,GAAoB;IACzC,IAAI,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,GAAoB;IACpC,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,6BAA6B,CAAC;QACzD,GAAG,CAAC,OAAO,EAAE,CAAC,eAAe,CAAC,CAAuB,CAAC;IACxD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,OAAO,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7E,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAA8C,EAC9C,KAAa;IAEb,IAAI,OAAO,EAAE,GAAG;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC;IACrC,IAAI,OAAO,EAAE,GAAG;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC;IACrC,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,CAAC"}
@@ -6,12 +6,14 @@
6
6
  import { AuthService } from "./authService.js";
7
7
  import { KeycloakAuthHandler } from "./keycloakAuthHandler.js";
8
8
  export class KeycloakModule {
9
- constructor(authService = new AuthService(), authHandler = new KeycloakAuthHandler(authService)) {
9
+ constructor(authService, authHandler) {
10
10
  this.authService = authService;
11
11
  this.authHandler = authHandler;
12
12
  }
13
- static create() {
14
- return new KeycloakModule();
13
+ static create(options) {
14
+ const authService = new AuthService(options);
15
+ const authHandler = new KeycloakAuthHandler(authService);
16
+ return new KeycloakModule(authService, authHandler);
15
17
  }
16
18
  }
17
19
  export class AuthModule extends KeycloakModule {
@@ -1 +1 @@
1
- {"version":3,"file":"keycloakModule.js","sourceRoot":"","sources":["../../../src/nest/keycloakModule.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,yBAAsB;AAC5C,OAAO,EAAE,mBAAmB,EAAE,iCAA8B;AAE5D,MAAM,OAAO,cAAc;IACzB,YACkB,cAAc,IAAI,WAAW,EAAE,EAC/B,cAAc,IAAI,mBAAmB,CAAC,WAAW,CAAC;QADlD,gBAAW,GAAX,WAAW,CAAoB;QAC/B,gBAAW,GAAX,WAAW,CAAuC;IACjE,CAAC;IAEJ,MAAM,CAAC,MAAM;QACX,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,cAAc;CAAG"}
1
+ {"version":3,"file":"keycloakModule.js","sourceRoot":"","sources":["../../../src/nest/keycloakModule.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAA2B,yBAAsB;AACrE,OAAO,EAAE,mBAAmB,EAAE,iCAA8B;AAE5D,MAAM,OAAO,cAAc;IACzB,YACkB,WAAwB,EACxB,WAAgC;QADhC,gBAAW,GAAX,WAAW,CAAa;QACxB,gBAAW,GAAX,WAAW,CAAqB;IAC/C,CAAC;IAEJ,MAAM,CAAC,MAAM,CAAC,OAA4B;QACxC,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;QACzD,OAAO,IAAI,cAAc,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACtD,CAAC;CACF;AAED,MAAM,OAAO,UAAW,SAAQ,cAAc;CAAG"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @module integrations/nest/logging
3
+ * @summary Keycloak auth log parameters.
4
+ * @description Registers `user` and `organization` as log parameters sourced from the
5
+ * logging config (populated by the auth interceptor's child logger via `Logging.for({ user, organization })`).
6
+ *
7
+ * These parameters are registered here — in `integrations/nest` — because this is the
8
+ * layer that extracts user/organization identity from Keycloak JWTs. The `ip` parameter,
9
+ * by contrast, is registered in `@decaf-ts/for-http/server` where the HTTP request IP is
10
+ * available.
11
+ */
12
+ import { logParameterRegistry } from "@decaf-ts/logging";
13
+ logParameterRegistry
14
+ .register({
15
+ key: "user",
16
+ shouldInclude(payload) {
17
+ return Boolean(payload.config.user);
18
+ },
19
+ render(payload) {
20
+ return String(payload.config.user);
21
+ },
22
+ style(rendered, payload) {
23
+ return payload.applyTheme(rendered, "app");
24
+ },
25
+ })
26
+ .register({
27
+ key: "organization",
28
+ shouldInclude(payload) {
29
+ return Boolean(payload.config.organization);
30
+ },
31
+ render(payload) {
32
+ return String(payload.config.organization);
33
+ },
34
+ style(rendered, payload) {
35
+ return payload.applyTheme(rendered, "app");
36
+ },
37
+ });
38
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../../src/nest/logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAEzD,oBAAoB;KACjB,QAAQ,CAAC;IACR,GAAG,EAAE,MAAM;IACX,aAAa,CAAC,OAAO;QACnB,OAAO,OAAO,CAAE,OAAO,CAAC,MAAkC,CAAC,IAAI,CAAC,CAAC;IACnE,CAAC;IACD,MAAM,CAAC,OAAO;QACZ,OAAO,MAAM,CAAE,OAAO,CAAC,MAAkC,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC;IACD,KAAK,CAAC,QAAQ,EAAE,OAAO;QACrB,OAAO,OAAO,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;CACF,CAAC;KACD,QAAQ,CAAC;IACR,GAAG,EAAE,cAAc;IACnB,aAAa,CAAC,OAAO;QACnB,OAAO,OAAO,CAAE,OAAO,CAAC,MAAkC,CAAC,YAAY,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,CAAC,OAAO;QACZ,OAAO,MAAM,CAAE,OAAO,CAAC,MAAkC,CAAC,YAAY,CAAC,CAAC;IAC1E,CAAC;IACD,KAAK,CAAC,QAAQ,EAAE,OAAO;QACrB,OAAO,OAAO,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;CACF,CAAC,CAAC"}
@@ -23,6 +23,29 @@ export function extractKeycloakRoles(payload) {
23
23
  }
24
24
  return [...roles];
25
25
  }
26
+ /**
27
+ * Extracts roles from the `resource_access` claim only, optionally excluding
28
+ * specified client IDs (e.g. `"account"`). Unlike {@link extractKeycloakRoles}
29
+ * this does NOT include `realm_access.roles`.
30
+ *
31
+ * @param payload The decoded JWT payload.
32
+ * @param excluded Client IDs to skip. @default ["account"]
33
+ */
34
+ export function getClientRoles(payload, excluded = ["account"]) {
35
+ const resourceAccess = payload?.resource_access;
36
+ if (!resourceAccess || typeof resourceAccess !== "object")
37
+ return [];
38
+ const roles = new Set();
39
+ for (const [clientId, data] of Object.entries(resourceAccess)) {
40
+ if (excluded.includes(clientId))
41
+ continue;
42
+ if (Array.isArray(data?.roles)) {
43
+ for (const role of data.roles)
44
+ roles.add(role);
45
+ }
46
+ }
47
+ return [...roles];
48
+ }
26
49
  export function getUser(jwt) {
27
50
  const payload = getTokenPayload(jwt);
28
51
  if (!payload)
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/nest/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/nest/utils.ts"],"names":[],"mappings":"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"}
package/lib/esm/utils.js CHANGED
@@ -18,7 +18,7 @@ export async function execWithLogging(command, options, log, level = LogLevel.in
18
18
  });
19
19
  child.stderr?.on("data", (data) => {
20
20
  stderr.push(data);
21
- log.error(data.trim());
21
+ log.debug(data.trim());
22
22
  });
23
23
  child.on("close", (code) => {
24
24
  if (code === 0) {
@@ -5,6 +5,6 @@
5
5
  */
6
6
  export * from "./utils.d.cts";
7
7
  export declare const VERSION: string;
8
- export declare const COMMIT = "96f5884";
9
- export declare const FULL_VERSION = "0.1.4-96f5884";
8
+ export declare const COMMIT = "4990f39";
9
+ export declare const FULL_VERSION = "0.2.1-4990f39";
10
10
  export declare const PACKAGE_NAME: string;
@@ -5,6 +5,6 @@
5
5
  */
6
6
  export * from "./utils.d.mts";
7
7
  export declare const VERSION: string;
8
- export declare const COMMIT = "96f5884";
9
- export declare const FULL_VERSION = "0.1.4-96f5884";
8
+ export declare const COMMIT = "4990f39";
9
+ export declare const FULL_VERSION = "0.2.1-4990f39";
10
10
  export declare const PACKAGE_NAME: string;
@@ -1,9 +1,62 @@
1
1
  import type { KeycloakAccessTokenPayload, KeycloakUser } from "./types.d.cts";
2
+ /**
3
+ * Configuration for the {@link AuthService}.
4
+ */
5
+ export interface AuthServiceOptions {
6
+ /**
7
+ * Whether to verify the JWT signature against the Keycloak JWKS endpoint.
8
+ * When `false` (or `verifyUrl` is empty), tokens are decoded without
9
+ * signature verification (dev/local mode only).
10
+ * @default false
11
+ */
12
+ verifyToken?: boolean;
13
+ /**
14
+ * The Keycloak JWKS URL (e.g. `https://keycloak/realms/myrealm/protocol/openid-connect/certs`).
15
+ * Required when `verifyToken` is `true`.
16
+ */
17
+ verifyUrl?: string;
18
+ /**
19
+ * Clock tolerance for JWT expiry verification (in seconds).
20
+ * @default 5
21
+ */
22
+ clockToleranceSeconds?: number;
23
+ /**
24
+ * Keycloak client IDs to exclude when extracting roles from `resource_access`.
25
+ * @default ["account"]
26
+ */
27
+ excludedClients?: string[];
28
+ }
2
29
  export declare class AuthService {
30
+ private readonly verifyToken;
31
+ private readonly verifyUrl;
32
+ private readonly clockToleranceSeconds;
33
+ private readonly excludedClients;
34
+ private jwks;
35
+ constructor(options?: AuthServiceOptions);
3
36
  getTokenPayload(jwt: string): KeycloakAccessTokenPayload | null;
4
37
  getRoles(jwt: string): string[];
5
38
  getUser(jwt: string): KeycloakUser | undefined;
6
- extractKeycloakRoles(payload: unknown): string[];
39
+ extractKeycloakRoles(payload: KeycloakAccessTokenPayload | null): string[];
40
+ /**
41
+ * Extracts client roles from the `resource_access` claim, excluding
42
+ * the configured `excludedClients` (default: `["account"]`).
43
+ */
44
+ extractClientRoles(payload: KeycloakAccessTokenPayload | null): string[];
7
45
  getRealmFromIssuer(jwt: string): string;
8
- assertValidToken(jwt: string): KeycloakAccessTokenPayload;
46
+ /**
47
+ * Validates a JWT:
48
+ * - In **verify mode**: verifies the signature against the Keycloak JWKS
49
+ * endpoint using `jose.jwtVerify`, then returns the verified payload.
50
+ * - In **decode-only mode**: decodes the JWT without verification and
51
+ * returns the payload (or throws if unparseable).
52
+ *
53
+ * @throws {AuthorizationError} when the token is invalid, expired, or
54
+ * signature verification fails.
55
+ */
56
+ assertValidToken(jwt: string): Promise<KeycloakAccessTokenPayload>;
57
+ /**
58
+ * Verifies the JWT signature against the Keycloak JWKS endpoint.
59
+ * Lazily creates the JWKS keystore on first call.
60
+ */
61
+ private verifyAgainstJwks;
9
62
  }
@@ -1,9 +1,62 @@
1
1
  import type { KeycloakAccessTokenPayload, KeycloakUser } from "./types.d.mts";
2
+ /**
3
+ * Configuration for the {@link AuthService}.
4
+ */
5
+ export interface AuthServiceOptions {
6
+ /**
7
+ * Whether to verify the JWT signature against the Keycloak JWKS endpoint.
8
+ * When `false` (or `verifyUrl` is empty), tokens are decoded without
9
+ * signature verification (dev/local mode only).
10
+ * @default false
11
+ */
12
+ verifyToken?: boolean;
13
+ /**
14
+ * The Keycloak JWKS URL (e.g. `https://keycloak/realms/myrealm/protocol/openid-connect/certs`).
15
+ * Required when `verifyToken` is `true`.
16
+ */
17
+ verifyUrl?: string;
18
+ /**
19
+ * Clock tolerance for JWT expiry verification (in seconds).
20
+ * @default 5
21
+ */
22
+ clockToleranceSeconds?: number;
23
+ /**
24
+ * Keycloak client IDs to exclude when extracting roles from `resource_access`.
25
+ * @default ["account"]
26
+ */
27
+ excludedClients?: string[];
28
+ }
2
29
  export declare class AuthService {
30
+ private readonly verifyToken;
31
+ private readonly verifyUrl;
32
+ private readonly clockToleranceSeconds;
33
+ private readonly excludedClients;
34
+ private jwks;
35
+ constructor(options?: AuthServiceOptions);
3
36
  getTokenPayload(jwt: string): KeycloakAccessTokenPayload | null;
4
37
  getRoles(jwt: string): string[];
5
38
  getUser(jwt: string): KeycloakUser | undefined;
6
- extractKeycloakRoles(payload: unknown): string[];
39
+ extractKeycloakRoles(payload: KeycloakAccessTokenPayload | null): string[];
40
+ /**
41
+ * Extracts client roles from the `resource_access` claim, excluding
42
+ * the configured `excludedClients` (default: `["account"]`).
43
+ */
44
+ extractClientRoles(payload: KeycloakAccessTokenPayload | null): string[];
7
45
  getRealmFromIssuer(jwt: string): string;
8
- assertValidToken(jwt: string): KeycloakAccessTokenPayload;
46
+ /**
47
+ * Validates a JWT:
48
+ * - In **verify mode**: verifies the signature against the Keycloak JWKS
49
+ * endpoint using `jose.jwtVerify`, then returns the verified payload.
50
+ * - In **decode-only mode**: decodes the JWT without verification and
51
+ * returns the payload (or throws if unparseable).
52
+ *
53
+ * @throws {AuthorizationError} when the token is invalid, expired, or
54
+ * signature verification fails.
55
+ */
56
+ assertValidToken(jwt: string): Promise<KeycloakAccessTokenPayload>;
57
+ /**
58
+ * Verifies the JWT signature against the Keycloak JWKS endpoint.
59
+ * Lazily creates the JWKS keystore on first call.
60
+ */
61
+ private verifyAgainstJwks;
9
62
  }
@@ -3,9 +3,11 @@ export * from "./utils.d.cts";
3
3
  export * from "./authService.d.cts";
4
4
  export * from "./keycloakAuthHandler.d.cts";
5
5
  export * from "./keycloakModule.d.cts";
6
+ import "./logging";
6
7
  /**
7
8
  * @summary Nest-style auth integrations.
8
9
  * @description Framework-agnostic auth helpers compatible with Decaf request context handling.
10
+ * Imports the `user`/`organization` log parameter registrations as a side effect.
9
11
  * @namespace nest
10
12
  * @memberOf module:integrations
11
13
  */
@@ -3,9 +3,11 @@ export * from "./utils.d.mts";
3
3
  export * from "./authService.d.mts";
4
4
  export * from "./keycloakAuthHandler.d.mts";
5
5
  export * from "./keycloakModule.d.mts";
6
+ import "./logging";
6
7
  /**
7
8
  * @summary Nest-style auth integrations.
8
9
  * @description Framework-agnostic auth helpers compatible with Decaf request context handling.
10
+ * Imports the `user`/`organization` log parameter registrations as a side effect.
9
11
  * @namespace nest
10
12
  * @memberOf module:integrations
11
13
  */
@@ -1,7 +1,53 @@
1
+ /**
2
+ * @module integrations/nest/keycloakAuthHandler
3
+ * @summary Keycloak request auth handler.
4
+ * @description Translates Keycloak JWT payloads into Decaf-friendly auth data.
5
+ * Extends the framework-agnostic {@link AuthHandler} from `@decaf-ts/for-http/server`.
6
+ *
7
+ * Only overrides the two extension points:
8
+ * - {@link KeycloakAuthHandler.extractFromAuth} — decodes the JWT and returns auth data (no validation).
9
+ * Returns empty data for public routes without requiring a token.
10
+ * - {@link KeycloakAuthHandler.validate} — validates the JWT via {@link AuthService.assertValidToken},
11
+ * then delegates to the base class for route-level and model-level role checks.
12
+ * Skips entirely for public routes.
13
+ *
14
+ * Does NOT override `bindToContext` — the base class default `ctx.accumulate(data)`
15
+ * is sufficient. Does NOT override `authorize`.
16
+ */
17
+ import type { Constructor } from "@decaf-ts/decoration";
18
+ import { Context, ContextualArgs } from "@decaf-ts/core";
19
+ import { AuthHandler, AuthData } from "@decaf-ts/for-http/server";
20
+ import { AuthService, type AuthServiceOptions } from "./authService.d.cts";
1
21
  import type { AuthExecutionContextLike } from "./types.d.cts";
2
- import { AuthService } from "./authService.d.cts";
3
- export declare class KeycloakAuthHandler {
4
- private readonly authService;
5
- constructor(authService?: AuthService);
6
- authorize(context: AuthExecutionContextLike): Promise<void>;
22
+ import { getClientRoles } from "./utils.d.cts";
23
+ /**
24
+ * Auth data returned by {@link KeycloakAuthHandler.extractFromAuth}.
25
+ *
26
+ * Carries the raw JWT `token` so that {@link KeycloakAuthHandler.validate} can
27
+ * validate it against the Keycloak instance (signature, expiry, revocation, etc.).
28
+ */
29
+ export interface KeycloakAuthData extends AuthData {
30
+ /** The raw JWT extracted from the request. Empty for public routes. */
31
+ token: string;
32
+ /** Whether the request targets a public route (skips validation). */
33
+ isPublic: boolean;
7
34
  }
35
+ export declare class KeycloakAuthHandler extends AuthHandler<AuthExecutionContextLike, Context, KeycloakAuthData> {
36
+ /**
37
+ * @param authService An {@link AuthService} configured with JWKS verification
38
+ * options. When omitted a default decode-only service is
39
+ * used.
40
+ * @param authServiceOptions Convenience: if `authService` is omitted, these
41
+ * options are used to construct one.
42
+ */
43
+ constructor(authService?: AuthService, authServiceOptions?: AuthServiceOptions);
44
+ protected readonly authService: AuthService;
45
+ protected extractFromAuth(ctx: AuthExecutionContextLike): KeycloakAuthData;
46
+ /**
47
+ * Validates the JWT against the Keycloak instance (signature, expiry, etc.)
48
+ * via {@link AuthService.assertValidToken}, then delegates to the base class
49
+ * for route-level and model-level role checks. Skips entirely for public routes.
50
+ */
51
+ protected validate(data: KeycloakAuthData, routeRoles: string[] | undefined, model: string | Constructor, ...args: ContextualArgs<Context>): Promise<void>;
52
+ }
53
+ export { getClientRoles };
@@ -1,7 +1,53 @@
1
+ /**
2
+ * @module integrations/nest/keycloakAuthHandler
3
+ * @summary Keycloak request auth handler.
4
+ * @description Translates Keycloak JWT payloads into Decaf-friendly auth data.
5
+ * Extends the framework-agnostic {@link AuthHandler} from `@decaf-ts/for-http/server`.
6
+ *
7
+ * Only overrides the two extension points:
8
+ * - {@link KeycloakAuthHandler.extractFromAuth} — decodes the JWT and returns auth data (no validation).
9
+ * Returns empty data for public routes without requiring a token.
10
+ * - {@link KeycloakAuthHandler.validate} — validates the JWT via {@link AuthService.assertValidToken},
11
+ * then delegates to the base class for route-level and model-level role checks.
12
+ * Skips entirely for public routes.
13
+ *
14
+ * Does NOT override `bindToContext` — the base class default `ctx.accumulate(data)`
15
+ * is sufficient. Does NOT override `authorize`.
16
+ */
17
+ import type { Constructor } from "@decaf-ts/decoration";
18
+ import { Context, ContextualArgs } from "@decaf-ts/core";
19
+ import { AuthHandler, AuthData } from "@decaf-ts/for-http/server";
20
+ import { AuthService, type AuthServiceOptions } from "./authService.d.mts";
1
21
  import type { AuthExecutionContextLike } from "./types.d.mts";
2
- import { AuthService } from "./authService.d.mts";
3
- export declare class KeycloakAuthHandler {
4
- private readonly authService;
5
- constructor(authService?: AuthService);
6
- authorize(context: AuthExecutionContextLike): Promise<void>;
22
+ import { getClientRoles } from "./utils.d.mts";
23
+ /**
24
+ * Auth data returned by {@link KeycloakAuthHandler.extractFromAuth}.
25
+ *
26
+ * Carries the raw JWT `token` so that {@link KeycloakAuthHandler.validate} can
27
+ * validate it against the Keycloak instance (signature, expiry, revocation, etc.).
28
+ */
29
+ export interface KeycloakAuthData extends AuthData {
30
+ /** The raw JWT extracted from the request. Empty for public routes. */
31
+ token: string;
32
+ /** Whether the request targets a public route (skips validation). */
33
+ isPublic: boolean;
7
34
  }
35
+ export declare class KeycloakAuthHandler extends AuthHandler<AuthExecutionContextLike, Context, KeycloakAuthData> {
36
+ /**
37
+ * @param authService An {@link AuthService} configured with JWKS verification
38
+ * options. When omitted a default decode-only service is
39
+ * used.
40
+ * @param authServiceOptions Convenience: if `authService` is omitted, these
41
+ * options are used to construct one.
42
+ */
43
+ constructor(authService?: AuthService, authServiceOptions?: AuthServiceOptions);
44
+ protected readonly authService: AuthService;
45
+ protected extractFromAuth(ctx: AuthExecutionContextLike): KeycloakAuthData;
46
+ /**
47
+ * Validates the JWT against the Keycloak instance (signature, expiry, etc.)
48
+ * via {@link AuthService.assertValidToken}, then delegates to the base class
49
+ * for route-level and model-level role checks. Skips entirely for public routes.
50
+ */
51
+ protected validate(data: KeycloakAuthData, routeRoles: string[] | undefined, model: string | Constructor, ...args: ContextualArgs<Context>): Promise<void>;
52
+ }
53
+ export { getClientRoles };
@@ -3,13 +3,13 @@
3
3
  * @summary Nest module wiring for Keycloak auth.
4
4
  * @description Exposes the Nest module setup for the integration auth service and Keycloak handler.
5
5
  */
6
- import { AuthService } from "./authService.d.cts";
6
+ import { AuthService, type AuthServiceOptions } from "./authService.d.cts";
7
7
  import { KeycloakAuthHandler } from "./keycloakAuthHandler.d.cts";
8
8
  export declare class KeycloakModule {
9
9
  readonly authService: AuthService;
10
10
  readonly authHandler: KeycloakAuthHandler;
11
- constructor(authService?: AuthService, authHandler?: KeycloakAuthHandler);
12
- static create(): KeycloakModule;
11
+ constructor(authService: AuthService, authHandler: KeycloakAuthHandler);
12
+ static create(options?: AuthServiceOptions): KeycloakModule;
13
13
  }
14
14
  export declare class AuthModule extends KeycloakModule {
15
15
  }
@@ -3,13 +3,13 @@
3
3
  * @summary Nest module wiring for Keycloak auth.
4
4
  * @description Exposes the Nest module setup for the integration auth service and Keycloak handler.
5
5
  */
6
- import { AuthService } from "./authService.d.mts";
6
+ import { AuthService, type AuthServiceOptions } from "./authService.d.mts";
7
7
  import { KeycloakAuthHandler } from "./keycloakAuthHandler.d.mts";
8
8
  export declare class KeycloakModule {
9
9
  readonly authService: AuthService;
10
10
  readonly authHandler: KeycloakAuthHandler;
11
- constructor(authService?: AuthService, authHandler?: KeycloakAuthHandler);
12
- static create(): KeycloakModule;
11
+ constructor(authService: AuthService, authHandler: KeycloakAuthHandler);
12
+ static create(options?: AuthServiceOptions): KeycloakModule;
13
13
  }
14
14
  export declare class AuthModule extends KeycloakModule {
15
15
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -1,8 +1,30 @@
1
1
  /**
2
2
  * @module integrations/nest/types
3
3
  * @summary Nest integration types.
4
- * @description Shared request-context and auth payload types for Nest integration helpers.
4
+ * @description Keycloak-specific payload types, a platform-specific execution context
5
+ * type, and re-exports of the framework-agnostic auth primitives from
6
+ * `@decaf-ts/for-http/server`.
5
7
  */
8
+ import type { AuthData, AuthRequestLike, UserData } from "@decaf-ts/for-http/server";
9
+ export type { AuthData, AuthRequestLike, UserData };
10
+ /**
11
+ * Structural subset of a NestJS-like execution context that exposes the HTTP request.
12
+ *
13
+ * Defined here (not in for-http) because the base `AuthHandler` class is intentionally
14
+ * generic over its execution context — only the platform that consumes it needs to know
15
+ * the concrete shape.
16
+ */
17
+ export interface AuthExecutionContextLike {
18
+ switchToHttp(): {
19
+ getRequest<T = AuthRequestLike>(): T;
20
+ };
21
+ getHandler?(): {
22
+ name?: string;
23
+ };
24
+ getClass?(): {
25
+ name?: string;
26
+ };
27
+ }
6
28
  export interface KeycloakAccessTokenPayload {
7
29
  preferred_username?: string;
8
30
  email?: string;
@@ -29,20 +51,3 @@ export interface KeycloakUser {
29
51
  family_name?: string;
30
52
  realm?: string;
31
53
  }
32
- export interface AuthRequestLike {
33
- path?: string;
34
- method?: string;
35
- headers?: Record<string, unknown>;
36
- [key: symbol | string]: unknown;
37
- }
38
- export interface AuthExecutionContextLike {
39
- switchToHttp(): {
40
- getRequest<T extends AuthRequestLike = AuthRequestLike>(): T;
41
- };
42
- getHandler?(): {
43
- name?: string;
44
- };
45
- }
46
- export interface AuthHandlerLike {
47
- authorize(context: AuthExecutionContextLike, resource?: string): Promise<void>;
48
- }
@@ -1,8 +1,30 @@
1
1
  /**
2
2
  * @module integrations/nest/types
3
3
  * @summary Nest integration types.
4
- * @description Shared request-context and auth payload types for Nest integration helpers.
4
+ * @description Keycloak-specific payload types, a platform-specific execution context
5
+ * type, and re-exports of the framework-agnostic auth primitives from
6
+ * `@decaf-ts/for-http/server`.
5
7
  */
8
+ import type { AuthData, AuthRequestLike, UserData } from "@decaf-ts/for-http/server";
9
+ export type { AuthData, AuthRequestLike, UserData };
10
+ /**
11
+ * Structural subset of a NestJS-like execution context that exposes the HTTP request.
12
+ *
13
+ * Defined here (not in for-http) because the base `AuthHandler` class is intentionally
14
+ * generic over its execution context — only the platform that consumes it needs to know
15
+ * the concrete shape.
16
+ */
17
+ export interface AuthExecutionContextLike {
18
+ switchToHttp(): {
19
+ getRequest<T = AuthRequestLike>(): T;
20
+ };
21
+ getHandler?(): {
22
+ name?: string;
23
+ };
24
+ getClass?(): {
25
+ name?: string;
26
+ };
27
+ }
6
28
  export interface KeycloakAccessTokenPayload {
7
29
  preferred_username?: string;
8
30
  email?: string;
@@ -29,20 +51,3 @@ export interface KeycloakUser {
29
51
  family_name?: string;
30
52
  realm?: string;
31
53
  }
32
- export interface AuthRequestLike {
33
- path?: string;
34
- method?: string;
35
- headers?: Record<string, unknown>;
36
- [key: symbol | string]: unknown;
37
- }
38
- export interface AuthExecutionContextLike {
39
- switchToHttp(): {
40
- getRequest<T extends AuthRequestLike = AuthRequestLike>(): T;
41
- };
42
- getHandler?(): {
43
- name?: string;
44
- };
45
- }
46
- export interface AuthHandlerLike {
47
- authorize(context: AuthExecutionContextLike, resource?: string): Promise<void>;
48
- }
@@ -7,5 +7,14 @@ import type { KeycloakAccessTokenPayload, KeycloakUser } from "./types.d.cts";
7
7
  export declare const DECAF_ADAPTER_OPTIONS: unique symbol;
8
8
  export declare function getTokenPayload(jwt: string): KeycloakAccessTokenPayload | null;
9
9
  export declare function extractKeycloakRoles(payload: KeycloakAccessTokenPayload | null): string[];
10
+ /**
11
+ * Extracts roles from the `resource_access` claim only, optionally excluding
12
+ * specified client IDs (e.g. `"account"`). Unlike {@link extractKeycloakRoles}
13
+ * this does NOT include `realm_access.roles`.
14
+ *
15
+ * @param payload The decoded JWT payload.
16
+ * @param excluded Client IDs to skip. @default ["account"]
17
+ */
18
+ export declare function getClientRoles(payload: KeycloakAccessTokenPayload | null, excluded?: string[]): string[];
10
19
  export declare function getUser(jwt: string): KeycloakUser | undefined;
11
20
  export declare function getRealmFromIssuer(jwt: string): string;
@@ -7,5 +7,14 @@ import type { KeycloakAccessTokenPayload, KeycloakUser } from "./types.d.mts";
7
7
  export declare const DECAF_ADAPTER_OPTIONS: unique symbol;
8
8
  export declare function getTokenPayload(jwt: string): KeycloakAccessTokenPayload | null;
9
9
  export declare function extractKeycloakRoles(payload: KeycloakAccessTokenPayload | null): string[];
10
+ /**
11
+ * Extracts roles from the `resource_access` claim only, optionally excluding
12
+ * specified client IDs (e.g. `"account"`). Unlike {@link extractKeycloakRoles}
13
+ * this does NOT include `realm_access.roles`.
14
+ *
15
+ * @param payload The decoded JWT payload.
16
+ * @param excluded Client IDs to skip. @default ["account"]
17
+ */
18
+ export declare function getClientRoles(payload: KeycloakAccessTokenPayload | null, excluded?: string[]): string[];
10
19
  export declare function getUser(jwt: string): KeycloakUser | undefined;
11
20
  export declare function getRealmFromIssuer(jwt: string): string;