@adatechnology/auth-keycloak 0.0.7 → 0.1.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/README.md +150 -48
- package/dist/index.d.ts +29 -2
- package/dist/index.js +225 -66
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -5,34 +5,36 @@ Módulo Keycloak para autenticação de clients e usuários, seguindo o padrão
|
|
|
5
5
|
Este pacote fornece um cliente leve para interagir com o Keycloak (obter/refresh de tokens, introspecção, userinfo)
|
|
6
6
|
e um interceptor opcional. O módulo foi projetado para ser usado junto ao `@adatechnology/http-client`.
|
|
7
7
|
|
|
8
|
-
Principais exportações
|
|
8
|
+
### Principais exportações
|
|
9
9
|
|
|
10
|
-
- `KeycloakModule` — módulo principal. Suporta `KeycloakModule.forRoot(config?)
|
|
11
|
-
- `KEYCLOAK_CLIENT` — provider token para injetar o cliente Keycloak (
|
|
12
|
-
- `KEYCLOAK_HTTP_INTERCEPTOR` — provider token para injetar o interceptor (
|
|
10
|
+
- `KeycloakModule` — módulo principal. Suporta `KeycloakModule.forRoot(config?)`.
|
|
11
|
+
- `KEYCLOAK_CLIENT` — provider token para injetar o cliente Keycloak (`@Inject(KEYCLOAK_CLIENT)`).
|
|
12
|
+
- `KEYCLOAK_HTTP_INTERCEPTOR` — provider token para injetar o interceptor (opcional).
|
|
13
|
+
- `BearerTokenGuard` — guard que valida o token Bearer via introspecção no Keycloak (401 em falha).
|
|
14
|
+
- `Roles` / `RolesGuard` — decorator e guard para autorização baseada em roles (403 em falha).
|
|
15
|
+
- `KeycloakError` — classe de erro tipada com `statusCode` e `details`.
|
|
13
16
|
|
|
14
|
-
Instalação
|
|
17
|
+
### Instalação
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
```bash
|
|
20
|
+
# Este pacote já declara dependências de workspace para http-client, logger e cache.
|
|
21
|
+
# Em um monorepo PNPM/Turbo os pacotes são resolvidos automaticamente.
|
|
22
|
+
```
|
|
19
23
|
|
|
20
|
-
|
|
24
|
+
### Uso básico
|
|
21
25
|
|
|
22
26
|
```ts
|
|
23
27
|
import { Module } from "@nestjs/common";
|
|
24
|
-
import { HttpModule } from "@adatechnology/http-client";
|
|
25
28
|
import { KeycloakModule } from "@adatechnology/auth-keycloak";
|
|
26
29
|
|
|
27
30
|
@Module({
|
|
28
31
|
imports: [
|
|
29
|
-
HttpModule.forRoot({ baseURL: "https://pokeapi.co/api/v2", timeout: 5000 }),
|
|
30
32
|
KeycloakModule.forRoot({
|
|
31
33
|
baseUrl: "https://keycloak.example.com",
|
|
32
|
-
realm: "
|
|
34
|
+
realm: "myrealm",
|
|
33
35
|
credentials: {
|
|
34
|
-
clientId: "
|
|
35
|
-
clientSecret: "
|
|
36
|
+
clientId: "my-client",
|
|
37
|
+
clientSecret: "my-secret",
|
|
36
38
|
grantType: "client_credentials",
|
|
37
39
|
},
|
|
38
40
|
}),
|
|
@@ -41,68 +43,154 @@ import { KeycloakModule } from "@adatechnology/auth-keycloak";
|
|
|
41
43
|
export class AppModule {}
|
|
42
44
|
```
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
### Injeção do cliente
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
```ts
|
|
49
|
+
import { Inject } from '@nestjs/common';
|
|
50
|
+
import { KEYCLOAK_CLIENT } from '@adatechnology/auth-keycloak';
|
|
51
|
+
import type { KeycloakClientInterface } from '@adatechnology/auth-keycloak';
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
constructor(
|
|
54
|
+
@Inject(KEYCLOAK_CLIENT) private readonly keycloakClient: KeycloakClientInterface,
|
|
55
|
+
) {}
|
|
56
|
+
```
|
|
52
57
|
|
|
53
|
-
API
|
|
58
|
+
### API do cliente
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
| Método | Descrição |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `getAccessToken()` | Obtém token com cache automático e deduplicação de requisições |
|
|
63
|
+
| `getTokenWithCredentials({ username, password })` | Login com credenciais (resource-owner password grant) |
|
|
64
|
+
| `refreshToken(refreshToken)` | Renova token e atualiza o cache interno |
|
|
65
|
+
| `validateToken(token)` | Introspecção via endpoint `/token/introspect` |
|
|
66
|
+
| `getUserInfo(token)` | Retorna claims via endpoint `/userinfo` |
|
|
67
|
+
| `clearTokenCache()` | Remove o token do cache (útil para forçar renovação) |
|
|
59
68
|
|
|
60
|
-
|
|
69
|
+
### Cache de token
|
|
70
|
+
|
|
71
|
+
O `KeycloakClient` usa `@adatechnology/cache` para armazenar o access token obtido via `client_credentials`.
|
|
72
|
+
Por padrão é criado um `InMemoryCacheProvider` local. Você pode substituir por Redis ou qualquer implementação
|
|
73
|
+
de `CacheProviderInterface` injetando o provider `CACHE_PROVIDER` no contexto do módulo:
|
|
61
74
|
|
|
62
75
|
```ts
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
import
|
|
76
|
+
import { Module } from "@nestjs/common";
|
|
77
|
+
import { CacheModule } from "@adatechnology/cache";
|
|
78
|
+
import { KeycloakModule } from "@adatechnology/auth-keycloak";
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
@Module({
|
|
81
|
+
imports: [
|
|
82
|
+
// Registra CACHE_PROVIDER como Redis — KeycloakClient o usará automaticamente
|
|
83
|
+
CacheModule.forRoot({
|
|
84
|
+
type: 'redis',
|
|
85
|
+
redis: { host: 'localhost', port: 6379 },
|
|
86
|
+
}),
|
|
87
|
+
KeycloakModule.forRoot({ ... }),
|
|
88
|
+
],
|
|
89
|
+
})
|
|
90
|
+
export class AppModule {}
|
|
68
91
|
```
|
|
69
92
|
|
|
70
|
-
|
|
93
|
+
Se `CACHE_PROVIDER` não for registrado no módulo, o `KeycloakClient` cria um `InMemoryCacheProvider`
|
|
94
|
+
interno sem necessidade de configuração adicional.
|
|
71
95
|
|
|
72
|
-
|
|
73
|
-
|
|
96
|
+
O TTL do cache é derivado do campo `expires_in` do token (com 60 segundos de margem). Você pode
|
|
97
|
+
sobrescrever com a opção `tokenCacheTtl` (em **milissegundos**):
|
|
74
98
|
|
|
75
|
-
|
|
99
|
+
```ts
|
|
100
|
+
KeycloakModule.forRoot({
|
|
101
|
+
...
|
|
102
|
+
tokenCacheTtl: 60_000, // força TTL de 60 s independente do token
|
|
103
|
+
})
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Propagação de contexto de log (cascade)
|
|
76
107
|
|
|
77
|
-
O
|
|
108
|
+
O cliente lê o `logContext` do `AsyncLocalStorage` da lib `@adatechnology/logger`. Para que os logs
|
|
109
|
+
de downstream (keycloak → cache) mostrem `className.methodName` da origem correta, use `runWithContext`
|
|
110
|
+
no controller:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
import { getContext, runWithContext } from '@adatechnology/logger';
|
|
114
|
+
|
|
115
|
+
// No controller
|
|
116
|
+
private withCtx<T>(logContext: object, fn: () => Promise<T>): Promise<T> {
|
|
117
|
+
return runWithContext({ ...(getContext() ?? {}), logContext }, fn);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async getToken() {
|
|
121
|
+
const logContext = { className: 'MyController', methodName: 'getToken' };
|
|
122
|
+
return this.withCtx(logContext, () => this.keycloakService.getAccessToken());
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Resultado no log:
|
|
127
|
+
```
|
|
128
|
+
[MyController.getToken][KeycloakClient.getAccessToken] → cache miss → request token
|
|
129
|
+
[MyController.getToken][InMemoryCacheProvider.set] → token cached
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### BearerTokenGuard — autenticação B2B via introspecção
|
|
133
|
+
|
|
134
|
+
Valida que o header `Authorization: Bearer <token>` contém um token ativo chamando
|
|
135
|
+
`POST /token/introspect` no Keycloak. Use sempre em conjunto com `RolesGuard` em rotas B2B.
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { Controller, Headers, Post, UseGuards } from "@nestjs/common";
|
|
139
|
+
import { BearerTokenGuard, Roles, RolesGuard } from "@adatechnology/auth-keycloak";
|
|
140
|
+
|
|
141
|
+
@Controller("orders")
|
|
142
|
+
export class OrdersController {
|
|
143
|
+
@Post()
|
|
144
|
+
@Roles("manage-requests")
|
|
145
|
+
@UseGuards(BearerTokenGuard, RolesGuard)
|
|
146
|
+
create(@Headers("x-user-id") keycloakId: string) {}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Por que dois guards em sequência?**
|
|
151
|
+
|
|
152
|
+
| Guard | Mecanismo | HTTP? | Falha |
|
|
153
|
+
|---|---|---|---|
|
|
154
|
+
| `BearerTokenGuard` | `POST /token/introspect` ao Keycloak | Sim | 401 — token inativo/expirado/forjado |
|
|
155
|
+
| `RolesGuard` | Decode local do payload JWT | Não | 403 — permissão insuficiente |
|
|
156
|
+
|
|
157
|
+
O `RolesGuard` sozinho **não é seguro** para autenticação: ele apenas decodifica o payload JWT
|
|
158
|
+
sem verificar a assinatura, o que significa que um token forjado passaria. O `BearerTokenGuard`
|
|
159
|
+
é quem garante autenticidade via introspecção.
|
|
160
|
+
|
|
161
|
+
### Autorização com @Roles
|
|
78
162
|
|
|
79
163
|
```ts
|
|
80
164
|
import { Controller, Get, UseGuards } from "@nestjs/common";
|
|
81
|
-
import { Roles } from "@adatechnology/auth-keycloak";
|
|
82
|
-
import { RolesGuard } from "@adatechnology/auth-keycloak";
|
|
165
|
+
import { Roles, RolesGuard } from "@adatechnology/auth-keycloak";
|
|
83
166
|
|
|
84
167
|
@Controller("secure")
|
|
85
|
-
@UseGuards(RolesGuard)
|
|
86
168
|
export class SecureController {
|
|
169
|
+
@Get("public")
|
|
170
|
+
@UseGuards(RolesGuard)
|
|
171
|
+
public() {
|
|
172
|
+
return { ok: true };
|
|
173
|
+
}
|
|
174
|
+
|
|
87
175
|
@Get("admin")
|
|
88
|
-
@
|
|
176
|
+
@UseGuards(RolesGuard)
|
|
177
|
+
@Roles("admin")
|
|
89
178
|
adminOnly() {
|
|
90
179
|
return { ok: true };
|
|
91
180
|
}
|
|
92
181
|
|
|
93
182
|
@Get("team")
|
|
94
|
-
@
|
|
183
|
+
@UseGuards(RolesGuard)
|
|
184
|
+
@Roles({ roles: ["manager", "lead"], mode: "all" }) // AND — requer ambas as roles
|
|
95
185
|
teamOnly() {
|
|
96
186
|
return { ok: true };
|
|
97
187
|
}
|
|
98
188
|
}
|
|
99
189
|
```
|
|
100
190
|
|
|
101
|
-
O `RolesGuard` extrai roles
|
|
102
|
-
|
|
103
|
-
## Erros
|
|
191
|
+
O `RolesGuard` extrai roles de `realm_access.roles` e `resource_access[clientId].roles` do JWT.
|
|
104
192
|
|
|
105
|
-
|
|
193
|
+
### Tratamento de erros
|
|
106
194
|
|
|
107
195
|
```ts
|
|
108
196
|
import { KeycloakError } from "@adatechnology/auth-keycloak";
|
|
@@ -111,17 +199,31 @@ try {
|
|
|
111
199
|
await keycloakClient.getUserInfo(token);
|
|
112
200
|
} catch (e) {
|
|
113
201
|
if (e instanceof KeycloakError) {
|
|
114
|
-
|
|
115
|
-
console.error(e.statusCode, e.details);
|
|
202
|
+
console.error(e.statusCode, e.details, e.keycloakError);
|
|
116
203
|
}
|
|
117
204
|
throw e;
|
|
118
205
|
}
|
|
119
206
|
```
|
|
120
207
|
|
|
121
|
-
|
|
208
|
+
### Variáveis de ambiente (referência)
|
|
209
|
+
|
|
210
|
+
| Variável | Padrão |
|
|
211
|
+
|---|---|
|
|
212
|
+
| `KEYCLOAK_BASE_URL` | `http://localhost:8081` |
|
|
213
|
+
| `KEYCLOAK_REALM` | `BACKEND` |
|
|
214
|
+
| `KEYCLOAK_CLIENT_ID` | `backend-api` |
|
|
215
|
+
| `KEYCLOAK_CLIENT_SECRET` | `backend-api-secret` |
|
|
216
|
+
|
|
217
|
+
### Notas
|
|
218
|
+
|
|
219
|
+
- Este módulo depende de `@adatechnology/http-client` para chamadas HTTP ao Keycloak.
|
|
220
|
+
- O interceptor `KeycloakHttpInterceptor` pode ser registrado como `APP_INTERCEPTOR` para integração global.
|
|
221
|
+
- `clearTokenCache()` é assíncrono desde a versão `0.0.7` (retorna `Promise<void>`).
|
|
222
|
+
|
|
223
|
+
### Contribuições
|
|
122
224
|
|
|
123
225
|
Relate issues/PRs no repositório principal. Mantenha compatibilidade com o padrão usado pelo `HttpModule`.
|
|
124
226
|
|
|
125
|
-
Licença
|
|
227
|
+
### Licença
|
|
126
228
|
|
|
127
229
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as _nestjs_common from '@nestjs/common';
|
|
2
2
|
import { DynamicModule, CanActivate, ExecutionContext } from '@nestjs/common';
|
|
3
3
|
import { AxiosRequestConfig, AxiosInstance } from 'axios';
|
|
4
|
+
import { LoggerProviderInterface } from '@adatechnology/logger';
|
|
4
5
|
import { Reflector } from '@nestjs/core';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -75,7 +76,7 @@ interface KeycloakClientInterface {
|
|
|
75
76
|
/**
|
|
76
77
|
* Clear the internal access token cache maintained by the client.
|
|
77
78
|
*/
|
|
78
|
-
clearTokenCache(): void
|
|
79
|
+
clearTokenCache(): Promise<void>;
|
|
79
80
|
}
|
|
80
81
|
/**
|
|
81
82
|
* Provider-facing interface type to be used when injecting the keycloak provider token.
|
|
@@ -87,6 +88,32 @@ declare class KeycloakModule {
|
|
|
87
88
|
static forRoot(config: KeycloakConfig, httpConfig?: AxiosRequestConfig | AxiosInstance): DynamicModule;
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Guard that validates the Bearer token in the Authorization header via
|
|
93
|
+
* Keycloak token introspection (POST /token/introspect).
|
|
94
|
+
*
|
|
95
|
+
* Use together with RolesGuard for B2B (service-to-service) routes that trust
|
|
96
|
+
* an X-User-Id header injected by an upstream authenticated service:
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```ts
|
|
100
|
+
* @Roles('manage-requests')
|
|
101
|
+
* @UseGuards(BearerTokenGuard, RolesGuard)
|
|
102
|
+
* async create(@Headers('x-user-id') keycloakId: string) {}
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* Execution order:
|
|
106
|
+
* 1. BearerTokenGuard — validates token is active (HTTP → Keycloak) → 401 on failure
|
|
107
|
+
* 2. RolesGuard — checks roles from decoded JWT payload (local) → 403 on failure
|
|
108
|
+
*/
|
|
109
|
+
declare class BearerTokenGuard implements CanActivate {
|
|
110
|
+
private readonly keycloakClient?;
|
|
111
|
+
private readonly logger?;
|
|
112
|
+
constructor(keycloakClient?: KeycloakClientInterface, logger?: LoggerProviderInterface);
|
|
113
|
+
private log;
|
|
114
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
115
|
+
}
|
|
116
|
+
|
|
90
117
|
declare const KEYCLOAK_CONFIG = "KEYCLOAK_CONFIG";
|
|
91
118
|
declare const KEYCLOAK_CLIENT = "KEYCLOAK_CLIENT";
|
|
92
119
|
declare const KEYCLOAK_HTTP_INTERCEPTOR = "KEYCLOAK_HTTP_INTERCEPTOR";
|
|
@@ -129,4 +156,4 @@ declare class KeycloakError extends Error {
|
|
|
129
156
|
});
|
|
130
157
|
}
|
|
131
158
|
|
|
132
|
-
export { KEYCLOAK_CLIENT, KEYCLOAK_CONFIG, KEYCLOAK_HTTP_INTERCEPTOR, KEYCLOAK_PROVIDER, type KeycloakClientInterface, type KeycloakConfig, KeycloakError, KeycloakModule, type KeycloakProviderInterface, type KeycloakTokenResponse, Roles, RolesGuard };
|
|
159
|
+
export { BearerTokenGuard, KEYCLOAK_CLIENT, KEYCLOAK_CONFIG, KEYCLOAK_HTTP_INTERCEPTOR, KEYCLOAK_PROVIDER, type KeycloakClientInterface, type KeycloakConfig, KeycloakError, KeycloakModule, type KeycloakProviderInterface, type KeycloakTokenResponse, Roles, RolesGuard };
|
package/dist/index.js
CHANGED
|
@@ -68,7 +68,7 @@ var require_base_app_error = __commonJS({
|
|
|
68
68
|
"use strict";
|
|
69
69
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
70
70
|
exports2.BaseAppError = void 0;
|
|
71
|
-
var
|
|
71
|
+
var BaseAppError3 = class extends Error {
|
|
72
72
|
code;
|
|
73
73
|
status;
|
|
74
74
|
context;
|
|
@@ -83,7 +83,7 @@ var require_base_app_error = __commonJS({
|
|
|
83
83
|
(_a = capturable.captureStackTrace) == null ? void 0 : _a.call(capturable, this, this.constructor);
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
|
-
exports2.BaseAppError =
|
|
86
|
+
exports2.BaseAppError = BaseAppError3;
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
89
|
|
|
@@ -268,6 +268,7 @@ var require_dist = __commonJS({
|
|
|
268
268
|
// src/index.ts
|
|
269
269
|
var index_exports = {};
|
|
270
270
|
__export(index_exports, {
|
|
271
|
+
BearerTokenGuard: () => BearerTokenGuard,
|
|
271
272
|
KEYCLOAK_CLIENT: () => KEYCLOAK_CLIENT,
|
|
272
273
|
KEYCLOAK_CONFIG: () => KEYCLOAK_CONFIG,
|
|
273
274
|
KEYCLOAK_HTTP_INTERCEPTOR: () => KEYCLOAK_HTTP_INTERCEPTOR,
|
|
@@ -280,15 +281,176 @@ __export(index_exports, {
|
|
|
280
281
|
module.exports = __toCommonJS(index_exports);
|
|
281
282
|
|
|
282
283
|
// src/keycloak.module.ts
|
|
283
|
-
var
|
|
284
|
+
var import_common6 = require("@nestjs/common");
|
|
284
285
|
var import_core2 = require("@nestjs/core");
|
|
285
|
-
var
|
|
286
|
-
var
|
|
286
|
+
var import_http_client3 = require("@adatechnology/http-client");
|
|
287
|
+
var import_logger3 = require("@adatechnology/logger");
|
|
288
|
+
var import_cache3 = require("@adatechnology/cache");
|
|
287
289
|
|
|
288
|
-
// src/
|
|
290
|
+
// src/bearer-token.guard.ts
|
|
289
291
|
var import_common = require("@nestjs/common");
|
|
290
|
-
var import_http_client = require("@adatechnology/http-client");
|
|
291
292
|
var import_logger = require("@adatechnology/logger");
|
|
293
|
+
var import_http_client = require("@adatechnology/http-client");
|
|
294
|
+
var import_shared = __toESM(require_dist());
|
|
295
|
+
|
|
296
|
+
// src/keycloak.token.ts
|
|
297
|
+
var KEYCLOAK_CONFIG = "KEYCLOAK_CONFIG";
|
|
298
|
+
var KEYCLOAK_CLIENT = "KEYCLOAK_CLIENT";
|
|
299
|
+
var KEYCLOAK_HTTP_INTERCEPTOR = "KEYCLOAK_HTTP_INTERCEPTOR";
|
|
300
|
+
var KEYCLOAK_PROVIDER = "KEYCLOAK_PROVIDER";
|
|
301
|
+
|
|
302
|
+
// package.json
|
|
303
|
+
var package_default = {
|
|
304
|
+
name: "@adatechnology/auth-keycloak",
|
|
305
|
+
version: "0.1.0",
|
|
306
|
+
publishConfig: {
|
|
307
|
+
access: "public"
|
|
308
|
+
},
|
|
309
|
+
main: "dist/index.js",
|
|
310
|
+
module: "dist/index.mjs",
|
|
311
|
+
types: "dist/index.d.ts",
|
|
312
|
+
files: [
|
|
313
|
+
"dist"
|
|
314
|
+
],
|
|
315
|
+
scripts: {
|
|
316
|
+
build: "rm -rf dist && tsup",
|
|
317
|
+
"build:watch": "tsup --watch",
|
|
318
|
+
check: "tsc -p tsconfig.json --noEmit",
|
|
319
|
+
test: 'echo "no tests"'
|
|
320
|
+
},
|
|
321
|
+
dependencies: {
|
|
322
|
+
"@adatechnology/cache": "workspace:*",
|
|
323
|
+
"@adatechnology/http-client": "workspace:*",
|
|
324
|
+
"@adatechnology/logger": "workspace:*"
|
|
325
|
+
},
|
|
326
|
+
peerDependencies: {
|
|
327
|
+
"@nestjs/common": "^11.0.16",
|
|
328
|
+
"@nestjs/core": "^11"
|
|
329
|
+
},
|
|
330
|
+
devDependencies: {
|
|
331
|
+
"@adatechnology/shared": "workspace:*",
|
|
332
|
+
"@esbuild-plugins/tsconfig-paths": "^0.1.2",
|
|
333
|
+
tsup: "^8.5.1",
|
|
334
|
+
typescript: "^5.2.0"
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// src/keycloak.constants.ts
|
|
339
|
+
var LIB_NAME = package_default.name;
|
|
340
|
+
var LIB_VERSION = package_default.version;
|
|
341
|
+
var TOKEN_CACHE_KEY = "keycloak:access_token";
|
|
342
|
+
var LOG_CONTEXT = {
|
|
343
|
+
KEYCLOAK_CLIENT: "KeycloakClient",
|
|
344
|
+
BEARER_TOKEN_GUARD: "BearerTokenGuard"
|
|
345
|
+
};
|
|
346
|
+
var HTTP_STATUS = {
|
|
347
|
+
UNAUTHORIZED: 401,
|
|
348
|
+
FORBIDDEN: 403
|
|
349
|
+
};
|
|
350
|
+
var BEARER_ERROR_CODE = {
|
|
351
|
+
MISSING_TOKEN: "UNAUTHORIZED_MISSING_TOKEN",
|
|
352
|
+
KEYCLOAK_NOT_CONFIGURED: "UNAUTHORIZED_KEYCLOAK_NOT_CONFIGURED",
|
|
353
|
+
TOKEN_VALIDATION_FAILED: "UNAUTHORIZED_TOKEN_VALIDATION_FAILED",
|
|
354
|
+
INACTIVE_TOKEN: "UNAUTHORIZED_INACTIVE_TOKEN"
|
|
355
|
+
};
|
|
356
|
+
var ROLES_ERROR_CODE = {
|
|
357
|
+
MISSING_TOKEN: "FORBIDDEN_MISSING_TOKEN",
|
|
358
|
+
INSUFFICIENT_ROLES: "FORBIDDEN_INSUFFICIENT_ROLES"
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// src/bearer-token.guard.ts
|
|
362
|
+
var BearerTokenGuard = class {
|
|
363
|
+
constructor(keycloakClient, logger) {
|
|
364
|
+
this.keycloakClient = keycloakClient;
|
|
365
|
+
this.logger = logger;
|
|
366
|
+
}
|
|
367
|
+
log(level, message, libMethod, meta) {
|
|
368
|
+
if (!this.logger) return;
|
|
369
|
+
const loggerCtx = (0, import_logger.getContext)();
|
|
370
|
+
const httpCtx = (0, import_http_client.getHttpRequestContext)();
|
|
371
|
+
const logContext = loggerCtx == null ? void 0 : loggerCtx.logContext;
|
|
372
|
+
const requestId = (loggerCtx == null ? void 0 : loggerCtx.requestId) ?? (httpCtx == null ? void 0 : httpCtx.requestId);
|
|
373
|
+
const source = (logContext == null ? void 0 : logContext.className) && (logContext == null ? void 0 : logContext.methodName) ? `${logContext.className}.${logContext.methodName}` : (httpCtx == null ? void 0 : httpCtx.className) && (httpCtx == null ? void 0 : httpCtx.methodName) ? `${httpCtx.className}.${httpCtx.methodName}` : void 0;
|
|
374
|
+
const payload = {
|
|
375
|
+
message,
|
|
376
|
+
context: LOG_CONTEXT.BEARER_TOKEN_GUARD,
|
|
377
|
+
lib: LIB_NAME,
|
|
378
|
+
libVersion: LIB_VERSION,
|
|
379
|
+
libMethod,
|
|
380
|
+
source,
|
|
381
|
+
requestId,
|
|
382
|
+
meta
|
|
383
|
+
};
|
|
384
|
+
if (level === "debug") this.logger.debug(payload);
|
|
385
|
+
else if (level === "info") this.logger.info(payload);
|
|
386
|
+
else if (level === "warn") this.logger.warn(payload);
|
|
387
|
+
else if (level === "error") this.logger.error(payload);
|
|
388
|
+
}
|
|
389
|
+
async canActivate(context) {
|
|
390
|
+
var _a, _b;
|
|
391
|
+
const method = "canActivate";
|
|
392
|
+
this.log("debug", `${method} - Start`, method);
|
|
393
|
+
const request = context.switchToHttp().getRequest();
|
|
394
|
+
const authorization = ((_a = request.headers) == null ? void 0 : _a.authorization) ?? ((_b = request.headers) == null ? void 0 : _b.Authorization);
|
|
395
|
+
if (!(authorization == null ? void 0 : authorization.startsWith("Bearer "))) {
|
|
396
|
+
this.log("warn", `${method} - Missing or invalid Authorization header`, method);
|
|
397
|
+
throw new import_shared.BaseAppError({
|
|
398
|
+
message: "Missing or invalid Authorization header",
|
|
399
|
+
status: HTTP_STATUS.UNAUTHORIZED,
|
|
400
|
+
code: BEARER_ERROR_CODE.MISSING_TOKEN,
|
|
401
|
+
context: {}
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
if (!this.keycloakClient) {
|
|
405
|
+
this.log("error", `${method} - Keycloak client not configured`, method);
|
|
406
|
+
throw new import_shared.BaseAppError({
|
|
407
|
+
message: "Keycloak client not configured",
|
|
408
|
+
status: HTTP_STATUS.UNAUTHORIZED,
|
|
409
|
+
code: BEARER_ERROR_CODE.KEYCLOAK_NOT_CONFIGURED,
|
|
410
|
+
context: {}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
const token = authorization.slice(7);
|
|
414
|
+
let isValid;
|
|
415
|
+
try {
|
|
416
|
+
isValid = await this.keycloakClient.validateToken(token);
|
|
417
|
+
} catch (err) {
|
|
418
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
419
|
+
this.log("error", `${method} - Token validation failed`, method, { detail });
|
|
420
|
+
throw new import_shared.BaseAppError({
|
|
421
|
+
message: "Token validation failed",
|
|
422
|
+
status: HTTP_STATUS.UNAUTHORIZED,
|
|
423
|
+
code: BEARER_ERROR_CODE.TOKEN_VALIDATION_FAILED,
|
|
424
|
+
context: { detail }
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
if (!isValid) {
|
|
428
|
+
this.log("warn", `${method} - Inactive or expired token`, method);
|
|
429
|
+
throw new import_shared.BaseAppError({
|
|
430
|
+
message: "Inactive or expired token",
|
|
431
|
+
status: HTTP_STATUS.UNAUTHORIZED,
|
|
432
|
+
code: BEARER_ERROR_CODE.INACTIVE_TOKEN,
|
|
433
|
+
context: {}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
this.log("debug", `${method} - Token valid`, method);
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
BearerTokenGuard = __decorateClass([
|
|
441
|
+
(0, import_common.Injectable)(),
|
|
442
|
+
__decorateParam(0, (0, import_common.Optional)()),
|
|
443
|
+
__decorateParam(0, (0, import_common.Inject)(KEYCLOAK_CLIENT)),
|
|
444
|
+
__decorateParam(1, (0, import_common.Optional)()),
|
|
445
|
+
__decorateParam(1, (0, import_common.Inject)(import_logger.LOGGER_PROVIDER))
|
|
446
|
+
], BearerTokenGuard);
|
|
447
|
+
|
|
448
|
+
// src/keycloak.client.ts
|
|
449
|
+
var import_common2 = require("@nestjs/common");
|
|
450
|
+
var import_http_client2 = require("@adatechnology/http-client");
|
|
451
|
+
var import_logger2 = require("@adatechnology/logger");
|
|
452
|
+
var import_cache = require("@adatechnology/cache");
|
|
453
|
+
var import_cache2 = require("@adatechnology/cache");
|
|
292
454
|
|
|
293
455
|
// src/errors/keycloak-error.ts
|
|
294
456
|
var KeycloakError = class _KeycloakError extends Error {
|
|
@@ -306,8 +468,6 @@ var KeycloakError = class _KeycloakError extends Error {
|
|
|
306
468
|
};
|
|
307
469
|
|
|
308
470
|
// src/keycloak.client.ts
|
|
309
|
-
var LIB_NAME = "@adatechnology/auth-keycloak";
|
|
310
|
-
var LIB_VERSION = "0.0.2";
|
|
311
471
|
function extractErrorInfo(err) {
|
|
312
472
|
var _a, _b, _c, _d, _e;
|
|
313
473
|
const statusCode = (err == null ? void 0 : err.status) ?? ((_a = err == null ? void 0 : err.response) == null ? void 0 : _a.status);
|
|
@@ -333,21 +493,24 @@ function extractErrorInfo(err) {
|
|
|
333
493
|
};
|
|
334
494
|
}
|
|
335
495
|
var KeycloakClient = class {
|
|
336
|
-
constructor(config, httpProvider, logger) {
|
|
496
|
+
constructor(config, httpProvider, logger, cacheProvider) {
|
|
337
497
|
this.config = config;
|
|
338
498
|
this.httpProvider = httpProvider;
|
|
339
499
|
this.logger = logger;
|
|
500
|
+
this.cacheProvider = cacheProvider ?? new import_cache.InMemoryCacheProvider(logger);
|
|
340
501
|
}
|
|
341
|
-
|
|
502
|
+
cacheProvider;
|
|
342
503
|
tokenPromise = null;
|
|
343
504
|
log(level, message, libMethod, meta) {
|
|
344
505
|
if (!this.logger) return;
|
|
345
|
-
const
|
|
346
|
-
const
|
|
347
|
-
const
|
|
506
|
+
const loggerCtx = (0, import_logger2.getContext)();
|
|
507
|
+
const httpCtx = (0, import_http_client2.getHttpRequestContext)();
|
|
508
|
+
const logContext = loggerCtx == null ? void 0 : loggerCtx.logContext;
|
|
509
|
+
const requestId = (loggerCtx == null ? void 0 : loggerCtx.requestId) ?? (httpCtx == null ? void 0 : httpCtx.requestId);
|
|
510
|
+
const source = (logContext == null ? void 0 : logContext.className) && (logContext == null ? void 0 : logContext.methodName) ? `${logContext.className}.${logContext.methodName}` : (httpCtx == null ? void 0 : httpCtx.className) && (httpCtx == null ? void 0 : httpCtx.methodName) ? `${httpCtx.className}.${httpCtx.methodName}` : void 0;
|
|
348
511
|
const payload = {
|
|
349
512
|
message,
|
|
350
|
-
context:
|
|
513
|
+
context: LOG_CONTEXT.KEYCLOAK_CLIENT,
|
|
351
514
|
lib: LIB_NAME,
|
|
352
515
|
libVersion: LIB_VERSION,
|
|
353
516
|
libMethod,
|
|
@@ -363,10 +526,10 @@ var KeycloakClient = class {
|
|
|
363
526
|
async getAccessToken() {
|
|
364
527
|
const method = "getAccessToken";
|
|
365
528
|
this.log("debug", `${method} - Start`, method);
|
|
366
|
-
const
|
|
367
|
-
if (
|
|
529
|
+
const cached = await this.cacheProvider.get(TOKEN_CACHE_KEY);
|
|
530
|
+
if (cached) {
|
|
368
531
|
this.log("debug", `${method} - Returning cached token`, method);
|
|
369
|
-
return
|
|
532
|
+
return cached;
|
|
370
533
|
}
|
|
371
534
|
if (this.tokenPromise) {
|
|
372
535
|
this.log("debug", `${method} - Waiting for existing token request`, method);
|
|
@@ -375,8 +538,8 @@ var KeycloakClient = class {
|
|
|
375
538
|
this.tokenPromise = (async () => {
|
|
376
539
|
try {
|
|
377
540
|
const tokenResponse = await this.requestToken();
|
|
378
|
-
const
|
|
379
|
-
this.
|
|
541
|
+
const ttlSeconds = this.config.tokenCacheTtl ? Math.floor(this.config.tokenCacheTtl / 1e3) : tokenResponse.expires_in - 60;
|
|
542
|
+
await this.cacheProvider.set(TOKEN_CACHE_KEY, tokenResponse.access_token, ttlSeconds);
|
|
380
543
|
this.log("debug", `${method} - Token obtained and cached`, method);
|
|
381
544
|
return tokenResponse.access_token;
|
|
382
545
|
} finally {
|
|
@@ -406,7 +569,7 @@ var KeycloakClient = class {
|
|
|
406
569
|
data: body,
|
|
407
570
|
config: {
|
|
408
571
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
409
|
-
logContext: { className:
|
|
572
|
+
logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
|
|
410
573
|
}
|
|
411
574
|
});
|
|
412
575
|
this.log("info", `${method} - Success for user: ${username}`, method);
|
|
@@ -444,7 +607,7 @@ var KeycloakClient = class {
|
|
|
444
607
|
data,
|
|
445
608
|
config: {
|
|
446
609
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
447
|
-
logContext: { className:
|
|
610
|
+
logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
|
|
448
611
|
}
|
|
449
612
|
});
|
|
450
613
|
this.log("debug", `${method} - Success`, method);
|
|
@@ -476,11 +639,11 @@ var KeycloakClient = class {
|
|
|
476
639
|
data,
|
|
477
640
|
config: {
|
|
478
641
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
479
|
-
logContext: { className:
|
|
642
|
+
logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
|
|
480
643
|
}
|
|
481
644
|
});
|
|
482
|
-
const
|
|
483
|
-
this.
|
|
645
|
+
const ttlSeconds = this.config.tokenCacheTtl ? Math.floor(this.config.tokenCacheTtl / 1e3) : response.data.expires_in - 60;
|
|
646
|
+
await this.cacheProvider.set(TOKEN_CACHE_KEY, response.data.access_token, ttlSeconds);
|
|
484
647
|
this.log("debug", `${method} - Success`, method);
|
|
485
648
|
return response.data;
|
|
486
649
|
} catch (err) {
|
|
@@ -510,7 +673,7 @@ var KeycloakClient = class {
|
|
|
510
673
|
data,
|
|
511
674
|
config: {
|
|
512
675
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
513
|
-
logContext: { className:
|
|
676
|
+
logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
|
|
514
677
|
}
|
|
515
678
|
});
|
|
516
679
|
const active = ((_a = response.data) == null ? void 0 : _a.active) === true;
|
|
@@ -535,7 +698,7 @@ var KeycloakClient = class {
|
|
|
535
698
|
url: userInfoUrl,
|
|
536
699
|
config: {
|
|
537
700
|
headers: { Authorization: `Bearer ${token}` },
|
|
538
|
-
logContext: { className:
|
|
701
|
+
logContext: { className: LOG_CONTEXT.KEYCLOAK_CLIENT, methodName: method }
|
|
539
702
|
}
|
|
540
703
|
});
|
|
541
704
|
this.log("debug", `${method} - Success`, method);
|
|
@@ -550,12 +713,8 @@ var KeycloakClient = class {
|
|
|
550
713
|
});
|
|
551
714
|
}
|
|
552
715
|
}
|
|
553
|
-
clearTokenCache() {
|
|
554
|
-
this.
|
|
555
|
-
}
|
|
556
|
-
static maskToken(token, visibleChars = 8) {
|
|
557
|
-
if (!token || typeof token !== "string") return "";
|
|
558
|
-
return token.length <= visibleChars ? token : `${token.slice(0, visibleChars)}...`;
|
|
716
|
+
async clearTokenCache() {
|
|
717
|
+
await this.cacheProvider.del(TOKEN_CACHE_KEY);
|
|
559
718
|
}
|
|
560
719
|
static scopesToString(scopes) {
|
|
561
720
|
if (!scopes) return "openid profile email";
|
|
@@ -563,14 +722,16 @@ var KeycloakClient = class {
|
|
|
563
722
|
}
|
|
564
723
|
};
|
|
565
724
|
KeycloakClient = __decorateClass([
|
|
566
|
-
(0,
|
|
567
|
-
__decorateParam(1, (0,
|
|
568
|
-
__decorateParam(2, (0,
|
|
569
|
-
__decorateParam(2, (0,
|
|
725
|
+
(0, import_common2.Injectable)(),
|
|
726
|
+
__decorateParam(1, (0, import_common2.Inject)(import_http_client2.HTTP_PROVIDER)),
|
|
727
|
+
__decorateParam(2, (0, import_common2.Optional)()),
|
|
728
|
+
__decorateParam(2, (0, import_common2.Inject)(import_logger2.LOGGER_PROVIDER)),
|
|
729
|
+
__decorateParam(3, (0, import_common2.Optional)()),
|
|
730
|
+
__decorateParam(3, (0, import_common2.Inject)(import_cache2.CACHE_PROVIDER))
|
|
570
731
|
], KeycloakClient);
|
|
571
732
|
|
|
572
733
|
// src/keycloak.http.interceptor.ts
|
|
573
|
-
var
|
|
734
|
+
var import_common3 = require("@nestjs/common");
|
|
574
735
|
var KeycloakHttpInterceptor = class {
|
|
575
736
|
constructor() {
|
|
576
737
|
}
|
|
@@ -582,15 +743,15 @@ var KeycloakHttpInterceptor = class {
|
|
|
582
743
|
}
|
|
583
744
|
};
|
|
584
745
|
KeycloakHttpInterceptor = __decorateClass([
|
|
585
|
-
(0,
|
|
746
|
+
(0, import_common3.Injectable)()
|
|
586
747
|
], KeycloakHttpInterceptor);
|
|
587
748
|
|
|
588
749
|
// src/roles.guard.ts
|
|
589
|
-
var
|
|
750
|
+
var import_common5 = require("@nestjs/common");
|
|
590
751
|
var import_core = require("@nestjs/core");
|
|
591
752
|
|
|
592
753
|
// src/roles.decorator.ts
|
|
593
|
-
var
|
|
754
|
+
var import_common4 = require("@nestjs/common");
|
|
594
755
|
var ROLES_META_KEY = "roles";
|
|
595
756
|
function Roles(...args) {
|
|
596
757
|
let payload;
|
|
@@ -604,17 +765,11 @@ function Roles(...args) {
|
|
|
604
765
|
}
|
|
605
766
|
payload.mode = payload.mode ?? "any";
|
|
606
767
|
payload.type = payload.type ?? "both";
|
|
607
|
-
return (0,
|
|
768
|
+
return (0, import_common4.SetMetadata)(ROLES_META_KEY, payload);
|
|
608
769
|
}
|
|
609
770
|
|
|
610
|
-
// src/keycloak.token.ts
|
|
611
|
-
var KEYCLOAK_CONFIG = "KEYCLOAK_CONFIG";
|
|
612
|
-
var KEYCLOAK_CLIENT = "KEYCLOAK_CLIENT";
|
|
613
|
-
var KEYCLOAK_HTTP_INTERCEPTOR = "KEYCLOAK_HTTP_INTERCEPTOR";
|
|
614
|
-
var KEYCLOAK_PROVIDER = "KEYCLOAK_PROVIDER";
|
|
615
|
-
|
|
616
771
|
// src/roles.guard.ts
|
|
617
|
-
var
|
|
772
|
+
var import_shared2 = __toESM(require_dist());
|
|
618
773
|
var RolesGuard = class {
|
|
619
774
|
constructor(reflector, config) {
|
|
620
775
|
this.reflector = reflector;
|
|
@@ -628,10 +783,10 @@ var RolesGuard = class {
|
|
|
628
783
|
const authHeader = ((_a = req.headers) == null ? void 0 : _a.authorization) || ((_b = req.headers) == null ? void 0 : _b.Authorization);
|
|
629
784
|
const token = authHeader ? String(authHeader).split(" ")[1] : (_c = req.query) == null ? void 0 : _c.token;
|
|
630
785
|
if (!token)
|
|
631
|
-
throw new
|
|
786
|
+
throw new import_shared2.BaseAppError({
|
|
632
787
|
message: "Authorization token not provided",
|
|
633
|
-
status:
|
|
634
|
-
code:
|
|
788
|
+
status: HTTP_STATUS.FORBIDDEN,
|
|
789
|
+
code: ROLES_ERROR_CODE.MISSING_TOKEN,
|
|
635
790
|
context: {}
|
|
636
791
|
});
|
|
637
792
|
const payload = this.decodeJwtPayload(token);
|
|
@@ -658,10 +813,10 @@ var RolesGuard = class {
|
|
|
658
813
|
const hasMatch = required.map((r) => availableRoles.has(r));
|
|
659
814
|
const result = meta.mode === "all" ? hasMatch.every(Boolean) : hasMatch.some(Boolean);
|
|
660
815
|
if (!result)
|
|
661
|
-
throw new
|
|
816
|
+
throw new import_shared2.BaseAppError({
|
|
662
817
|
message: "Insufficient roles",
|
|
663
|
-
status:
|
|
664
|
-
code:
|
|
818
|
+
status: HTTP_STATUS.FORBIDDEN,
|
|
819
|
+
code: ROLES_ERROR_CODE.INSUFFICIENT_ROLES,
|
|
665
820
|
context: { required }
|
|
666
821
|
});
|
|
667
822
|
return true;
|
|
@@ -681,10 +836,10 @@ var RolesGuard = class {
|
|
|
681
836
|
}
|
|
682
837
|
};
|
|
683
838
|
RolesGuard = __decorateClass([
|
|
684
|
-
(0,
|
|
685
|
-
__decorateParam(0, (0,
|
|
686
|
-
__decorateParam(1, (0,
|
|
687
|
-
__decorateParam(1, (0,
|
|
839
|
+
(0, import_common5.Injectable)(),
|
|
840
|
+
__decorateParam(0, (0, import_common5.Inject)(import_core.Reflector)),
|
|
841
|
+
__decorateParam(1, (0, import_common5.Optional)()),
|
|
842
|
+
__decorateParam(1, (0, import_common5.Inject)(KEYCLOAK_CONFIG))
|
|
688
843
|
], RolesGuard);
|
|
689
844
|
|
|
690
845
|
// src/keycloak.module.ts
|
|
@@ -694,7 +849,7 @@ var KeycloakModule = class {
|
|
|
694
849
|
module: KeycloakModule,
|
|
695
850
|
global: true,
|
|
696
851
|
imports: [
|
|
697
|
-
|
|
852
|
+
import_http_client3.HttpModule.forRoot(
|
|
698
853
|
httpConfig || { baseURL: config.baseUrl, timeout: 5e3 },
|
|
699
854
|
{
|
|
700
855
|
logging: {
|
|
@@ -711,11 +866,12 @@ var KeycloakModule = class {
|
|
|
711
866
|
{ provide: KEYCLOAK_CONFIG, useValue: config },
|
|
712
867
|
{
|
|
713
868
|
provide: KEYCLOAK_CLIENT,
|
|
714
|
-
useFactory: (cfg, httpProvider, logger) => new KeycloakClient(cfg, httpProvider, logger),
|
|
869
|
+
useFactory: (cfg, httpProvider, logger, cacheProvider) => new KeycloakClient(cfg, httpProvider, logger, cacheProvider),
|
|
715
870
|
inject: [
|
|
716
871
|
KEYCLOAK_CONFIG,
|
|
717
|
-
|
|
718
|
-
{ token:
|
|
872
|
+
import_http_client3.HTTP_PROVIDER,
|
|
873
|
+
{ token: import_logger3.LOGGER_PROVIDER, optional: true },
|
|
874
|
+
{ token: import_cache3.CACHE_PROVIDER, optional: true }
|
|
719
875
|
]
|
|
720
876
|
},
|
|
721
877
|
{
|
|
@@ -726,7 +882,8 @@ var KeycloakModule = class {
|
|
|
726
882
|
provide: KEYCLOAK_HTTP_INTERCEPTOR,
|
|
727
883
|
useFactory: () => new KeycloakHttpInterceptor()
|
|
728
884
|
},
|
|
729
|
-
RolesGuard
|
|
885
|
+
RolesGuard,
|
|
886
|
+
BearerTokenGuard
|
|
730
887
|
],
|
|
731
888
|
exports: [
|
|
732
889
|
import_core2.Reflector,
|
|
@@ -734,16 +891,18 @@ var KeycloakModule = class {
|
|
|
734
891
|
KEYCLOAK_PROVIDER,
|
|
735
892
|
KEYCLOAK_HTTP_INTERCEPTOR,
|
|
736
893
|
KEYCLOAK_CONFIG,
|
|
737
|
-
RolesGuard
|
|
894
|
+
RolesGuard,
|
|
895
|
+
BearerTokenGuard
|
|
738
896
|
]
|
|
739
897
|
};
|
|
740
898
|
}
|
|
741
899
|
};
|
|
742
900
|
KeycloakModule = __decorateClass([
|
|
743
|
-
(0,
|
|
901
|
+
(0, import_common6.Module)({})
|
|
744
902
|
], KeycloakModule);
|
|
745
903
|
// Annotate the CommonJS export names for ESM import in node:
|
|
746
904
|
0 && (module.exports = {
|
|
905
|
+
BearerTokenGuard,
|
|
747
906
|
KEYCLOAK_CLIENT,
|
|
748
907
|
KEYCLOAK_CONFIG,
|
|
749
908
|
KEYCLOAK_HTTP_INTERCEPTOR,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adatechnology/auth-keycloak",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
"dist"
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@adatechnology/
|
|
15
|
-
"@adatechnology/
|
|
14
|
+
"@adatechnology/cache": "0.0.8",
|
|
15
|
+
"@adatechnology/http-client": "0.0.9",
|
|
16
|
+
"@adatechnology/logger": "0.0.7"
|
|
16
17
|
},
|
|
17
18
|
"peerDependencies": {
|
|
18
19
|
"@nestjs/common": "^11.0.16",
|