keycloak-api-manager 2.0.2 → 2.0.3

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.
@@ -79,7 +79,7 @@
79
79
  <option name="presentableId" value="Default" />
80
80
  <updated>1759849149064</updated>
81
81
  <workItem from="1759849150239" duration="1214000" />
82
- <workItem from="1759917554117" duration="50432000" />
82
+ <workItem from="1759917554117" duration="53158000" />
83
83
  </task>
84
84
  <servers />
85
85
  </component>
package/README.md CHANGED
@@ -119,7 +119,7 @@ const users = await KeycloakManager.users.find({ first: 0, max: 10 });
119
119
  users = await KeycloakManager.users.find({ q: "phone:123" });
120
120
 
121
121
  // Override client configuration for all further requests:
122
- setConfig({
122
+ KeycloakManager.setConfig({
123
123
  realmName: 'another-realm',
124
124
  });
125
125
 
package/index.js CHANGED
@@ -83,9 +83,18 @@ exports.configure=async function(adminClientCredentials){
83
83
  //exports = kcAdminClient;
84
84
  };
85
85
 
86
+
87
+ //TODO: Remove da documentare
86
88
  exports.setConfig=async function(configToOverride){
87
89
  return(kcAdminClient.setConfig(configToOverride));
88
90
  }
91
+ //TODO: Remove da documentare
92
+ exports.getToken=async function(configToOverride){
93
+ return({
94
+ accessToken:kcAdminClient.accessToken,
95
+ refreshToken:kcAdminClient.refreshToken,
96
+ });
97
+ }
89
98
 
90
99
 
91
100
  /*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keycloak-api-manager",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "description": "Keycloak-api-manager is a lightweight Node.js wrapper for the Keycloak Admin REST API. It provides an easy-to-use functional methods and functions to manage realms, users, roles, clients, groups, and permissions directly from your application code — just like you would from the Keycloak admin console.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/index.old.js DELETED
@@ -1,1200 +0,0 @@
1
- var express = require('express');
2
- var conf=require('./config').conf;
3
- var responseinterceptor = require('responseinterceptor');
4
-
5
- var Keycloak =require('keycloak-connect');
6
- var session=require('express-session');
7
- var keycloak = null;
8
- var ready=false;
9
- var readyQueue=[];
10
-
11
-
12
-
13
- /**
14
- * ***************************** - ENGLISH - *******************************
15
- * Configuration function for the Keycloak adapter in an Express application.
16
- * It must be called at app startup, before defining any protected routes.
17
- *
18
- * Parameters:
19
- * - app: Express application instance (e.g., const app = express();)
20
- * - keyCloakConfig: JSON object containing the Keycloak client configuration.
21
- * This can be obtained from the Keycloak admin console:
22
- * Clients → [client name] → Installation → "Keycloak OIDC JSON" → Download
23
- * Example:
24
- * {
25
- * "realm": "realm-name",
26
- * "auth-server-url": "https://keycloak.example.com/",
27
- * "ssl-required": "external",
28
- * "resource": "client-name",
29
- * "credentials": { "secret": "secret-code" },
30
- * "confidential-port": 0
31
- * }
32
- * - keyCloakOptions: advanced configuration options for the adapter.
33
- * Main supported options:
34
- * - session: Express session configuration (as in express-session)
35
- * - scope: authentication scopes (e.g., 'openid profile email offline_access')
36
- * Note: to use offline_access, the client must have the option enabled and
37
- * the user must have the offline_access role.
38
- * - idpHint: to suggest an identity provider to Keycloak during login
39
- * - cookies: to enable cookie handling
40
- * - realmUrl: to override the realm URL
41
- */
42
- exports.configure=function(app,keyCloackConfig,keyCloackOptions){
43
- if(keyCloackOptions){
44
- if (keyCloackOptions.session){
45
- const memoryStore = new session.MemoryStore();
46
- app.use(
47
- session({
48
- secret: keyCloackOptions.session.secret || 'mySecret',
49
- resave: keyCloackOptions.session.resave || false,
50
- saveUninitialized: keyCloackOptions.session.saveUninitialized || true,
51
- store: memoryStore,
52
- })
53
- );
54
- keyCloackOptions.store=memoryStore;
55
- }
56
- }else keyCloackOptions={};
57
-
58
- keycloak = new Keycloak(keyCloackOptions,keyCloackConfig);
59
- app.use(keycloak.middleware());
60
- readyQueue.forEach(function(clb){
61
- clb();
62
- });
63
- ready=true;
64
- readyQueue=[];
65
-
66
- };
67
-
68
-
69
- /**
70
- * *************************** - ITALIANO - *****************************
71
- * Metodo da utilizzare per definire le rotte Express che devono essere protette da Keycloak.
72
- *
73
- * Questo metodo deve essere invocato **dopo** aver configurato Keycloak con `configure()`.
74
- * Le rotte dichiarate all’interno della callback fornita saranno protette e avranno accesso
75
- * alle funzionalità di autenticazione/autorizzazione gestite da Keycloak.
76
- *
77
- * 📌 Le rotte pubbliche (non protette) vanno dichiarate **prima** della chiamata a questo metodo.
78
- *
79
- * @param {Function} callback - Una funzione che definisce tutte le rotte da proteggere.
80
- * Deve contenere esclusivamente route che richiedono autenticazione.
81
- *
82
- * ✅ Esempio d'uso:
83
- *
84
- * // Rotta pubblica non protetta da Keycloak
85
- * app.get('/public', (req, res) => {
86
- * res.send('Public content');
87
- * });
88
- *
89
- * // Sezione di route protette da Keycloak
90
- * keycloakAdapter.underKeycloakProtection(() => {
91
- *
92
- * // Rotta protetta da autenticazione
93
- * app.get('/confidential', keycloakAdapter.protectMiddleware(), (req, res) => {
94
- * res.send('Confidential content visible only to authenticated users');
95
- * });
96
- *
97
- * // Rotta con login forzato: gestita direttamente dal middleware
98
- * app.get('/loginMiddleware', keycloakAdapter.loginMiddleware("/home"), (req, res) => {
99
- * // Questa risposta non verrà mai inviata, perché la gestione è effettuata direttamente dal middleware
100
- * });
101
- * });
102
- */
103
-
104
- /**
105
- * ***************************** - ENGLISH - *******************************
106
- * Method to define Express routes that must be protected by Keycloak.
107
- *
108
- * This method must be called **after** Keycloak has been configured with `configure()`.
109
- * The routes declared inside the provided callback will be protected and will have access
110
- * to authentication/authorization features managed by Keycloak.
111
- *
112
- * 📌 Public (unprotected) routes should be declared **before** calling this method.
113
- *
114
- * @param {Function} callback - A function that defines all routes to be protected.
115
- * It must contain exclusively routes requiring authentication.
116
- *
117
- * ✅ Usage example:
118
- *
119
- * // Public route not protected by Keycloak
120
- * app.get('/public', (req, res) => {
121
- * res.send('Public content');
122
- * });
123
- *
124
- * // Section of routes protected by Keycloak
125
- * keycloakAdapter.underKeycloakProtection(() => {
126
- *
127
- * // Route protected by authentication
128
- * app.get('/confidential', keycloakAdapter.protectMiddleware(), (req, res) => {
129
- * res.send('Confidential content visible only to authenticated users');
130
- * });
131
- *
132
- * // Route with forced login: handled directly by middleware
133
- * app.get('/loginMiddleware', keycloakAdapter.loginMiddleware("/home"), (req, res) => {
134
- * // This response will never be sent because the middleware handles the request directly
135
- * });
136
- * });
137
- */
138
- exports.underKeycloakProtection=function(callback){
139
- if(ready){
140
- callback();
141
- }else{
142
- readyQueue.push(callback);
143
- }
144
- }
145
-
146
-
147
- /**
148
- * *************************** - ITALIANO - *****************************
149
- * Middleware per proteggere le rotte Express basandosi sull'autenticazione e, opzionalmente,
150
- * sull'autorizzazione tramite ruoli Keycloak.
151
- *
152
- * Permette di limitare l'accesso a una risorsa solo agli utenti autenticati oppure
153
- * a quelli che possiedono ruoli specifici nel realm o in un client Keycloak.
154
- *
155
- * @param {string|function} [conditions] -
156
- * - Se stringa, specifica uno o più ruoli richiesti, con sintassi:
157
- * - 'role' → ruolo client nel client configurato (es. 'admin')
158
- * - 'clientid:role' → ruolo client specifico di un client (es. 'myclient:editor')
159
- * - 'realm:role' → ruolo di realm (es. 'realm:superuser')
160
- * - Se funzione, riceve (token, req) e deve restituire true o false in modo sincrono.
161
- * Questa funzione consente una logica di autorizzazione personalizzata.
162
- *
163
- * @returns {Function} Middleware Express per la protezione della route.
164
- *
165
- * --- Esempi di utilizzo ---
166
- *
167
- * // Solo autenticazione senza controllo sui ruoli
168
- * app.get('/admin', keycloakAdapter.protectMiddleware(), (req, res) => {
169
- * res.send('Solo utenti autenticati possono vedere questa risorsa.');
170
- * });
171
- *
172
- * // Controllo su ruolo client del client configurato (es. 'admin')
173
- * app.get('/admin', keycloakAdapter.protectMiddleware('admin'), (req, res) => {
174
- * res.send('Solo utenti con ruolo client admin possono accedere.');
175
- * });
176
- *
177
- * // Controllo su ruolo di un client specifico (es. client 'clientid', ruolo 'admin')
178
- * app.get('/admin', keycloakAdapter.protectMiddleware('clientid:admin'), (req, res) => {
179
- * res.send('Solo utenti con ruolo admin nel client "clientid" possono accedere.');
180
- * });
181
- *
182
- * // Controllo su ruolo di realm (es. ruolo 'superuser' a livello realm)
183
- * app.get('/admin', keycloakAdapter.protectMiddleware('realm:superuser'), (req, res) => {
184
- * res.send('Solo utenti con ruolo realm superuser possono accedere.');
185
- * });
186
- *
187
- * // Funzione di controllo personalizzata (sincrona)
188
- * app.get('/custom', keycloakAdapter.protectMiddleware((token, req) => {
189
- * // Consenti solo se l’utente ha il ruolo realm 'editor'
190
- * // e se la richiesta ha header personalizzato specifico
191
- * return token.hasRealmRole('editor') && req.headers['x-custom-header'] === 'OK';
192
- * }), (req, res) => {
193
- * res.send('Accesso consentito dalla funzione di controllo personalizzata.');
194
- * });
195
- *
196
- * --- Dettagli sul token e metodi utili ---
197
- *
198
- * L'oggetto `token` passato alla funzione di controllo espone metodi come:
199
- * - token.hasRole('admin') // ruolo client nel client configurato
200
- * - token.hasRole('realm:superuser') // ruolo realm
201
- * - token.hasRole('my-client:editor') // ruolo client di un client specifico
202
- * - token.hasResourceRole('editor', 'my-client-id') // equivalente a hasRole('my-client:editor')
203
- *
204
- * La funzione di controllo deve essere sincrona e restituire true (consente l’accesso)
205
- * o false (nega l’accesso).
206
- */
207
-
208
- /**
209
- * ***************************** - ENGLISH - *******************************
210
- * Middleware to protect Express routes based on authentication and, optionally,
211
- * authorization via Keycloak roles.
212
- *
213
- * Allows restricting access to a resource only to authenticated users or
214
- * to those possessing specific roles in the realm or in a Keycloak client.
215
- *
216
- * @param {string|function} [conditions] -
217
- * - If a string, specifies one or more required roles, using the syntax:
218
- * - 'role' → client role in the configured client (e.g., 'admin')
219
- * - 'clientid:role' → client role of a specific client (e.g., 'myclient:editor')
220
- * - 'realm:role' → realm role (e.g., 'realm:superuser')
221
- * - If a function, receives (token, req) and must return true or false synchronously.
222
- * This function enables custom authorization logic.
223
- *
224
- * @returns {Function} Express middleware to protect the route.
225
- *
226
- * --- Usage examples ---
227
- *
228
- * // Authentication only, no role check
229
- * app.get('/admin', keycloakAdapter.protectMiddleware(), (req, res) => {
230
- * res.send('Only authenticated users can see this resource.');
231
- * });
232
- *
233
- * // Check on client role of configured client (e.g., 'admin')
234
- * app.get('/admin', keycloakAdapter.protectMiddleware('admin'), (req, res) => {
235
- * res.send('Only users with the admin client role can access.');
236
- * });
237
- *
238
- * // Check on role of a specific client (e.g., client 'clientid', role 'admin')
239
- * app.get('/admin', keycloakAdapter.protectMiddleware('clientid:admin'), (req, res) => {
240
- * res.send('Only users with admin role in client "clientid" can access.');
241
- * });
242
- *
243
- * // Check on realm role (e.g., 'superuser' role at realm level)
244
- * app.get('/admin', keycloakAdapter.protectMiddleware('realm:superuser'), (req, res) => {
245
- * res.send('Only users with realm superuser role can access.');
246
- * });
247
- *
248
- * // Custom synchronous authorization function
249
- * app.get('/custom', keycloakAdapter.protectMiddleware((token, req) => {
250
- * // Allow only if user has realm role 'editor'
251
- * // and the request has a specific custom header
252
- * return token.hasRealmRole('editor') && req.headers['x-custom-header'] === 'OK';
253
- * }), (req, res) => {
254
- * res.send('Access granted by custom authorization function.');
255
- * });
256
- *
257
- * --- Token details and useful methods ---
258
- *
259
- * The `token` object passed to the authorization function exposes methods such as:
260
- * - token.hasRole('admin') // client role in configured client
261
- * - token.hasRole('realm:superuser') // realm role
262
- * - token.hasRole('my-client:editor') // client role of a specific client
263
- * - token.hasResourceRole('editor', 'my-client-id') // equivalent to hasRole('my-client:editor')
264
- *
265
- * The authorization function must be synchronous and return true (allow access)
266
- * or false (deny access).
267
- */
268
-
269
- exports.protectMiddleware=function(conditions){
270
- return(keycloak.protect(conditions));
271
- }
272
-
273
-
274
- /**
275
- * *************************** - ITALIANO - *****************************
276
- * Middleware simile a `protectMiddleware` ma con controllo dinamico dei ruoli tramite funzione.
277
- *
278
- * A differenza di `protectMiddleware` che accetta una stringa che esprime il ruolo o una funzione di controllo
279
- * che lavora sul token, questo middleware accetta una funzione che riceve la richiesta e la risposta express
280
- * `req` e `res`e deve restituire una stringa con la stringa di controllo sul ruolo.
281
- *
282
- * È utile per risorse parametriche dove la stringa di controllo sul ruolo va generata dinamicamente in base alla richiesta,
283
- * ad esempio in base a parametri URL o query string.
284
- *
285
- * Nota: questa funzione **non** accede né analizza il token, né fa altri controlli oltre al ruolo,
286
- * quindi non può essere usata per logiche complesse che dipendono da proprietà della richiesta
287
- * diverse dal ruolo (es. IP client, header personalizzati, ecc).
288
- * La funzione ha il solo compito di generare la stringa di controllo
289
- *
290
- * --- Parametri ---
291
- * @param {function} customFunction - funzione che riceve (req, res) e restituisce una stringa
292
- * con la stringa di controllo ruolo da passare a Keycloak.
293
- *
294
- * --- Esempio di utilizzo ---
295
- *
296
- * app.get('/custom/:id', keycloakAdapter.customProtectMiddleware((req) => {
297
- * // Costruisce dinamicamente il ruolo client in base al parametro URL 'id'
298
- * return `clientRole${req.params.id}`;
299
- * }), (req, res) => {
300
- * res.send(`Accesso consentito a chi ha il ruolo 'clientRole${req.params.id}`);
301
- * });
302
- *
303
- * --- Funzionamento interno ---
304
- * - Richiama la funzione `customFunction` con req, res per ottenere la stringa ruolo.
305
- * - Passa tale stringa a `keycloak.protect()`.
306
- * - Restituisce un middleware Express che esegue la protezione Keycloak basata su quella stringa.
307
- */
308
-
309
- /**
310
- * ***************************** - ENGLISH - *******************************
311
- * Middleware similar to `protectMiddleware` but with dynamic role checking via a function.
312
- *
313
- * Unlike `protectMiddleware`, which accepts a string expressing the role or a control function
314
- * that works on the token, this middleware accepts a function that receives the Express
315
- * request and response objects `req` and `res` and must return a string representing the role control string.
316
- *
317
- * This is useful for parametric resources where the role control string must be dynamically generated based on the request,
318
- * for example, based on URL parameters or query strings.
319
- *
320
- * Note: this function **does not** access or parse the token, nor performs any checks other than the role,
321
- * so it cannot be used for complex logic depending on request properties other than the role
322
- * (e.g., client IP, custom headers, etc.).
323
- * The function's sole task is to generate the role control string.
324
- *
325
- * --- Parameters ---
326
- * @param {function} customFunction - function that receives (req, res) and returns a string
327
- * with the role control string to pass to Keycloak.
328
- *
329
- * --- Usage example ---
330
- *
331
- * app.get('/custom/:id', keycloakAdapter.customProtectMiddleware((req) => {
332
- * // Dynamically builds the client role based on URL parameter 'id'
333
- * return `clientRole${req.params.id}`;
334
- * }), (req, res) => {
335
- * res.send(`Access granted to users with role 'clientRole${req.params.id}'`);
336
- * });
337
- *
338
- * --- Internal working ---
339
- * - Calls the `customFunction` with req, res to obtain the role string.
340
- * - Passes that string to `keycloak.protect()`.
341
- * - Returns an Express middleware that enforces Keycloak protection based on that string.
342
- */
343
-
344
- exports.customProtectMiddleware=function(customFunction){
345
- return function(req, res, next){
346
- let protectionString=customFunction(req,res);
347
- keycloak.protect(protectionString)(req,res,next);
348
- }
349
- }
350
-
351
-
352
- /**
353
- * *************************** - ITALIANO - *****************************
354
- * Middleware `encodeTokenRole` che decodifica il token Keycloak e lo aggiunge
355
- * alla richiesta Express come `req.encodedTokenRole`.
356
- *
357
- * A differenza di `protectMiddleware` o `customProtectMiddleware`, questo middleware
358
- * NON effettua alcun controllo sui ruoli o sull’autenticazione, ma si limita a estrarre
359
- * e rendere disponibile il token decodificato all’interno della funzione di gestione
360
- * della route.
361
- *
362
- * È particolarmente utile quando vuoi eseguire logiche personalizzate basate sul ruolo
363
- * o su altre informazioni contenute nel token direttamente nella route handler,
364
- * per esempio mostrare contenuti diversi in base al ruolo.
365
- *
366
- * --- Contenuto di `req.encodedTokenRole` ---
367
- * Rappresenta il token decodificato Keycloak e espone vari metodi utili come:
368
- * - token.hasRole('admin') // true/false se ha ruolo client "admin"
369
- * - token.hasRole('realm:superuser') // true/false se ha ruolo realm "superuser"
370
- * - token.hasRole('my-client:editor') // true/false se ha ruolo client "editor" per client "my-client"
371
- * - token.hasResourceRole('editor', 'my-client-id') // identico a hasRole('my-client:editor')
372
- *
373
- * --- Esempio di utilizzo ---
374
- *
375
- * app.get('/encodeToken', keycloakAdapter.encodeTokenRole(), (req, res) => {
376
- * if (req.encodedTokenRole.hasRole('realm:admin')) {
377
- * res.send("Utente con ruolo admin (realm) in encodeToken");
378
- * } else {
379
- * res.send("Utente normale in encodeToken");
380
- * }
381
- * });
382
- *
383
- * --- Funzionamento interno ---
384
- * Utilizza `keycloak.protect()` con una funzione di callback che assegna il token
385
- * decodificato a `req.encodedTokenRole` e passa sempre la protezione.
386
- *
387
- * In questo modo non blocca l’accesso ma rende disponibile il token nella route.
388
- */
389
-
390
-
391
- /**
392
- * ***************************** - ENGLISH - *******************************
393
- * `encodeTokenRole` middleware that decodes the Keycloak token and adds it
394
- * to the Express request as `req.encodedTokenRole`.
395
- *
396
- * Unlike `protectMiddleware` or `customProtectMiddleware`, this middleware
397
- * does NOT perform any role or authentication checks, but simply extracts
398
- * and makes the decoded token available within the route handler function.
399
- *
400
- * It is especially useful when you want to perform custom logic based on roles
401
- * or other information contained in the token directly in the route handler,
402
- * for example showing different content based on role.
403
- *
404
- * --- Contents of `req.encodedTokenRole` ---
405
- * Represents the decoded Keycloak token and exposes several useful methods such as:
406
- * - token.hasRole('admin') // true/false if it has client role "admin"
407
- * - token.hasRole('realm:superuser') // true/false if it has realm role "superuser"
408
- * - token.hasRole('my-client:editor') // true/false if it has client role "editor" for client "my-client"
409
- * - token.hasResourceRole('editor', 'my-client-id') // identical to hasRole('my-client:editor')
410
- *
411
- * --- Usage example ---
412
- *
413
- * app.get('/encodeToken', keycloakAdapter.encodeTokenRole(), (req, res) => {
414
- * if (req.encodedTokenRole.hasRole('realm:admin')) {
415
- * res.send("User with admin (realm) role in encodeToken");
416
- * } else {
417
- * res.send("Regular user in encodeToken");
418
- * }
419
- * });
420
- *
421
- * --- Internal working ---
422
- * Uses `keycloak.protect()` with a callback function that assigns the decoded token
423
- * to `req.encodedTokenRole` and always allows access.
424
- *
425
- * This way it does not block access but makes the token available in the route.
426
- */
427
-
428
- exports.encodeTokenRole=function(){
429
- let getTokenFunction=function(token,req){
430
- req.encodedTokenRole=token;
431
- return(true);
432
- }
433
- return(keycloak.protect(getTokenFunction));
434
- }
435
-
436
-
437
-
438
- /**
439
- * *************************** - ITALIANO - *****************************
440
- * Middleware `enforcerMiddleware` per abilitare il controllo delle autorizzazioni (permissions)
441
- * basate su risorse e policy definite in Keycloak Authorization Services (basato su UMA 2.0).
442
- *
443
- * A differenza di `protectMiddleware` e simili, che verificano solo autenticazione o ruoli,
444
- * `enforcerMiddleware` consente di verificare se l'utente ha il permesso di accedere
445
- * a una specifica risorsa protetta tramite policy flessibili e dinamiche.
446
- *
447
- * È utile in contesti dove le risorse sono registrate in Keycloak (come documenti, istanze, entità dinamiche) e
448
- * protette da policy flessibili.
449
- *
450
- * --- Parametri ---
451
- * @param {string|function} conditions
452
- * - stringa contenente il nome della risorsa o permesso da controllare
453
- * - funzione di controllo personalizzata con firma:
454
- * function(token, req, callback)
455
- * - token: token Keycloak decodificato
456
- * - req: richiesta Express
457
- * - callback(boolean): da invocare con true se autorizzato, false altrimenti
458
- *
459
- * @param {object} [options] (opzionale)
460
- * - response_mode: 'permissions' (default) o 'token'
461
- * - claims: object con claim info per policy dinamiche (es. owner id matching)
462
- * - resource_server_id: id del client risorsa (default: client corrente)
463
- *
464
- * --- Funzionamento ---
465
- * - Se conditions è funzione, viene usata per effettuare controlli custom con callback.
466
- * - Se conditions è stringa, si usa `keycloak.enforcer(conditions, options)` per il controllo.
467
- *
468
- * --- Modalità response_mode ---
469
- * 1) 'permissions' (default)
470
- * - Keycloak ritorna la lista delle permission concesse (no nuovo token)
471
- * - Permissions disponibili in `req.permissions`
472
- *
473
- * 2) 'token'
474
- * - Keycloak emette un nuovo access token con le permission concesse
475
- * - Permissions disponibili in `req.kauth.grant.access_token.content.authorization.permissions`
476
- * - Utile per app con sessioni e caching decisioni
477
- *
478
- * --- Requisiti lato Keycloak ---
479
- * Il client deve avere:
480
- * - Authorization Enabled = ON
481
- * - Policy Enforcement Mode = Enforcing
482
- * - Add permissions to access token = ON
483
- *
484
- * Inoltre devi aver configurato in Keycloak:
485
- * - Risorse (Resource)
486
- * - Policy (es. ruolo, owner, script JS)
487
- * - Permission (associa policy a risorsa)
488
- *
489
- * --- Esempi di utilizzo ---
490
- *
491
- * // Controllo con stringa statica
492
- * app.get('/onlyAdminroute', keycloakAdapter.enforcerMiddleware('ui-admin-resource'), (req, res) => {
493
- * res.send('Sei un admin autorizzato per questa risorsa');
494
- * });
495
- *
496
- * // Controllo con funzione custom (asincrona con callback)
497
- * app.get('/onlyAdminrouteByfunction', keycloakAdapter.enforcerMiddleware(function(token, req, callback) {
498
- * token.hasPermission('ui-admin-resource', function(permission) {
499
- * if (permission) callback(true);
500
- * else {
501
- * token.hasPermission('ui-viewer-resource', function(permission) {
502
- * callback(permission ? true : false);
503
- * });
504
- * }
505
- * });
506
- * }), (req, res) => {
507
- * res.send('Sei admin o viewer autorizzato (controllo custom)');
508
- * });
509
- */
510
-
511
- /**
512
- * ***************************** - ENGLISH - *******************************
513
- * `enforcerMiddleware` middleware to enable permission checks
514
- * based on resources and policies defined in Keycloak Authorization Services (UMA 2.0-based).
515
- *
516
- * Unlike `protectMiddleware` and similar, which only verify authentication or roles,
517
- * `enforcerMiddleware` allows checking if the user has permission to access
518
- * a specific protected resource through flexible and dynamic policies.
519
- *
520
- * Useful in contexts where resources are registered in Keycloak (such as documents, instances, dynamic entities) and
521
- * protected by flexible policies.
522
- *
523
- * --- Parameters ---
524
- * @param {string|function} conditions
525
- * - string containing the name of the resource or permission to check
526
- * - custom check function with signature:
527
- * function(token, req, callback)
528
- * - token: decoded Keycloak token
529
- * - req: Express request
530
- * - callback(boolean): invoke with true if authorized, false otherwise
531
- *
532
- * @param {object} [options] (optional)
533
- * - response_mode: 'permissions' (default) or 'token'
534
- * - claims: object with claim info for dynamic policies (e.g. owner id matching)
535
- * - resource_server_id: resource client id (default: current client)
536
- *
537
- * --- How it works ---
538
- * - If conditions is a function, it is used for custom checks with callback.
539
- * - If conditions is a string, `keycloak.enforcer(conditions, options)` is used for the check.
540
- *
541
- * --- response_mode modes ---
542
- * 1) 'permissions' (default)
543
- * - Keycloak returns the list of granted permissions (no new token)
544
- * - Permissions available in `req.permissions`
545
- *
546
- * 2) 'token'
547
- * - Keycloak issues a new access token containing the granted permissions
548
- * - Permissions available in `req.kauth.grant.access_token.content.authorization.permissions`
549
- * - Useful for apps with sessions and decision caching
550
- *
551
- * --- Keycloak requirements ---
552
- * The client must have:
553
- * - Authorization Enabled = ON
554
- * - Policy Enforcement Mode = Enforcing
555
- * - Add permissions to access token = ON
556
- *
557
- * You must also configure in Keycloak:
558
- * - Resources
559
- * - Policies (e.g., role, owner, JS script)
560
- * - Permissions (associate policies to resources)
561
- *
562
- * --- Usage examples ---
563
- *
564
- * // Check with static string
565
- * app.get('/onlyAdminroute', keycloakAdapter.enforcerMiddleware('ui-admin-resource'), (req, res) => {
566
- * res.send('You are an authorized admin for this resource');
567
- * });
568
- *
569
- * // Check with custom function (async with callback)
570
- * app.get('/onlyAdminrouteByfunction', keycloakAdapter.enforcerMiddleware(function(token, req, callback) {
571
- * token.hasPermission('ui-admin-resource', function(permission) {
572
- * if (permission) callback(true);
573
- * else {
574
- * token.hasPermission('ui-viewer-resource', function(permission) {
575
- * callback(permission ? true : false);
576
- * });
577
- * }
578
- * });
579
- * }), (req, res) => {
580
- * res.send('You are an authorized admin or viewer (custom check)');
581
- * });
582
- */
583
-
584
- exports.enforcerMiddleware=function(conditions,options){
585
- if (typeof conditions === 'function') {
586
- return (function(req, res, next){
587
- let tokenF=function(permission,callbackPermission){
588
- encodeTokenPermissionHandler(permission,req,res,callbackPermission);
589
- }
590
- conditions({hasPermission:tokenF},req,function(yesOrNot){
591
- if(yesOrNot) next();
592
- else {
593
- keycloak.protect(function (token, req) {
594
- return(false);
595
- })(req,res,next);
596
- }
597
- });
598
- })
599
- }else{
600
- return(keycloak.enforcer(conditions,options));
601
- }
602
- }
603
-
604
-
605
-
606
-
607
- /**
608
- * *************************** - ITALIANO - *****************************
609
- * Middleware `customEnforcerMiddleware` per il controllo delle autorizzazioni basate su risorse e policy
610
- * definite in Keycloak Authorization Services (UMA 2.0), con stringhe di controllo dinamiche.
611
- *
612
- * Questo middleware è simile a `enforcerMiddleware` ma prende come parametro una funzione
613
- * `customFunction(req, res)` che deve restituire dinamicamente una stringa contenente
614
- * la stringa di controllo (permission/resource) da verificare.
615
- *
616
- * --- Parametri ---
617
- * @param {function} customFunction
618
- * Funzione che riceve `req` e `res` e restituisce la stringa di controllo per Keycloak.
619
- * Esempio:
620
- * function(req, res) {
621
- * return req.params.permission;
622
- * }
623
- *
624
- * @param {object} [options] (opzionale)
625
- * Opzioni aggiuntive passate a `keycloak.enforcer()`, tra cui:
626
- * - response_mode: 'permissions' (default) o 'token'
627
- * - claims: oggetto con claim info per policy dinamiche (es: owner ID)
628
- * - resource_server_id: stringa id client risorsa (default: client corrente)
629
- *
630
- * --- Modalità response_mode ---
631
- * 1) 'permissions' (default)
632
- * - Il server restituisce solo la lista di permission concesse (no nuovo token)
633
- * - Permissions disponibili in `req.permissions`
634
- *
635
- * 2) 'token'
636
- * - Il server emette un nuovo access token con le permission concesse
637
- * - Permissions disponibili in `req.kauth.grant.access_token.content.authorization.permissions`
638
- * - Utile per caching decisioni, gestione sessioni, refresh automatico token
639
- *
640
- * --- Requisiti lato Keycloak ---
641
- * Il client deve essere configurato con:
642
- * - Authorization Enabled = ON
643
- * - Policy Enforcement Mode = Enforcing
644
- * - Add permissions to access token = ON
645
- *
646
- * Inoltre devi aver creato:
647
- * - Risorse (Resource)
648
- * - Policy (es. ruolo, owner, regole JS)
649
- * - Permission (associa policy a risorsa)
650
- *
651
- * --- Esempio di utilizzo ---
652
- *
653
- * const tmpFunctionEnforce = function(req, res) {
654
- * return req.params.permission; // permission dinamica da parametro URL
655
- * };
656
- *
657
- * app.get('/onlyAdminrouteByfunction/:permission', keycloakAdapter.customEnforcerMiddleware(tmpFunctionEnforce), (req, res) => {
658
- * res.send('Sei un utente autorizzato con permesso dinamico: ' + req.params.permission);
659
- * });
660
- *
661
- */
662
-
663
- /**
664
- * ***************************** - ENGLISH - *******************************
665
- * `customEnforcerMiddleware` middleware for permission checks based on resources and policies
666
- * defined in Keycloak Authorization Services (UMA 2.0), using dynamic permission strings.
667
- *
668
- * This middleware is similar to `enforcerMiddleware`, but takes a function
669
- * `customFunction(req, res)` as a parameter, which must dynamically return
670
- * the permission/resource string to be checked.
671
- *
672
- * --- Parameters ---
673
- * @param {function} customFunction
674
- * Function that receives `req` and `res` and returns the control string for Keycloak.
675
- * Example:
676
- * function(req, res) {
677
- * return req.params.permission;
678
- * }
679
- *
680
- * @param {object} [options] (optional)
681
- * Additional options passed to `keycloak.enforcer()`, including:
682
- * - response_mode: 'permissions' (default) or 'token'
683
- * - claims: object with claim info for dynamic policies (e.g., owner ID)
684
- * - resource_server_id: string representing the resource client ID (default: current client)
685
- *
686
- * --- response_mode options ---
687
- * 1) 'permissions' (default)
688
- * - The server returns only the list of granted permissions (no new token)
689
- * - Permissions available in `req.permissions`
690
- *
691
- * 2) 'token'
692
- * - The server issues a new access token with granted permissions
693
- * - Permissions available in `req.kauth.grant.access_token.content.authorization.permissions`
694
- * - Useful for decision caching, session handling, automatic token refresh
695
- *
696
- * --- Keycloak Requirements ---
697
- * The client must be configured with:
698
- * - Authorization Enabled = ON
699
- * - Policy Enforcement Mode = Enforcing
700
- * - Add permissions to access token = ON
701
- *
702
- * You must also have created:
703
- * - Resources
704
- * - Policies (e.g., role, owner, JS rules)
705
- * - Permissions (linking policies to resources)
706
- *
707
- * --- Usage Example ---
708
- *
709
- * const tmpFunctionEnforce = function(req, res) {
710
- * return req.params.permission; // dynamic permission from URL parameter
711
- * };
712
- *
713
- * app.get('/onlyAdminrouteByfunction/:permission', keycloakAdapter.customEnforcerMiddleware(tmpFunctionEnforce), (req, res) => {
714
- * res.send('You are an authorized user with dynamic permission: ' + req.params.permission);
715
- * });
716
- */
717
-
718
- exports.customEnforcerMiddleware=function(customFunction,options){
719
- return function(req, res, next){
720
- let protectionString=customFunction(req,res);
721
- keycloak.enforcer(protectionString,options)(req,res,next);
722
- }
723
- }
724
-
725
-
726
-
727
- function encodeTokenPermissionHandler(permissions,req,res,callback){
728
- res.oldEnd=res.end;
729
- res.end=function(content){
730
- res.end=res.oldEnd;
731
- callback(false);
732
- }
733
- keycloak.enforcer(permissions)(req,res,function(){
734
- res.end=res.oldEnd;
735
- callback(true);
736
- });
737
- }
738
-
739
-
740
- /**
741
- * *************************** - ITALIANO - *****************************
742
- * Middleware `encodeTokenPermission`
743
- *
744
- * Questo middleware ha il solo compito di decodificare il token di accesso presente nella richiesta
745
- * e aggiungere alla `req` un oggetto chiamato `encodedTokenPremission`contenete i permessi del token.
746
- *
747
- * A differenza di `enforcerMiddleware` e `customEnforcerMiddleware`, **non esegue alcun controllo**
748
- * sull'accesso o autorizzazione, ma espone un metodo utile (`hasPermission`) per verificare i permessi
749
- * all'interno del gestore della route.
750
- *
751
- * È particolarmente utile nei casi in cui:
752
- * - si voglia **personalizzare la risposta** in base ai permessi dell'utente (es. mostrare una pagina diversa),
753
- * - si voglia **gestire manualmente l'accesso** o eseguire controlli personalizzati su più permessi,
754
- * - non si voglia bloccare l'accesso preventivamente ma decidere dinamicamente nel gestore della risorsa.
755
- *
756
- * --- Aggiunte a `req` ---
757
- * Dopo l'applicazione del middleware, `req` contiene:
758
- *
759
- * @property {Object} req.encodedTokenPremission
760
- * Un oggetto che espone il metodo:
761
- *
762
- * - `hasPermission(permission: string, callback: function(boolean))`
763
- * Verifica se il token possiede il permesso specificato.
764
- * La callback riceve `true` se il permesso è presente, `false` altrimenti.
765
- *
766
- * --- Esempio di utilizzo ---
767
- *
768
- * ```js
769
- * app.get('/encodeTokenPermission',
770
- * keycloakAdapter.encodeTokenPermission(),
771
- * (req, res) => {
772
- * req.encodedTokenPremission.hasPermission('ui-admin-resource', function(perm) {
773
- * if (perm)
774
- * res.send('You are an authorized admin User by function permission parameters');
775
- * else
776
- * res.status(403).send('Access Denied by encodeTokenPermission');
777
- * });
778
- * });
779
- * ```
780
- */
781
-
782
-
783
- /**
784
- * ***************************** - ENGLISH - *******************************
785
- * `encodeTokenPermission` Middleware
786
- *
787
- * This middleware's sole purpose is to decode the access token present in the request
788
- * and add to the `req` object a property called `encodedTokenPermission` containing the token's permissions.
789
- *
790
- * Unlike `enforcerMiddleware` and `customEnforcerMiddleware`, it **does not perform any access**
791
- * or authorization checks, but exposes a useful method (`hasPermission`) for checking permissions
792
- * within the route handler.
793
- *
794
- * It is particularly useful when:
795
- * - you want to **customize the response** based on the user's permissions (e.g., show a different page),
796
- * - you want to **manually handle access** or perform custom checks on multiple permissions,
797
- * - you do not want to block access upfront but decide dynamically within the route handler.
798
- *
799
- * --- Additions to `req` ---
800
- * After applying the middleware, `req` contains:
801
- *
802
- * @property {Object} req.encodedTokenPermission
803
- * An object exposing the method:
804
- *
805
- * - `hasPermission(permission: string, callback: function(boolean))`
806
- * Checks whether the token contains the specified permission.
807
- * The callback receives `true` if the permission is present, `false` otherwise.
808
- *
809
- * --- Usage Example ---
810
- *
811
- * ```js
812
- * app.get('/encodeTokenPermission',
813
- * keycloakAdapter.encodeTokenPermission(),
814
- * (req, res) => {
815
- * req.encodedTokenPermission.hasPermission('ui-admin-resource', function(perm) {
816
- * if (perm)
817
- * res.send('You are an authorized admin user by function permission parameters');
818
- * else
819
- * res.status(403).send('Access Denied by encodeTokenPermission');
820
- * });
821
- * });
822
- * ```
823
- */
824
-
825
- exports.encodeTokenPermission=function(){
826
- return(function (req,res,next){
827
- req.encodedTokenPremission={
828
- "hasPermission":function(permission,callback){
829
- encodeTokenPermissionHandler(permission,req,res,callback);
830
- }
831
- };
832
- next();
833
- });
834
- }
835
-
836
- /**
837
- * *************************** - ITALIANO - *****************************
838
- * Middleware `loginMiddleware`
839
- *
840
- * Questo middleware viene utilizzato per **forzare l'autenticazione dell'utente** tramite Keycloak.
841
- *
842
- * È particolarmente utile nei casi in cui si voglia:
843
- * - assicurarsi che l'utente sia autenticato,
844
- * - reindirizzare l'utente ad una pagina specifica dopo il login o in caso di accesso negato,
845
- * - integrare flussi di autenticazione automatici su rotte che non richiedono direttamente autorizzazione
846
- * ma dove si vuole comunque forzare la login (es. pagina profilo, area personale, ecc.).
847
- *
848
- * --- Comportamento ---
849
- * 1. Se l’utente **non è autenticato**, Keycloak redirige al suo flusso di login.
850
- * 2. Se l’autenticazione fallisce o viene rifiutata, l’utente viene reindirizzato secondo le specifiche configurate su keycloak
851
- * 3. Se autenticato correttamente, viene reindirizzato a 'redirectTo' (di solito `/home`, `/dashboard`, ecc.).
852
- *
853
- * --- Parametri ---
854
- * @param {string} redirectTo - URL verso cui reindirizzare l’utente dopo il login.
855
- *
856
- * --- Attenzione ---
857
- * La funzione di callback associata alla route **non viene mai eseguita**, perché il middleware risponde prima
858
- * con un redirect o con un blocco.
859
- *
860
- * --- Esempio di utilizzo ---
861
- * ```js
862
- * app.get('/loginMiddleware',
863
- * keycloakAdapter.loginMiddleware("/home"),
864
- * (req, res) => {
865
- * // Questa sezione non viene mai raggiunta
866
- * res.send("Se vedi questo messaggio, qualcosa è andato storto.");
867
- * });
868
- * ```
869
- *
870
- * --- Requisiti ---
871
- * È necessario che Keycloak sia correttamente configurato e collegato all'app come middleware.
872
- */
873
-
874
- /**
875
- * ***************************** - ENGLISH - *******************************
876
- * `loginMiddleware` Middleware
877
- *
878
- * This middleware is used to **force user authentication** via Keycloak.
879
- *
880
- * It is particularly useful when you want to:
881
- * - ensure the user is authenticated,
882
- * - redirect the user to a specific page after login or when access is denied,
883
- * - integrate automatic login flows on routes that don’t require direct authorization,
884
- * but where login should still be enforced (e.g., profile page, personal area, etc.).
885
- *
886
- * --- Behavior ---
887
- * 1. If the user is **not authenticated**, Keycloak redirects them to the login flow.
888
- * 2. If authentication fails or is denied, the user is redirected according to Keycloak's configured settings.
889
- * 3. If authentication is successful, the user is redirected to 'redirectTo' (usually `/home`, `/dashboard`, etc.).
890
- *
891
- * --- Parameters ---
892
- * @param {string} redirectTo - URL to redirect the user to after login.
893
- *
894
- * --- Warning ---
895
- * The route handler callback is **never executed**, because the middleware will respond earlier
896
- * with a redirect or block the request.
897
- *
898
- * --- Usage Example ---
899
- * ```js
900
- * app.get('/loginMiddleware',
901
- * keycloakAdapter.loginMiddleware("/home"),
902
- * (req, res) => {
903
- * // This section is never reached
904
- * res.send("If you see this message, something went wrong.");
905
- * });
906
- * ```
907
- *
908
- * --- Requirements ---
909
- * Keycloak must be properly configured and connected to the app as middleware.
910
- */
911
-
912
- exports.loginMiddleware=function(redirecTo){
913
- return([keycloak.protect(),function(req,res,next){
914
- res.redirect(redirecTo);
915
- }]);
916
- }
917
-
918
-
919
- /**
920
- * *************************** - ITALIANO - *****************************
921
- * Middleware `logoutMiddleware`
922
- *
923
- * Questo middleware viene utilizzato per **forzare il logout dell'utente**, eliminando la sessione locale
924
- * e redirigendo l'utente al logout di Keycloak secondo le sue configurazioni.
925
- *
926
- * È utile nei casi in cui:
927
- * - Si voglia disconnettere completamente l’utente,
928
- * - Si desideri **terminare la sessione su Keycloak** (non solo localmente),
929
- * - Si voglia reindirizzare l’utente ad una pagina pubblica, come una homepage, dopo il logout.
930
- *
931
- * --- Comportamento ---
932
- * 1. Ottiene l'`id_token` dell'utente autenticato.
933
- * 2. Costruisce l'URL di logout di Keycloak includendo il token e l'URL di redirect.
934
- * 3. **Distrugge la sessione locale Express** (es. cookie, dati utente).
935
- * 4. Redirige l'utente all’URL di logout di Keycloak, che a sua volta redirige all'URL fornito.
936
- *
937
- * --- Parametri ---
938
- * @param {string} redirectTo - URL su cui l'utente verrà reindirizzato dopo il logout completo.
939
- *
940
- * --- Esempio di utilizzo ---
941
- * ```js
942
- * app.get('/logoutMiddleware',
943
- * keycloakAdapter.logoutMiddleware("http://localhost:3001/home"),
944
- * (req, res) => {
945
- * // Questa sezione non viene mai raggiunta
946
- * // Il middleware gestisce il logout e il redirect automaticamente
947
- * });
948
- * ```
949
- *
950
- * --- Nota ---
951
- * - Il middleware **non esegue mai la callback della route**, poiché gestisce completamente la risposta.
952
- * - Il parametro `redirectTo` deve corrispondere a un **valid redirect URI** configurato in Keycloak per il client.
953
- *
954
- * --- Requisiti ---
955
- * - Il client Keycloak deve avere configurato correttamente i `Valid Redirect URIs`.
956
- * - La sessione Express deve essere attiva (es: `express-session` correttamente inizializzato).
957
- */
958
-
959
- /**
960
- * ***************************** - ENGLISH - *******************************
961
- * `logoutMiddleware` Middleware
962
- *
963
- * This middleware is used to **force user logout**, removing the local session
964
- * and redirecting the user to Keycloak's logout endpoint according to its configuration.
965
- *
966
- * It is useful when:
967
- * - You want to completely log out the user,
968
- * - You want to **terminate the session on Keycloak** (not just locally),
969
- * - You want to redirect the user to a public page, such as a homepage, after logout.
970
- *
971
- * --- Behavior ---
972
- * 1. Retrieves the `id_token` of the authenticated user.
973
- * 2. Constructs the Keycloak logout URL including the token and the redirect URL.
974
- * 3. **Destroys the local Express session** (e.g., cookies, user data).
975
- * 4. Redirects the user to the Keycloak logout URL, which in turn redirects to the provided URL.
976
- *
977
- * --- Parameters ---
978
- * @param {string} redirectTo - URL to which the user will be redirected after complete logout.
979
- *
980
- * --- Usage Example ---
981
- * ```js
982
- * app.get('/logoutMiddleware',
983
- * keycloakAdapter.logoutMiddleware("http://localhost:3001/home"),
984
- * (req, res) => {
985
- * // This section is never reached
986
- * // The middleware handles logout and redirection automatically
987
- * });
988
- * ```
989
- *
990
- * --- Note ---
991
- * - The middleware **never executes the route callback**, as it fully handles the response.
992
- * - The `redirectTo` parameter must match a **valid redirect URI** configured in Keycloak for the client.
993
- *
994
- * --- Requirements ---
995
- * - The Keycloak client must have properly configured `Valid Redirect URIs`.
996
- * - The Express session must be active (e.g., `express-session` properly initialized).
997
- */
998
- exports.logoutMiddleware=function(redirectTo){
999
- return function(req,res,next){
1000
- const idToken = req.kauth?.grant?.id_token?.token;
1001
- const logoutUrl = keycloak.logoutUrl(redirectTo,idToken);
1002
- req.session.destroy(() => {
1003
- res.redirect(logoutUrl);
1004
- });
1005
- }
1006
- }
1007
-
1008
-
1009
- /**
1010
- * *************************** - ITALIANO - *****************************
1011
- * Funzione `login`
1012
- *
1013
- * Questa non è un middleware, ma una **funzione sincrona classica** che forza l'autenticazione dell'utente
1014
- * tramite Keycloak e, se non autenticato, lo redirige alla pagina di login.
1015
- * Dopo il login, l’utente viene reindirizzato all’URL specificato nel parametro `redirectTo`.
1016
- *
1017
- * --- Differenze rispetto a `loginMiddleware` ---
1018
- * - `loginMiddleware` gestisce tutto automaticamente **prima** della funzione handler della rotta.
1019
- * - `login` invece è una funzione **chiamabile manualmente all'interno della funzione di gestione della rotta**,
1020
- * offrendo **maggiore controllo** su quando e come eseguire il login.
1021
- *
1022
- * --- Parametri ---
1023
- * @param {Object} req - Oggetto `Request` di Express
1024
- * @param {Object} res - Oggetto `Response` di Express
1025
- * @param {string} redirectTo - URL verso cui redirigere l’utente dopo login avvenuto con successo
1026
- *
1027
- * --- Comportamento ---
1028
- * 1. Tenta di proteggere la richiesta tramite `keycloak.protect()`.
1029
- * 2. Se l’utente **è autenticato**, esegue `res.redirect(redirectTo)`.
1030
- * 3. Se **non autenticato**, Keycloak gestisce automaticamente la redirezione alla pagina di login.
1031
- *
1032
- * --- Esempio di utilizzo ---
1033
- * ```js
1034
- * app.get('/login', (req, res) => {
1035
- * // Logica della tua route
1036
- * // ...
1037
- *
1038
- * // Forza l'autenticazione, se necessario
1039
- * keycloakAdapter.login(req, res, "/home");
1040
- * });
1041
- * ```
1042
- *
1043
- * --- Note ---
1044
- * - La funzione può essere chiamata **dentro una route Express**, quindi permette logiche condizionali personalizzate.
1045
- * - Utile per scenari in cui solo certe condizioni devono forzare il login dell’utente.
1046
- *
1047
- * --- Requisiti ---
1048
- * - Keycloak deve essere correttamente inizializzato e integrato con Express.
1049
- * - I `Valid Redirect URIs` devono includere l’URL passato in `redirectTo`.
1050
- */
1051
-
1052
- /**
1053
- * ***************************** - ENGLISH - *******************************
1054
- * `login` Function
1055
- *
1056
- * This is not a middleware, but a **classic synchronous function** that forces user authentication
1057
- * via Keycloak and, if the user is not authenticated, redirects them to the login page.
1058
- * After successful login, the user is redirected to the URL specified in the `redirectTo` parameter.
1059
- *
1060
- * --- Differences from `loginMiddleware` ---
1061
- * - `loginMiddleware` handles everything automatically **before** the route handler function.
1062
- * - `login` instead is a function **that can be manually called inside the route handler**,
1063
- * offering **greater control** over when and how login is enforced.
1064
- *
1065
- * --- Parameters ---
1066
- * @param {Object} req - Express `Request` object
1067
- * @param {Object} res - Express `Response` object
1068
- * @param {string} redirectTo - URL to redirect the user to after successful login
1069
- *
1070
- * --- Behavior ---
1071
- * 1. Attempts to protect the request using `keycloak.protect()`.
1072
- * 2. If the user **is authenticated**, it performs `res.redirect(redirectTo)`.
1073
- * 3. If **not authenticated**, Keycloak automatically handles redirection to the login page.
1074
- *
1075
- * --- Usage Example ---
1076
- * ```js
1077
- * app.get('/login', (req, res) => {
1078
- * // Your route logic
1079
- * // ...
1080
- *
1081
- * // Force authentication if necessary
1082
- * keycloakAdapter.login(req, res, "/home");
1083
- * });
1084
- * ```
1085
- *
1086
- * --- Notes ---
1087
- * - The function can be called **within an Express route**, allowing for custom conditional logic.
1088
- * - Useful for scenarios where only certain conditions should trigger a login.
1089
- *
1090
- * --- Requirements ---
1091
- * - Keycloak must be properly initialized and integrated with Express.
1092
- * - `Valid Redirect URIs` must include the URL passed to `redirectTo`.
1093
- */
1094
-
1095
- exports.login=function(req,res,redirectTo){
1096
- keycloak.protect()(req,res,function(){
1097
- res.redirect(redirectTo);
1098
- });
1099
- }
1100
-
1101
-
1102
- /**
1103
- * *************************** - ITALIANO - *****************************
1104
- * Funzione `logout`
1105
- *
1106
- * Questa non è un middleware, ma una **funzione sincrona classica** che forza l'utente ad eseguire il logout
1107
- * tramite Keycloak. Oltre a terminare la sessione corrente (se presente), genera l’URL di logout di Keycloak
1108
- * e redirige il browser dell’utente all’indirizzo specificato.
1109
- *
1110
- * --- Differenze rispetto a `logoutMiddleware` ---
1111
- * - `logoutMiddleware` è progettato per essere usato direttamente come middleware nella definizione della rotta.
1112
- * - `logout` invece è una funzione **da richiamare all'interno della route**, utile per gestire il logout **condizionatamente**
1113
- * o all’interno di una logica più complessa.
1114
- *
1115
- * --- Parametri ---
1116
- * @param {Object} req - Oggetto `Request` di Express
1117
- * @param {Object} res - Oggetto `Response` di Express
1118
- * @param {string} redirectTo - URL verso cui redirigere l’utente dopo il logout
1119
- *
1120
- * --- Comportamento ---
1121
- * 1. Recupera l’`id_token` dal token Keycloak dell’utente corrente (se presente).
1122
- * 2. Costruisce l’URL di logout tramite `keycloak.logoutUrl()`.
1123
- * 3. Distrugge la sessione Express dell’utente.
1124
- * 4. Redirige l’utente al logout URL di Keycloak, che a sua volta reindirizzerà a `redirectTo`.
1125
- *
1126
- * --- Esempio di utilizzo ---
1127
- * ```js
1128
- * app.get('/logout', (req, res) => {
1129
- * // Eventuale logica personalizzata prima del logout
1130
- * // ...
1131
- *
1132
- * keycloakAdapter.logout(req, res, "http://localhost:3001/home");
1133
- * });
1134
- * ```
1135
- *
1136
- * --- Requisiti ---
1137
- * - L’utente deve essere autenticato con Keycloak e avere un token valido in `req.kauth.grant`.
1138
- * - L’URL specificato in `redirectTo` deve essere presente nei `Valid Redirect URIs` nel client di Keycloak.
1139
- */
1140
-
1141
- /**
1142
- * ***************************** - ENGLISH - *******************************
1143
- * `logout` Function
1144
- *
1145
- * This is not a middleware, but a **classic synchronous function** that forces the user to logout
1146
- * via Keycloak. In addition to terminating the current session (if any), it generates the Keycloak
1147
- * logout URL and redirects the user's browser to that address.
1148
- *
1149
- * --- Differences from `logoutMiddleware` ---
1150
- * - `logoutMiddleware` is designed to be used directly as middleware in the route definition.
1151
- * - `logout` instead is a function **to be called inside the route**, useful for handling logout
1152
- * **conditionally** or within more complex logic.
1153
- *
1154
- * --- Parameters ---
1155
- * @param {Object} req - Express `Request` object
1156
- * @param {Object} res - Express `Response` object
1157
- * @param {string} redirectTo - URL to redirect the user after logout
1158
- *
1159
- * --- Behavior ---
1160
- * 1. Retrieves the `id_token` from the current user's Keycloak token (if present).
1161
- * 2. Builds the logout URL using `keycloak.logoutUrl()`.
1162
- * 3. Destroys the user's Express session.
1163
- * 4. Redirects the user to the Keycloak logout URL, which in turn redirects to `redirectTo`.
1164
- *
1165
- * --- Usage Example ---
1166
- * ```js
1167
- * app.get('/logout', (req, res) => {
1168
- * // Any custom logic before logout
1169
- * // ...
1170
- *
1171
- * keycloakAdapter.logout(req, res, "http://localhost:3001/home");
1172
- * });
1173
- * ```
1174
- *
1175
- * --- Requirements ---
1176
- * - The user must be authenticated with Keycloak and have a valid token in `req.kauth.grant`.
1177
- * - The URL specified in `redirectTo` must be present in the `Valid Redirect URIs` in the Keycloak client.
1178
- */
1179
-
1180
- exports.logout=function(req,res,redirectTo){
1181
- const idToken = req.kauth?.grant?.id_token?.token;
1182
- const logoutUrl = keycloak.logoutUrl(redirectTo,idToken);
1183
- req.session.destroy(() => {
1184
- res.redirect(logoutUrl);
1185
- });
1186
- }
1187
-
1188
-
1189
-
1190
-
1191
- /*
1192
- <table><tbody>
1193
- <tr><th align="left">Alessandro Romanino</th><td><a href="https://github.com/aromanino">GitHub/aromanino</a></td><td><a href="mailto:a.romanino@gmail.com">mailto:a.romanino@gmail.com</a></td></tr>
1194
- <tr><th align="left">Guido Porruvecchio</th><td><a href="https://github.com/gporruvecchio">GitHub/porruvecchio</a></td><td><a href="mailto:guido.porruvecchio@gmail.com">mailto:guido.porruvecchio@gmail.com</a></td></tr>
1195
- </tbody></table>
1196
- * */
1197
-
1198
-
1199
-
1200
-