@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.
- package/dist/integrations.cjs +1 -1
- package/dist/integrations.cjs.map +1 -1
- package/dist/integrations.js +1 -1
- package/dist/integrations.js.map +1 -1
- package/lib/cjs/index.cjs +3 -3
- package/lib/cjs/nest/authService.cjs +53 -2
- package/lib/cjs/nest/authService.cjs.map +1 -1
- package/lib/cjs/nest/index.cjs +2 -0
- package/lib/cjs/nest/index.cjs.map +1 -1
- package/lib/cjs/nest/keycloakAuthHandler.cjs +49 -23
- package/lib/cjs/nest/keycloakAuthHandler.cjs.map +1 -1
- package/lib/cjs/nest/keycloakModule.cjs +5 -3
- package/lib/cjs/nest/keycloakModule.cjs.map +1 -1
- package/lib/cjs/nest/logging.cjs +41 -0
- package/lib/cjs/nest/logging.cjs.map +1 -0
- package/lib/cjs/nest/utils.cjs +24 -0
- package/lib/cjs/nest/utils.cjs.map +1 -1
- package/lib/cjs/utils.cjs +1 -1
- package/lib/esm/index.js +3 -3
- package/lib/esm/nest/authService.js +54 -3
- package/lib/esm/nest/authService.js.map +1 -1
- package/lib/esm/nest/index.js +2 -0
- package/lib/esm/nest/index.js.map +1 -1
- package/lib/esm/nest/keycloakAuthHandler.js +49 -23
- package/lib/esm/nest/keycloakAuthHandler.js.map +1 -1
- package/lib/esm/nest/keycloakModule.js +5 -3
- package/lib/esm/nest/keycloakModule.js.map +1 -1
- package/lib/esm/nest/logging.js +38 -0
- package/lib/esm/nest/logging.js.map +1 -0
- package/lib/esm/nest/utils.js +23 -0
- package/lib/esm/nest/utils.js.map +1 -1
- package/lib/esm/utils.js +1 -1
- package/lib/types/index.d.cts +2 -2
- package/lib/types/index.d.mts +2 -2
- package/lib/types/nest/authService.d.cts +55 -2
- package/lib/types/nest/authService.d.mts +55 -2
- package/lib/types/nest/index.d.cts +2 -0
- package/lib/types/nest/index.d.mts +2 -0
- package/lib/types/nest/keycloakAuthHandler.d.cts +51 -5
- package/lib/types/nest/keycloakAuthHandler.d.mts +51 -5
- package/lib/types/nest/keycloakModule.d.cts +3 -3
- package/lib/types/nest/keycloakModule.d.mts +3 -3
- package/lib/types/nest/logging.d.cts +1 -0
- package/lib/types/nest/logging.d.mts +1 -0
- package/lib/types/nest/types.d.cts +23 -18
- package/lib/types/nest/types.d.mts +23 -18
- package/lib/types/nest/utils.d.cts +9 -0
- package/lib/types/nest/utils.d.mts +9 -0
- package/package.json +32 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keycloakAuthHandler.js","sourceRoot":"","sources":["../../../src/nest/keycloakAuthHandler.ts"],"names":[],"mappings":"
|
|
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
|
|
9
|
+
constructor(authService, authHandler) {
|
|
10
10
|
this.authService = authService;
|
|
11
11
|
this.authHandler = authHandler;
|
|
12
12
|
}
|
|
13
|
-
static create() {
|
|
14
|
-
|
|
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,
|
|
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"}
|
package/lib/esm/nest/utils.js
CHANGED
|
@@ -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.
|
|
21
|
+
log.debug(data.trim());
|
|
22
22
|
});
|
|
23
23
|
child.on("close", (code) => {
|
|
24
24
|
if (code === 0) {
|
package/lib/types/index.d.cts
CHANGED
|
@@ -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 = "
|
|
9
|
-
export declare const FULL_VERSION = "0.1
|
|
8
|
+
export declare const COMMIT = "4990f39";
|
|
9
|
+
export declare const FULL_VERSION = "0.2.1-4990f39";
|
|
10
10
|
export declare const PACKAGE_NAME: string;
|
package/lib/types/index.d.mts
CHANGED
|
@@ -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 = "
|
|
9
|
-
export declare const FULL_VERSION = "0.1
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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 {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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 {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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;
|