@decaf-ts/integrations 0.2.1 → 0.3.0

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/keycloak/services/KeycloakRoleService.cjs +25 -0
  7. package/lib/cjs/keycloak/services/KeycloakRoleService.cjs.map +1 -1
  8. package/lib/cjs/keycloak/services/KeycloakService.cjs +29 -0
  9. package/lib/cjs/keycloak/services/KeycloakService.cjs.map +1 -1
  10. package/lib/cjs/nest/authService.cjs +53 -2
  11. package/lib/cjs/nest/authService.cjs.map +1 -1
  12. package/lib/cjs/nest/keycloakAuthHandler.cjs +13 -6
  13. package/lib/cjs/nest/keycloakAuthHandler.cjs.map +1 -1
  14. package/lib/cjs/nest/keycloakModule.cjs +5 -3
  15. package/lib/cjs/nest/keycloakModule.cjs.map +1 -1
  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/keycloak/services/KeycloakRoleService.js +25 -0
  21. package/lib/esm/keycloak/services/KeycloakRoleService.js.map +1 -1
  22. package/lib/esm/keycloak/services/KeycloakService.js +30 -1
  23. package/lib/esm/keycloak/services/KeycloakService.js.map +1 -1
  24. package/lib/esm/nest/authService.js +54 -3
  25. package/lib/esm/nest/authService.js.map +1 -1
  26. package/lib/esm/nest/keycloakAuthHandler.js +13 -6
  27. package/lib/esm/nest/keycloakAuthHandler.js.map +1 -1
  28. package/lib/esm/nest/keycloakModule.js +5 -3
  29. package/lib/esm/nest/keycloakModule.js.map +1 -1
  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/keycloak/services/KeycloakRoleService.d.cts +14 -0
  36. package/lib/types/keycloak/services/KeycloakRoleService.d.mts +14 -0
  37. package/lib/types/keycloak/services/KeycloakService.d.cts +9 -0
  38. package/lib/types/keycloak/services/KeycloakService.d.mts +9 -0
  39. package/lib/types/keycloak/types.d.cts +11 -0
  40. package/lib/types/keycloak/types.d.mts +11 -0
  41. package/lib/types/nest/authService.d.cts +55 -2
  42. package/lib/types/nest/authService.d.mts +55 -2
  43. package/lib/types/nest/keycloakAuthHandler.d.cts +14 -5
  44. package/lib/types/nest/keycloakAuthHandler.d.mts +14 -5
  45. package/lib/types/nest/keycloakModule.d.cts +3 -3
  46. package/lib/types/nest/keycloakModule.d.mts +3 -3
  47. package/lib/types/nest/utils.d.cts +9 -0
  48. package/lib/types/nest/utils.d.mts +9 -0
  49. package/package.json +17 -7
@@ -5,9 +5,9 @@
5
5
  * Extends the framework-agnostic {@link AuthHandler} from `@decaf-ts/for-http/server`.
6
6
  *
7
7
  * Only overrides the two extension points:
8
- * - {@link extractFromAuth} — decodes the JWT and returns auth data (no validation).
8
+ * - {@link KeycloakAuthHandler.extractFromAuth} — decodes the JWT and returns auth data (no validation).
9
9
  * Returns empty data for public routes without requiring a token.
10
- * - {@link validate} — validates the JWT via {@link AuthService.assertValidToken},
10
+ * - {@link KeycloakAuthHandler.validate} — validates the JWT via {@link AuthService.assertValidToken},
11
11
  * then delegates to the base class for route-level and model-level role checks.
12
12
  * Skips entirely for public routes.
13
13
  *
@@ -17,8 +17,9 @@
17
17
  import type { Constructor } from "@decaf-ts/decoration";
18
18
  import { Context, ContextualArgs } from "@decaf-ts/core";
19
19
  import { AuthHandler, AuthData } from "@decaf-ts/for-http/server";
20
- import { AuthService } from "./authService.d.cts";
20
+ import { AuthService, type AuthServiceOptions } from "./authService.d.cts";
21
21
  import type { AuthExecutionContextLike } from "./types.d.cts";
22
+ import { getClientRoles } from "./utils.d.cts";
22
23
  /**
23
24
  * Auth data returned by {@link KeycloakAuthHandler.extractFromAuth}.
24
25
  *
@@ -32,8 +33,15 @@ export interface KeycloakAuthData extends AuthData {
32
33
  isPublic: boolean;
33
34
  }
34
35
  export declare class KeycloakAuthHandler extends AuthHandler<AuthExecutionContextLike, Context, KeycloakAuthData> {
35
- private readonly authService;
36
- constructor(authService?: AuthService);
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;
37
45
  protected extractFromAuth(ctx: AuthExecutionContextLike): KeycloakAuthData;
38
46
  /**
39
47
  * Validates the JWT against the Keycloak instance (signature, expiry, etc.)
@@ -42,3 +50,4 @@ export declare class KeycloakAuthHandler extends AuthHandler<AuthExecutionContex
42
50
  */
43
51
  protected validate(data: KeycloakAuthData, routeRoles: string[] | undefined, model: string | Constructor, ...args: ContextualArgs<Context>): Promise<void>;
44
52
  }
53
+ export { getClientRoles };
@@ -5,9 +5,9 @@
5
5
  * Extends the framework-agnostic {@link AuthHandler} from `@decaf-ts/for-http/server`.
6
6
  *
7
7
  * Only overrides the two extension points:
8
- * - {@link extractFromAuth} — decodes the JWT and returns auth data (no validation).
8
+ * - {@link KeycloakAuthHandler.extractFromAuth} — decodes the JWT and returns auth data (no validation).
9
9
  * Returns empty data for public routes without requiring a token.
