@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.
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/constants.d.ts +69 -0
- package/dist/constants.js +76 -0
- package/dist/decorators/access-token.decorator.d.ts +5 -0
- package/dist/decorators/access-token.decorator.js +13 -0
- package/dist/decorators/enforcer-options.decorator.d.ts +8 -0
- package/dist/decorators/enforcer-options.decorator.js +12 -0
- package/dist/decorators/keycloak-user.decorator.d.ts +5 -0
- package/dist/decorators/keycloak-user.decorator.js +13 -0
- package/dist/decorators/public.decorator.d.ts +7 -0
- package/dist/decorators/public.decorator.js +12 -0
- package/dist/decorators/resource.decorator.d.ts +6 -0
- package/dist/decorators/resource.decorator.js +11 -0
- package/dist/decorators/roles.decorator.d.ts +10 -0
- package/dist/decorators/roles.decorator.js +15 -0
- package/dist/decorators/scopes.decorator.d.ts +19 -0
- package/dist/decorators/scopes.decorator.js +28 -0
- package/dist/guards/auth.guard.d.ts +19 -0
- package/dist/guards/auth.guard.js +172 -0
- package/dist/guards/resource.guard.d.ts +18 -0
- package/dist/guards/resource.guard.js +175 -0
- package/dist/guards/role.guard.d.ts +17 -0
- package/dist/guards/role.guard.js +139 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -0
- package/dist/interface/keycloak-connect-module-async-options.interface.d.ts +9 -0
- package/dist/interface/keycloak-connect-module-async-options.interface.js +2 -0
- package/dist/interface/keycloak-connect-options-factory.interface.d.ts +4 -0
- package/dist/interface/keycloak-connect-options-factory.interface.js +2 -0
- package/dist/interface/keycloak-connect-options.interface.d.ts +166 -0
- package/dist/interface/keycloak-connect-options.interface.js +3 -0
- package/dist/internal.util.d.ts +8 -0
- package/dist/internal.util.js +69 -0
- package/dist/keycloak-connect.module.d.ts +32 -0
- package/dist/keycloak-connect.module.js +126 -0
- package/dist/keycloak-connect.providers.d.ts +7 -0
- package/dist/keycloak-connect.providers.js +81 -0
- package/dist/services/keycloak-multitenant.service.d.ts +24 -0
- package/dist/services/keycloak-multitenant.service.js +174 -0
- package/dist/util.d.ts +1 -0
- package/dist/util.js +8 -0
- package/package.json +100 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 John Joshua Ferrer
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Nest Keycloak Connect
|
|
4
|
+
|
|
5
|
+
### You are currently viewing the pre-release documentation for version 2.0.
|
|
6
|
+
## Click [here](https://github.com/ferrerojosh/nest-keycloak-connect/tree/v1.0) for the 1.0 stable release documentation.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+
|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+

|
|
17
|
+

