@clemax/nest-keycloak-connect 2.0.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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +298 -0
  3. package/dist/constants.d.ts +69 -0
  4. package/dist/constants.js +76 -0
  5. package/dist/decorators/access-token.decorator.d.ts +5 -0
  6. package/dist/decorators/access-token.decorator.js +13 -0
  7. package/dist/decorators/enforcer-options.decorator.d.ts +8 -0
  8. package/dist/decorators/enforcer-options.decorator.js +12 -0
  9. package/dist/decorators/keycloak-user.decorator.d.ts +5 -0
  10. package/dist/decorators/keycloak-user.decorator.js +13 -0
  11. package/dist/decorators/public.decorator.d.ts +7 -0
  12. package/dist/decorators/public.decorator.js +12 -0
  13. package/dist/decorators/resource.decorator.d.ts +6 -0
  14. package/dist/decorators/resource.decorator.js +11 -0
  15. package/dist/decorators/roles.decorator.d.ts +10 -0
  16. package/dist/decorators/roles.decorator.js +15 -0
  17. package/dist/decorators/scopes.decorator.d.ts +19 -0
  18. package/dist/decorators/scopes.decorator.js +28 -0
  19. package/dist/guards/auth.guard.d.ts +19 -0
  20. package/dist/guards/auth.guard.js +172 -0
  21. package/dist/guards/resource.guard.d.ts +18 -0
  22. package/dist/guards/resource.guard.js +175 -0
  23. package/dist/guards/role.guard.d.ts +17 -0
  24. package/dist/guards/role.guard.js +139 -0
  25. package/dist/index.d.ts +1 -0
  26. package/dist/index.js +18 -0
  27. package/dist/interface/keycloak-connect-module-async-options.interface.d.ts +9 -0
  28. package/dist/interface/keycloak-connect-module-async-options.interface.js +2 -0
  29. package/dist/interface/keycloak-connect-options-factory.interface.d.ts +4 -0
  30. package/dist/interface/keycloak-connect-options-factory.interface.js +2 -0
  31. package/dist/interface/keycloak-connect-options.interface.d.ts +166 -0
  32. package/dist/interface/keycloak-connect-options.interface.js +3 -0
  33. package/dist/internal.util.d.ts +8 -0
  34. package/dist/internal.util.js +69 -0
  35. package/dist/keycloak-connect.module.d.ts +32 -0
  36. package/dist/keycloak-connect.module.js +126 -0
  37. package/dist/keycloak-connect.providers.d.ts +7 -0
  38. package/dist/keycloak-connect.providers.js +81 -0
  39. package/dist/services/keycloak-multitenant.service.d.ts +24 -0
  40. package/dist/services/keycloak-multitenant.service.js +174 -0
  41. package/dist/util.d.ts +1 -0
  42. package/dist/util.js +8 -0
  43. package/package.json +100 -0
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ var __importDefault = (this && this.__importDefault) || function (mod) {
24
+ return (mod && mod.__esModule) ? mod : { "default": mod };
25
+ };
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.KeycloakMultiTenantService = void 0;
28
+ const common_1 = require("@nestjs/common");
29
+ const keycloak_connect_1 = __importDefault(require("keycloak-connect"));
30
+ const constants_1 = require("../constants");
31
+ /**
32
+ * Stores all keycloak instances when multi tenant option is defined.
33
+ */
34
+ let KeycloakMultiTenantService = class KeycloakMultiTenantService {
35
+ constructor(keycloakOpts) {
36
+ this.keycloakOpts = keycloakOpts;
37
+ this.instances = new Map();
38
+ }
39
+ /**
40
+ * Clears the cached Keycloak instances.
41
+ */
42
+ clear() {
43
+ this.instances.clear();
44
+ }
45
+ /**
46
+ * Retrieves a keycloak instance based on the realm provided.
47
+ * @param realm the realm to retrieve from
48
+ * @param request the request instance, defaults to undefined
49
+ * @returns the multi tenant keycloak instance
50
+ */
51
+ get(realm_1) {
52
+ return __awaiter(this, arguments, void 0, function* (realm, request = undefined) {
53
+ if (typeof this.keycloakOpts === 'string') {
54
+ throw new Error('Keycloak configuration is a configuration path. This should not happen after module load.');
55
+ }
56
+ if (this.keycloakOpts.multiTenant === null ||
57
+ this.keycloakOpts.multiTenant === undefined) {
58
+ throw new Error('Multi tenant is not defined yet multi tenant service is being called.');
59
+ }
60
+ const authServerUrl = yield this.resolveAuthServerUrl(realm, request);
61
+ const secret = yield this.resolveSecret(realm, request);
62
+ const clientId = yield this.resolveClientId(realm, request);
63
+ // Check if existing
64
+ if (this.instances.has(realm) &&
65
+ !this.keycloakOpts.multiTenant.resolveAlways) {
66
+ // Otherwise return the instance
67
+ return this.instances.get(realm);
68
+ }
69
+ else {
70
+ // TODO: Repeating code from provider, will need to rework this in 2.0
71
+ // Override realm, secret, and authServerUrl
72
+ const keycloakOpts = Object.assign(this.keycloakOpts, {
73
+ authServerUrl,
74
+ realm,
75
+ secret,
76
+ clientId,
77
+ });
78
+ const keycloak = new keycloak_connect_1.default({}, keycloakOpts);
79
+ // The most important part
80
+ keycloak.accessDenied = (req, res, next) => {
81
+ req.resourceDenied = true;
82
+ next();
83
+ };
84
+ // Save instance
85
+ this.instances.set(realm, keycloak);
86
+ return keycloak;
87
+ }
88
+ });
89
+ }
90
+ resolveAuthServerUrl(realm_1) {
91
+ return __awaiter(this, arguments, void 0, function* (realm, request = undefined) {
92
+ if (typeof this.keycloakOpts === 'string') {
93
+ throw new Error('Keycloak configuration is a configuration path. This should not happen after module load.');
94
+ }
95
+ if (this.keycloakOpts.multiTenant === null ||
96
+ this.keycloakOpts.multiTenant === undefined) {
97
+ throw new Error('Multi tenant is not defined yet multi tenant service is being called.');
98
+ }
99
+ // If no realm auth server url resolver is defined, return defaults
100
+ if (!this.keycloakOpts.multiTenant.realmAuthServerUrlResolver) {
101
+ return (this.keycloakOpts.authServerUrl ||
102
+ this.keycloakOpts['auth-server-url'] ||
103
+ this.keycloakOpts.serverUrl ||
104
+ this.keycloakOpts['server-url']);
105
+ }
106
+ // Resolve realm authServerUrl
107
+ const resolvedAuthServerUrl = this.keycloakOpts.multiTenant.realmAuthServerUrlResolver(realm, request);
108
+ const authServerUrl = resolvedAuthServerUrl || resolvedAuthServerUrl instanceof Promise
109
+ ? yield resolvedAuthServerUrl
110
+ : resolvedAuthServerUrl;
111
+ // Override auth server url
112
+ // Order of priority: resolved realm auth server url > provided auth server url
113
+ return (authServerUrl ||
114
+ this.keycloakOpts.authServerUrl ||
115
+ this.keycloakOpts['auth-server-url'] ||
116
+ this.keycloakOpts.serverUrl ||
117
+ this.keycloakOpts['server-url']);
118
+ });
119
+ }
120
+ resolveClientId(realm_1) {
121
+ return __awaiter(this, arguments, void 0, function* (realm, request = undefined) {
122
+ if (typeof this.keycloakOpts === 'string') {
123
+ throw new Error('Keycloak configuration is a configuration path. This should not happen after module load.');
124
+ }
125
+ if (this.keycloakOpts.multiTenant === null ||
126
+ this.keycloakOpts.multiTenant === undefined) {
127
+ throw new Error('Multi tenant is not defined yet multi tenant service is being called.');
128
+ }
129
+ // If no realm client-id resolver is defined, return defaults
130
+ if (!this.keycloakOpts.multiTenant.realmClientIdResolver) {
131
+ return this.keycloakOpts.clientId || this.keycloakOpts['client-id'];
132
+ }
133
+ // Resolve realm client-id
134
+ const resolvedClientId = this.keycloakOpts.multiTenant.realmClientIdResolver(realm, request);
135
+ const realmClientId = resolvedClientId || resolvedClientId instanceof Promise
136
+ ? yield resolvedClientId
137
+ : resolvedClientId;
138
+ // Override client-id
139
+ // Order of priority: resolved realm secret > default global secret
140
+ return (realmClientId ||
141
+ this.keycloakOpts.clientId ||
142
+ this.keycloakOpts['client-id']);
143
+ });
144
+ }
145
+ resolveSecret(realm_1) {
146
+ return __awaiter(this, arguments, void 0, function* (realm, request = undefined) {
147
+ if (typeof this.keycloakOpts === 'string') {
148
+ throw new Error('Keycloak configuration is a configuration path. This should not happen after module load.');
149
+ }
150
+ if (this.keycloakOpts.multiTenant === null ||
151
+ this.keycloakOpts.multiTenant === undefined) {
152
+ throw new Error('Multi tenant is not defined yet multi tenant service is being called.');
153
+ }
154
+ // If no realm secret resolver is defined, return defaults
155
+ if (!this.keycloakOpts.multiTenant.realmSecretResolver) {
156
+ return this.keycloakOpts.secret;
157
+ }
158
+ // Resolve realm secret
159
+ const resolvedRealmSecret = this.keycloakOpts.multiTenant.realmSecretResolver(realm, request);
160
+ const realmSecret = resolvedRealmSecret || resolvedRealmSecret instanceof Promise
161
+ ? yield resolvedRealmSecret
162
+ : resolvedRealmSecret;
163
+ // Override secret
164
+ // Order of priority: resolved realm secret > default global secret
165
+ return realmSecret || this.keycloakOpts.secret;
166
+ });
167
+ }
168
+ };
169
+ exports.KeycloakMultiTenantService = KeycloakMultiTenantService;
170
+ exports.KeycloakMultiTenantService = KeycloakMultiTenantService = __decorate([
171
+ (0, common_1.Injectable)(),
172
+ __param(0, (0, common_1.Inject)(constants_1.KEYCLOAK_CONNECT_OPTIONS)),
173
+ __metadata("design:paramtypes", [Object])
174
+ ], KeycloakMultiTenantService);
package/dist/util.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare const parseToken: (token: string) => any;
package/dist/util.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseToken = void 0;
4
+ const parseToken = (token) => {
5
+ const parts = token.split('.');
6
+ return JSON.parse(Buffer.from(parts[1], 'base64').toString());
7
+ };
8
+ exports.parseToken = parseToken;
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "@clemax/nest-keycloak-connect",
3
+ "version": "2.0.0",
4
+ "description": "keycloak-nodejs-connect module for Nest",
5
+ "author": "John Joshua Ferrer <johnjoshuaferrer@disroot.org>",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "nestjs",
9
+ "keycloak",
10
+ "typescript"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/ferrerojosh/nest-keycloak-connect"
15
+ },
16
+ "bugs": "https://github.com/ferrerojosh/nest-keycloak-connect/issues",
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "main": "./dist/index.js",
21
+ "types": "./dist/index.d.ts",
22
+ "typesVersions": {
23
+ "*": {
24
+ "dist/index.d.ts": [
25
+ "dist/index.d.ts"
26
+ ],
27
+ "*": [
28
+ "dist/*"
29
+ ]
30
+ }
31
+ },
32
+ "exports": {
33
+ ".": "./dist/index.js",
34
+ "./*": "./dist/*"
35
+ },
36
+ "peerDependencies": {
37
+ "@nestjs/common": ">=6.0.0 <12.0.0",
38
+ "@nestjs/core": ">=6.0.0 <12.0.0",
39
+ "@nestjs/graphql": ">=6",
40
+ "keycloak-connect": "npm:@clemax/keycloak-connect@>=10.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@nestjs/common": "^11.0.6",
44
+ "@nestjs/core": "^11.0.6",
45
+ "@nestjs/graphql": "^13.0.2",
46
+ "@types/express": "^4.17.21",
47
+ "@types/node": "^18.19.23",
48
+ "class-transformer": "0.5.1",
49
+ "class-validator": "0.14.1",
50
+ "cpr": "3.0.1",
51
+ "eslint": "8.57.0",
52
+ "eslint-config-prettier": "9.1.0",
53
+ "eslint-plugin-prettier": "5.1.3",
54
+ "graphql": "^16.10.0",
55
+ "husky": "^9.0.11",
56
+ "keycloak-connect": "npm:@clemax/keycloak-connect@26.1.2",
57
+ "lint-staged": "^15.2.2",
58
+ "prettier": "3.2.5",
59
+ "reflect-metadata": "0.2.1",
60
+ "release-it": "17.1.1",
61
+ "rimraf": "3.0.2",
62
+ "rxjs": "7.8.1",
63
+ "ts-node": "10.8.2",
64
+ "typescript": "5.4.2",
65
+ "typescript-eslint": "^7.2.0"
66
+ },
67
+ "peerDependenciesMeta": {
68
+ "@nestjs/graphql": {
69
+ "optional": true
70
+ }
71
+ },
72
+ "funding": [
73
+ {
74
+ "type": "individual",
75
+ "url": "https://www.paypal.me/ferrerojosh/"
76
+ },
77
+ {
78
+ "type": "github",
79
+ "url": "https://github.com/sponsors/ferrerojosh"
80
+ }
81
+ ],
82
+ "volta": {
83
+ "node": "21.7.1"
84
+ },
85
+ "lint-staged": {
86
+ "**/*.ts": [
87
+ "prettier --write",
88
+ "eslint"
89
+ ]
90
+ },
91
+ "scripts": {
92
+ "start:dev": "tsc -w",
93
+ "clean": "rimraf dist",
94
+ "build": "tsc",
95
+ "release": "release-it",
96
+ "release:alpha": "release-it --preReleaseId=alpha --npm.tag=next --github.preRelease",
97
+ "format": "prettier src --write",
98
+ "lint": "eslint src"
99
+ }
100
+ }