10
- * - {@link validate} — validates the JWT via {@link AuthService.assertValidToken},
10
+ * - {@link KeycloakAuthHandler.validate} — validates the JWT via {@link AuthService.assertValidToken},
11
11
  * then delegates to the base class for route-level and model-level role checks.
12
12
  * Skips entirely for public routes.
13
13
  *
@@ -17,8 +17,9 @@
17
17
  import type { Constructor } from "@decaf-ts/decoration";
18
18
  import { Context, ContextualArgs } from "@decaf-ts/core";
19
19
  import { AuthHandler, AuthData } from "@decaf-ts/for-http/server";
20
- import { AuthService } from "./authService.d.mts";
20
+ import { AuthService, type AuthServiceOptions } from "./authService.d.mts";
21
21
  import type { AuthExecutionContextLike } from "./types.d.mts";
22
+ import { getClientRoles } from "./utils.d.mts";
22
23
  /**
23
24
  * Auth data returned by {@link KeycloakAuthHandler.extractFromAuth}.
24
25
  *
@@ -32,8 +33,15 @@ export interface KeycloakAuthData extends AuthData {
32
33
  isPublic: boolean;
33
34
  }
34
35
  export declare class KeycloakAuthHandler extends AuthHandler<AuthExecutionContextLike, Context, KeycloakAuthData> {
35
- private readonly authService;
36
- constructor(authService?: AuthService);
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;
37
45
  protected extractFromAuth(ctx: AuthExecutionContextLike): KeycloakAuthData;
38
46
  /**
39
47
  * Validates the JWT against the Keycloak instance (signature, expiry, etc.)
@@ -42,3 +50,4 @@ export declare class KeycloakAuthHandler extends AuthHandler<AuthExecutionContex
42
50
  */
43
51
  protected validate(data: KeycloakAuthData, routeRoles: string[] | undefined, model: string | Constructor, ...args: ContextualArgs<Context>): Promise<void>;
44
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
  }
@@ -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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decaf-ts/integrations",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.mts",
@@ -214,11 +214,11 @@
214
214
  "reset": "rm -rf * && git checkout . && git pull && npm run do-install",
215
215
  "build": "build-scripts --dev",
216
216
  "build:prod": "build-scripts --prod",
217
- "test": "npm run build && NODE_OPTIONS=\"--experimental-vm-modules\" jest --runInBand --coverage --detectOpenHandles",
217
+ "test": "npm run build && KEYCLOAK_HOST=172.20.0.4:8080 NODE_OPTIONS=\"--experimental-vm-modules\" jest --runInBand --coverage --detectOpenHandles",
218
218
  "test:unit": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --testPathPatterns=\"/tests/unit\" --passWithNoTests --detectOpenHandles",
219
- "test:integration": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --testPathPatterns=\"/tests/(integration)\" --passWithNoTests --detectOpenHandles",
220
- "test:e2e": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --testPathPatterns=\"/tests/(e2e)\" --passWithNoTests --detectOpenHandles",
221
- "test:all": "NODE_OPTIONS=\"--experimental-vm-modules\" jest --runInBand --testPathPatterns=\"/tests\" --passWithNoTests",
219
+ "test:integration": "KEYCLOAK_HOST=172.20.0.4:8080 NODE_OPTIONS=\"--experimental-vm-modules\" jest --testPathPatterns=\"/tests/(integration)\" --passWithNoTests --detectOpenHandles",
220
+ "test:e2e": "KEYCLOAK_HOST=172.20.0.4:8080 NODE_OPTIONS=\"--experimental-vm-modules\" jest --testPathPatterns=\"/tests/(e2e)\" --passWithNoTests --detectOpenHandles",
221
+ "test:all": "KEYCLOAK_HOST=172.20.0.4:8080 NODE_OPTIONS=\"--experimental-vm-modules\" jest --runInBand --testPathPatterns=\"/tests\" --passWithNoTests",
222
222
  "test:circular": "dpdm -T --no-warning --no-tree ./src/index.ts",
223
223
  "coverage": "rimraf ./workdocs/reports/data/*.json && npm run test:all -- --coverage --config=./workdocs/reports/jest.coverage.config.cjs",
224
224
  "lint": "eslint .",
@@ -254,8 +254,10 @@
254
254
  "uuid": "^11.1.1"
255
255
  },
256
256
  "devDependencies": {
257
+ "@decaf-ts/cli": "latest",
257
258
  "@decaf-ts/for-http": "latest",
258
- "@decaf-ts/for-nest": "^0.11.2-refactor",
259
+ "@decaf-ts/for-nano": "latest",
260
+ "@decaf-ts/for-nest": "0.11.2-refactor.5",
259
261
  "@decaf-ts/utils": "latest",
260
262
  "@nestjs/common": "^11.0.0",
261
263
  "@nestjs/core": "^11.0.0",
@@ -269,11 +271,19 @@
269
271
  "supertest": "^7.0.0"
270
272
  },
271
273
  "peerDependencies": {
272
- "@decaf-ts/for-http": ">=0.18.0"
274
+ "@decaf-ts/for-http": "latest",
275
+ "@decaf-ts/for-nest": "0.11.2-refactor.5",
276
+ "jose": ">=5.0.0"
273
277
  },
274
278
  "peerDependenciesMeta": {
275
279
  "@decaf-ts/for-http": {
276
280
  "optional": true
281
+ },
282
+ "@decaf-ts/for-nest": {
283
+ "optional": true
284
+ },
285
+ "jose": {
286
+ "optional": true
277
287
  }
278
288
  },
279
289
  "overrides": {