|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
An adapter for [keycloak-nodejs-connect](https://github.com/keycloak/keycloak-nodejs-connect)
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- Protect your resources using [Keycloak's Authorization Services](https://www.keycloak.org/docs/latest/authorization_services/).
|
|
27
|
+
- Simply add `@Resource`, `@Scopes`, or `@Roles` in your controllers and you're good to go.
|
|
28
|
+
- Compatible with [Fastify](https://github.com/fastify/fastify) platform.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
### Yarn
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
yarn add nest-keycloak-connect keycloak-connect
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### NPM
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install nest-keycloak-connect keycloak-connect --save
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Getting Started
|
|
45
|
+
|
|
46
|
+
### Module registration
|
|
47
|
+
|
|
48
|
+
Registering the module:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
KeycloakConnectModule.register({
|
|
52
|
+
authServerUrl: 'http://localhost:8080', // might be http://localhost:8080/auth for older keycloak versions
|
|
53
|
+
realm: 'master',
|
|
54
|
+
clientId: 'my-nestjs-app',
|
|
55
|
+
secret: 'secret',
|
|
56
|
+
policyEnforcement: PolicyEnforcementMode.PERMISSIVE, // optional
|
|
57
|
+
tokenValidation: TokenValidation.ONLINE, // optional
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Async registration is also available:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
KeycloakConnectModule.registerAsync({
|
|
65
|
+
useExisting: KeycloakConfigService,
|
|
66
|
+
imports: [ConfigModule],
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### KeycloakConfigService
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { Injectable } from '@nestjs/common';
|
|
74
|
+
import {
|
|
75
|
+
KeycloakConnectOptions,
|
|
76
|
+
KeycloakConnectOptionsFactory,
|
|
77
|
+
PolicyEnforcementMode,
|
|
78
|
+
TokenValidation,
|
|
79
|
+
} from 'nest-keycloak-connect';
|
|
80
|
+
|
|
81
|
+
@Injectable()
|
|
82
|
+
export class KeycloakConfigService implements KeycloakConnectOptionsFactory {
|
|
83
|
+
createKeycloakConnectOptions(): KeycloakConnectOptions {
|
|
84
|
+
return {
|
|
85
|
+
// http://localhost:8080/auth for older keycloak versions
|
|
86
|
+
authServerUrl: 'http://localhost:8080',
|
|
87
|
+
realm: 'master',
|
|
88
|
+
clientId: 'my-nestjs-app',
|
|
89
|
+
secret: 'secret',
|
|
90
|
+
policyEnforcement: PolicyEnforcementMode.PERMISSIVE,
|
|
91
|
+
tokenValidation: TokenValidation.ONLINE,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
You can also register by just providing the `keycloak.json` path and an optional module configuration:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
KeycloakConnectModule.register(`./keycloak.json`, {
|
|
101
|
+
policyEnforcement: PolicyEnforcementMode.PERMISSIVE,
|
|
102
|
+
tokenValidation: TokenValidation.ONLINE,
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Guards
|
|
107
|
+
|
|
108
|
+
Register any of the guards either globally, or scoped in your controller.
|
|
109
|
+
|
|
110
|
+
#### Global registration using APP_GUARD token
|
|
111
|
+
|
|
112
|
+
**_NOTE: These are in order, see https://docs.nestjs.com/guards#binding-guards for more information._**
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
providers: [
|
|
116
|
+
{
|
|
117
|
+
provide: APP_GUARD,
|
|
118
|
+
useClass: AuthGuard,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
provide: APP_GUARD,
|
|
122
|
+
useClass: ResourceGuard,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
provide: APP_GUARD,
|
|
126
|
+
useClass: RoleGuard,
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### Scoped registration
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
@Controller('cats')
|
|
135
|
+
@UseGuards(AuthGuard, ResourceGuard)
|
|
136
|
+
export class CatsController {}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## What does these providers do ?
|
|
140
|
+
|
|
141
|
+
### AuthGuard
|
|
142
|
+
|
|
143
|
+
Adds an authentication guard, you can also have it scoped if you like (using regular `@UseGuards(AuthGuard)` in your controllers). By default, it will throw a 401 unauthorized when it is unable to verify the JWT token or `Bearer` header is missing.
|
|
144
|
+
|
|
145
|
+
### ResourceGuard
|
|
146
|
+
|
|
147
|
+
Adds a resource guard, which is permissive by default (can be configured see [options](#nest-keycloak-options)). Only controllers annotated with `@Resource` and methods with `@Scopes` are handled by this guard.
|
|
148
|
+
|
|
149
|
+
**_NOTE: This guard is not necessary if you are using role-based authorization exclusively. You can use role guard exclusively for that._**
|
|
150
|
+
|
|
151
|
+
### RoleGuard
|
|
152
|
+
|
|
153
|
+
Adds a role guard, **can only be used in conjunction with resource guard when enforcement policy is PERMISSIVE**, unless you only use role guard exclusively.
|
|
154
|
+
Permissive by default. Used by controller methods annotated with `@Roles` (matching can be configured)
|
|
155
|
+
|
|
156
|
+
## Configuring controllers
|
|
157
|
+
|
|
158
|
+
In your controllers, simply do:
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
import {
|
|
162
|
+
Resource,
|
|
163
|
+
Roles,
|
|
164
|
+
Scopes,
|
|
165
|
+
Public,
|
|
166
|
+
RoleMatchingMode,
|
|
167
|
+
} from 'nest-keycloak-connect';
|
|
168
|
+
import { Controller, Get, Delete, Put, Post, Param } from '@nestjs/common';
|
|
169
|
+
import { Product } from './product';
|
|
170
|
+
import { ProductService } from './product.service';
|
|
171
|
+
|
|
172
|
+
@Controller()
|
|
173
|
+
@Resource(Product.name)
|
|
174
|
+
export class ProductController {
|
|
175
|
+
constructor(private service: ProductService) {}
|
|
176
|
+
|
|
177
|
+
@Get()
|
|
178
|
+
@Public()
|
|
179
|
+
async findAll() {
|
|
180
|
+
return await this.service.findAll();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@Get()
|
|
184
|
+
@Roles({ roles: ['admin', 'other'] })
|
|
185
|
+
async findAllBarcodes() {
|
|
186
|
+
return await this.service.findAllBarcodes();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@Get(':code')
|
|
190
|
+
@Scopes('View')
|
|
191
|
+
async findByCode(@Param('code') code: string) {
|
|
192
|
+
return await this.service.findByCode(code);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@Post()
|
|
196
|
+
@Scopes('Create')
|
|
197
|
+
@ConditionalScopes((request, token) => {
|
|
198
|
+
if (token.hasRealmRole('sysadmin')) {
|
|
199
|
+
return ['Overwrite'];
|
|
200
|
+
}
|
|
201
|
+
return [];
|
|
202
|
+
})
|
|
203
|
+
async create(@Body() product: Product) {
|
|
204
|
+
return await this.service.create(product);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@Delete(':code')
|
|
208
|
+
@Scopes('Delete')
|
|
209
|
+
@Roles({ roles: ['admin', 'realm:sysadmin'], mode: RoleMatchingMode.ALL })
|
|
210
|
+
async deleteByCode(@Param('code') code: string) {
|
|
211
|
+
return await this.service.deleteByCode(code);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@Put(':code')
|
|
215
|
+
@Scopes('Edit')
|
|
216
|
+
async update(@Param('code') code: string, @Body() product: Product) {
|
|
217
|
+
return await this.service.update(code, product);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Decorators
|
|
223
|
+
|
|
224
|
+
Here is the decorators you can use in your controllers.
|
|
225
|
+
|
|
226
|
+
| Decorator | Description |
|
|
227
|
+
| ------------------ | --------------------------------------------------------------------------------------------------------- |
|
|
228
|
+
| @KeycloakUser | Retrieves the current Keycloak logged-in user. (must be per method, unless controller is request scoped.) |
|
|
229
|
+
| @AccessToken | Retrieves the access token used in the request |
|
|
230
|
+
| @ResolvedScopes | Retrieves the resolved scopes (used in @ConditionalScopes) |
|
|
231
|
+
| @EnforcerOptions | Keycloak enforcer options. |
|
|
232
|
+
| @Public | Allow any user to use the route. |
|
|
233
|
+
| @Resource | Keycloak application resource name. |
|
|
234
|
+
| @Scopes | Keycloak application scopes. |
|
|
235
|
+
| @ConditionalScopes | Conditional keycloak application scopes. |
|
|
236
|
+
| @Roles | Keycloak realm/application roles. |
|
|
237
|
+
|
|
238
|
+
## Multi tenant configuration
|
|
239
|
+
|
|
240
|
+
Setting up for multi-tenant is configured as an option in your configuration:
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
{
|
|
244
|
+
// Add /auth for older keycloak versions
|
|
245
|
+
authServerUrl: 'http://localhost:8180/', // will be used as fallback
|
|
246
|
+
clientId: 'nest-api', // will be used as fallback
|
|
247
|
+
secret: 'fallback', // will be used as fallback
|
|
248
|
+
multiTenant: {
|
|
249
|
+
resolveAlways: true,
|
|
250
|
+
realmResolver: (request) => {
|
|
251
|
+
return request.get('host').split('.')[0];
|
|
252
|
+
},
|
|
253
|
+
realmSecretResolver: (realm, request) => {
|
|
254
|
+
const secrets = { master: 'secret', slave: 'password' };
|
|
255
|
+
return secrets[realm];
|
|
256
|
+
},
|
|
257
|
+
realmClientIdResolver: (realm, request) => {
|
|
258
|
+
const clientIds = { master: 'angular-app', slave: 'vue-app' };
|
|
259
|
+
return clientIds[realm];
|
|
260
|
+
},
|
|
261
|
+
// note to add /auth for older keycloak versions
|
|
262
|
+
realmAuthServerUrlResolver: (realm, request) => {
|
|
263
|
+
const authServerUrls = { master: 'https://master.local/', slave: 'https://slave.local/' };
|
|
264
|
+
return authServerUrls[realm];
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Configuration options
|
|
271
|
+
|
|
272
|
+
### Keycloak Options
|
|
273
|
+
|
|
274
|
+
For Keycloak options, refer to the official [keycloak-connect](https://github.com/keycloak/keycloak-nodejs-connect/blob/main/middleware/auth-utils/config.js) library.
|
|
275
|
+
|
|
276
|
+
### Nest Keycloak Options
|
|
277
|
+
|
|
278
|
+
| Option | Description | Required | Default |
|
|
279
|
+
| ----------------- | ------------------------------------------------------------------------ | -------- | ------------ |
|
|
280
|
+
| cookieKey | Cookie Key | no | KEYCLOAK_JWT |
|
|
281
|
+
| policyEnforcement | Sets the policy enforcement mode | no | PERMISSIVE |
|
|
282
|
+
| tokenValidation | Sets the token validation method | no | ONLINE |
|
|
283
|
+
| multiTenant | Sets the options for [multi-tenant configuration](#multi-tenant-options) | no | - |
|
|
284
|
+
| roleMerge | Sets the merge mode for @Role decorator | no | OVERRIDE |
|
|
285
|
+
|
|
286
|
+
### Multi Tenant Options
|
|
287
|
+
|
|
288
|
+
| Option | Description | Required | Default |
|
|
289
|
+
| -------------------------- | ------------------------------------------------------------------------------------------------------- | -------- | ------- |
|
|
290
|
+
| resolveAlways | Option to always resolve the realm and secret. Disabled by default. | no | false |
|
|
291
|
+
| realmResolver | A function that passes a request (from respective platform i.e express or fastify) and returns a string | yes | - |
|
|
292
|
+
| realmSecretResolver | A function that passes the realm string, and an optional request and returns the secret string | no | - |
|
|
293
|
+
| realmAuthServerUrlResolver | A function that passes the realm string, and an optional request and returns the auth server url string | no | - |
|
|
294
|
+
| realmClientIdResolver | A function that passes the realm string, and an optional request and returns the client-id string | no | - |
|
|
295
|
+
|
|
296
|
+
## Example app
|
|
297
|
+
|
|
298
|
+
An [example application](example) is provided in the source code with both Keycloak Realm and Postman requests for you to experiment with.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Used internally, provides keycloak options for the Nest guards.
|
|
3
|
+
*/
|
|
4
|
+
export declare const KEYCLOAK_CONNECT_OPTIONS = "KEYCLOAK_CONNECT_OPTIONS";
|
|
5
|
+
/**
|
|
6
|
+
* Key for injecting a keycloak instance.
|
|
7
|
+
*/
|
|
8
|
+
export declare const KEYCLOAK_INSTANCE = "KEYCLOAK_INSTANCE";
|
|
9
|
+
/**
|
|
10
|
+
* Key for injecting a keycloak multi tenant service.
|
|
11
|
+
*/
|
|
12
|
+
export declare const KEYCLOAK_MULTITENANT_SERVICE = "KEYCLOAK_MULTITENANT_SERVICE";
|
|
13
|
+
/**
|
|
14
|
+
* Default cookie key.
|
|
15
|
+
*/
|
|
16
|
+
export declare const KEYCLOAK_COOKIE_DEFAULT = "KEYCLOAK_JWT";
|
|
17
|
+
/**
|
|
18
|
+
* Role matching mode.
|
|
19
|
+
*/
|
|
20
|
+
export declare enum RoleMatch {
|
|
21
|
+
/**
|
|
22
|
+
* Match all roles
|
|
23
|
+
*/
|
|
24
|
+
ALL = "all",
|
|
25
|
+
/**
|
|
26
|
+
* Match any roles
|
|
27
|
+
*/
|
|
28
|
+
ANY = "any"
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Policy enforcement mode.
|
|
32
|
+
*/
|
|
33
|
+
export declare enum PolicyEnforcementMode {
|
|
34
|
+
/**
|
|
35
|
+
* Deny all request when there is no matching resource.
|
|
36
|
+
*/
|
|
37
|
+
ENFORCING = "enforcing",
|
|
38
|
+
/**
|
|
39
|
+
* Allow all request even when there's no matching resource.
|
|
40
|
+
*/
|
|
41
|
+
PERMISSIVE = "permissive"
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Token validation methods.
|
|
45
|
+
*/
|
|
46
|
+
export declare enum TokenValidation {
|
|
47
|
+
/**
|
|
48
|
+
* The default validation method, performs live validation via Keycloak servers.
|
|
49
|
+
*/
|
|
50
|
+
ONLINE = "online",
|
|
51
|
+
/**
|
|
52
|
+
* Validate offline against the configured keycloak options.
|
|
53
|
+
*/
|
|
54
|
+
OFFLINE = "offline",
|
|
55
|
+
/**
|
|
56
|
+
* Does not check for any validation. Should only be used for special cases (i.e development, internal networks)
|
|
57
|
+
*/
|
|
58
|
+
NONE = "none"
|
|
59
|
+
}
|
|
60
|
+
export declare enum RoleMerge {
|
|
61
|
+
/**
|
|
62
|
+
* Overrides roles if defined both controller and handlers, with controller taking over.
|
|
63
|
+
*/
|
|
64
|
+
OVERRIDE = 0,
|
|
65
|
+
/**
|
|
66
|
+
* Merges all roles from both controller and handlers.
|
|
67
|
+
*/
|
|
68
|
+
ALL = 1
|
|
69
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RoleMerge = exports.TokenValidation = exports.PolicyEnforcementMode = exports.RoleMatch = exports.KEYCLOAK_COOKIE_DEFAULT = exports.KEYCLOAK_MULTITENANT_SERVICE = exports.KEYCLOAK_INSTANCE = exports.KEYCLOAK_CONNECT_OPTIONS = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Used internally, provides keycloak options for the Nest guards.
|
|
6
|
+
*/
|
|
7
|
+
exports.KEYCLOAK_CONNECT_OPTIONS = 'KEYCLOAK_CONNECT_OPTIONS';
|
|
8
|
+
/**
|
|
9
|
+
* Key for injecting a keycloak instance.
|
|
10
|
+
*/
|
|
11
|
+
exports.KEYCLOAK_INSTANCE = 'KEYCLOAK_INSTANCE';
|
|
12
|
+
/**
|
|
13
|
+
* Key for injecting a keycloak multi tenant service.
|
|
14
|
+
*/
|
|
15
|
+
exports.KEYCLOAK_MULTITENANT_SERVICE = 'KEYCLOAK_MULTITENANT_SERVICE';
|
|
16
|
+
/**
|
|
17
|
+
* Default cookie key.
|
|
18
|
+
*/
|
|
19
|
+
exports.KEYCLOAK_COOKIE_DEFAULT = 'KEYCLOAK_JWT';
|
|
20
|
+
/**
|
|
21
|
+
* Role matching mode.
|
|
22
|
+
*/
|
|
23
|
+
var RoleMatch;
|
|
24
|
+
(function (RoleMatch) {
|
|
25
|
+
/**
|
|
26
|
+
* Match all roles
|
|
27
|
+
*/
|
|
28
|
+
RoleMatch["ALL"] = "all";
|
|
29
|
+
/**
|
|
30
|
+
* Match any roles
|
|
31
|
+
*/
|
|
32
|
+
RoleMatch["ANY"] = "any";
|
|
33
|
+
})(RoleMatch || (exports.RoleMatch = RoleMatch = {}));
|
|
34
|
+
/**
|
|
35
|
+
* Policy enforcement mode.
|
|
36
|
+
*/
|
|
37
|
+
var PolicyEnforcementMode;
|
|
38
|
+
(function (PolicyEnforcementMode) {
|
|
39
|
+
/**
|
|
40
|
+
* Deny all request when there is no matching resource.
|
|
41
|
+
*/
|
|
42
|
+
PolicyEnforcementMode["ENFORCING"] = "enforcing";
|
|
43
|
+
/**
|
|
44
|
+
* Allow all request even when there's no matching resource.
|
|
45
|
+
*/
|
|
46
|
+
PolicyEnforcementMode["PERMISSIVE"] = "permissive";
|
|
47
|
+
})(PolicyEnforcementMode || (exports.PolicyEnforcementMode = PolicyEnforcementMode = {}));
|
|
48
|
+
/**
|
|
49
|
+
* Token validation methods.
|
|
50
|
+
*/
|
|
51
|
+
var TokenValidation;
|
|
52
|
+
(function (TokenValidation) {
|
|
53
|
+
/**
|
|
54
|
+
* The default validation method, performs live validation via Keycloak servers.
|
|
55
|
+
*/
|
|
56
|
+
TokenValidation["ONLINE"] = "online";
|
|
57
|
+
/**
|
|
58
|
+
* Validate offline against the configured keycloak options.
|
|
59
|
+
*/
|
|
60
|
+
TokenValidation["OFFLINE"] = "offline";
|
|
61
|
+
/**
|
|
62
|
+
* Does not check for any validation. Should only be used for special cases (i.e development, internal networks)
|
|
63
|
+
*/
|
|
64
|
+
TokenValidation["NONE"] = "none";
|
|
65
|
+
})(TokenValidation || (exports.TokenValidation = TokenValidation = {}));
|
|
66
|
+
var RoleMerge;
|
|
67
|
+
(function (RoleMerge) {
|
|
68
|
+
/**
|
|
69
|
+
* Overrides roles if defined both controller and handlers, with controller taking over.
|
|
70
|
+
*/
|
|
71
|
+
RoleMerge[RoleMerge["OVERRIDE"] = 0] = "OVERRIDE";
|
|
72
|
+
/**
|
|
73
|
+
* Merges all roles from both controller and handlers.
|
|
74
|
+
*/
|
|
75
|
+
RoleMerge[RoleMerge["ALL"] = 1] = "ALL";
|
|
76
|
+
})(RoleMerge || (exports.RoleMerge = RoleMerge = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AccessToken = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const internal_util_1 = require("../internal.util");
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves the currently used access token
|
|
8
|
+
* @since 2.0.0
|
|
9
|
+
*/
|
|
10
|
+
exports.AccessToken = (0, common_1.createParamDecorator)((data, ctx) => {
|
|
11
|
+
const [req] = (0, internal_util_1.extractRequest)(ctx);
|
|
12
|
+
return req.accessToken;
|
|
13
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as KeycloakConnect from 'keycloak-connect';
|
|
2
|
+
export declare const META_ENFORCER_OPTIONS = "enforcer-options";
|
|
3
|
+
/**
|
|
4
|
+
* Keycloak enforcer options
|
|
5
|
+
* @param opts - enforcer options
|
|
6
|
+
* @since 1.3.0
|
|
7
|
+
*/
|
|
8
|
+
export declare const EnforcerOptions: (opts: KeycloakConnect.EnforcerOptions) => import("@nestjs/common").CustomDecorator<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EnforcerOptions = exports.META_ENFORCER_OPTIONS = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.META_ENFORCER_OPTIONS = 'enforcer-options';
|
|
6
|
+
/**
|
|
7
|
+
* Keycloak enforcer options
|
|
8
|
+
* @param opts - enforcer options
|
|
9
|
+
* @since 1.3.0
|
|
10
|
+
*/
|
|
11
|
+
const EnforcerOptions = (opts) => (0, common_1.SetMetadata)(exports.META_ENFORCER_OPTIONS, opts);
|
|
12
|
+
exports.EnforcerOptions = EnforcerOptions;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KeycloakUser = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const internal_util_1 = require("../internal.util");
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves the current Keycloak logged-in user.
|
|
8
|
+
* @since 1.5.0
|
|
9
|
+
*/
|
|
10
|
+
exports.KeycloakUser = (0, common_1.createParamDecorator)((data, ctx) => {
|
|
11
|
+
const [req] = (0, internal_util_1.extractRequest)(ctx);
|
|
12
|
+
return req.user;
|
|
13
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const META_PUBLIC = "public";
|
|
2
|
+
/**
|
|
3
|
+
* Allows unauthorized traffic to enter the route.
|
|
4
|
+
* @since 1.2.0
|
|
5
|
+
* @param skipAuth attaches authorization header to user object when `false`, defaults to `true`
|
|
6
|
+
*/
|
|
7
|
+
export declare const Public: () => import("@nestjs/common").CustomDecorator<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Public = exports.META_PUBLIC = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.META_PUBLIC = 'public';
|
|
6
|
+
/**
|
|
7
|
+
* Allows unauthorized traffic to enter the route.
|
|
8
|
+
* @since 1.2.0
|
|
9
|
+
* @param skipAuth attaches authorization header to user object when `false`, defaults to `true`
|
|
10
|
+
*/
|
|
11
|
+
const Public = () => (0, common_1.SetMetadata)(exports.META_PUBLIC, true);
|
|
12
|
+
exports.Public = Public;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Resource = exports.META_RESOURCE = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.META_RESOURCE = 'resource';
|
|
6
|
+
/**
|
|
7
|
+
* Keycloak Resource.
|
|
8
|
+
* @param resource - name of resource
|
|
9
|
+
*/
|
|
10
|
+
const Resource = (resource) => (0, common_1.SetMetadata)(exports.META_RESOURCE, resource);
|
|
11
|
+
exports.Resource = Resource;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { RoleMatch } from '../constants';
|
|
2
|
+
export declare const META_ROLES = "roles";
|
|
3
|
+
export declare const META_ROLE_MATCHING_MODE = "role-matching-mode";
|
|
4
|
+
/**
|
|
5
|
+
* Keycloak user roles.
|
|
6
|
+
* @param roles - the roles to match
|
|
7
|
+
* @since 2.0.0
|
|
8
|
+
*/
|
|
9
|
+
export declare const Roles: (...roles: string[]) => import("@nestjs/common").CustomDecorator<string>;
|
|
10
|
+
export declare const RoleMatchingMode: (mode: RoleMatch) => import("@nestjs/common").CustomDecorator<string>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RoleMatchingMode = exports.Roles = exports.META_ROLE_MATCHING_MODE = exports.META_ROLES = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.META_ROLES = 'roles';
|
|
6
|
+
exports.META_ROLE_MATCHING_MODE = 'role-matching-mode';
|
|
7
|
+
/**
|
|
8
|
+
* Keycloak user roles.
|
|
9
|
+
* @param roles - the roles to match
|
|
10
|
+
* @since 2.0.0
|
|
11
|
+
*/
|
|
12
|
+
const Roles = (...roles) => (0, common_1.SetMetadata)(exports.META_ROLES, roles);
|
|
13
|
+
exports.Roles = Roles;
|
|
14
|
+
const RoleMatchingMode = (mode) => (0, common_1.SetMetadata)(exports.META_ROLE_MATCHING_MODE, mode);
|
|
15
|
+
exports.RoleMatchingMode = RoleMatchingMode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as KeycloakConnect from 'keycloak-connect';
|
|
2
|
+
export declare const META_SCOPES = "scopes";
|
|
3
|
+
export declare const META_CONDITIONAL_SCOPES = "conditional-scopes";
|
|
4
|
+
export type ConditionalScopeFn = (request: any, token: KeycloakConnect.Token) => string[];
|
|
5
|
+
/**
|
|
6
|
+
* Keycloak authorization scopes.
|
|
7
|
+
* @param scopes - scopes that are associated with the resource
|
|
8
|
+
*/
|
|
9
|
+
export declare const Scopes: (...scopes: string[]) => import("@nestjs/common").CustomDecorator<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Keycloak authorization conditional scopes.
|
|
12
|
+
* @param scopes - scopes that are associated with the resource depending on the conditions
|
|
13
|
+
*/
|
|
14
|
+
export declare const ConditionalScopes: (resolver: ConditionalScopeFn) => import("@nestjs/common").CustomDecorator<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Retrieves the resolved scopes.
|
|
17
|
+
* @since 1.5.0
|
|
18
|
+
*/
|
|
19
|
+
export declare const ResolvedScopes: (...dataOrPipes: unknown[]) => ParameterDecorator;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResolvedScopes = exports.ConditionalScopes = exports.Scopes = exports.META_CONDITIONAL_SCOPES = exports.META_SCOPES = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
exports.META_SCOPES = 'scopes';
|
|
6
|
+
exports.META_CONDITIONAL_SCOPES = 'conditional-scopes';
|
|
7
|
+
/**
|
|
8
|
+
* Keycloak authorization scopes.
|
|
9
|
+
* @param scopes - scopes that are associated with the resource
|
|
10
|
+
*/
|
|
11
|
+
const Scopes = (...scopes) => (0, common_1.SetMetadata)(exports.META_SCOPES, scopes);
|
|
12
|
+
exports.Scopes = Scopes;
|
|
13
|
+
/**
|
|
14
|
+
* Keycloak authorization conditional scopes.
|
|
15
|
+
* @param scopes - scopes that are associated with the resource depending on the conditions
|
|
16
|
+
*/
|
|
17
|
+
const ConditionalScopes = (resolver) => (0, common_1.SetMetadata)(exports.META_CONDITIONAL_SCOPES, resolver);
|
|
18
|
+
exports.ConditionalScopes = ConditionalScopes;
|
|
19
|
+
const common_2 = require("@nestjs/common");
|
|
20
|
+
const internal_util_1 = require("../internal.util");
|
|
21
|
+
/**
|
|
22
|
+
* Retrieves the resolved scopes.
|
|
23
|
+
* @since 1.5.0
|
|
24
|
+
*/
|
|
25
|
+
exports.ResolvedScopes = (0, common_2.createParamDecorator)((data, ctx) => {
|
|
26
|
+
const [req] = (0, internal_util_1.extractRequest)(ctx);
|
|
27
|
+
return req.scopes;
|
|
28
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import * as KeycloakConnect from 'keycloak-connect';
|
|
3
|
+
import { KeycloakConnectConfig } from '../interface/keycloak-connect-options.interface';
|
|
4
|
+
import { KeycloakMultiTenantService } from '../services/keycloak-multitenant.service';
|
|
5
|
+
/**
|
|
6
|
+
* An authentication guard. Will return a 401 unauthorized when it is unable to
|
|
7
|
+
* verify the JWT token or Bearer header is missing.
|
|
8
|
+
*/
|
|
9
|
+
export declare class AuthGuard implements CanActivate {
|
|
10
|
+
private singleTenant;
|
|
11
|
+
private keycloakOpts;
|
|
12
|
+
private multiTenant;
|
|
13
|
+
private readonly logger;
|
|
14
|
+
private readonly reflector;
|
|
15
|
+
constructor(singleTenant: KeycloakConnect.Keycloak, keycloakOpts: KeycloakConnectConfig, multiTenant: KeycloakMultiTenantService);
|
|
16
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
17
|
+
private validateToken;
|
|
18
|
+
private extractJwt;
|
|
19
|
+
}
|