keycloak-express-middleware 3.0.8 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +143 -3
  2. package/index.js +1215 -1205
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -13,6 +13,112 @@ it is based on **'keycloak-connect'**, and **'express-session'**
13
13
  - ⚙️ Configurable Keycloak client and realm settings
14
14
  - 👤 User info extraction from token
15
15
  - 🌍 CORS support and integration with frontend apps (SPA or mobile)
16
+ ---
17
+ ## ⚠️ keycloak-express-middleware evolution by Version 4.0.0
18
+ The new version of keycloak-express-middleware introduces a substantial evolution in its architecture.
19
+ It now embraces an object-oriented paradigm, which means each instance of the middleware is self-contained and independent.
20
+ Concretely, you can instantiate the library multiple times within the same application—each time pointing to a different client in Keycloak
21
+ and the instances will not share internal connections or state across modules.
22
+ This is a major shift from the previous version(until 3.0.9), where the library maintained a single shared
23
+ connection and did not support using distinct Keycloak clients simultaneously within the same
24
+ application scope. By moving to this new ***one instance = one client*** model, you gain the flexibility to support scenarios such as:
25
+ - a single Express application acting as multiple Keycloak clients, each with different realms, client-ids or roles,
26
+ - isolating middleware logic per client without risking cross-contamination of sessions or grants,
27
+ - simplifying multitenancy or micro-service architectures where different parts of an app authenticate against different Keycloak clients.
28
+
29
+ **To summarize:** the new version enables multi-client usage within the same app by turning the middleware into configurable,
30
+ independent object instances — something that the earlier version did not support.
31
+
32
+ ### 🏗️ Migration Guide: From Old to New Version
33
+
34
+ 🧩 Old Version (pre–object-oriented)
35
+ ```js
36
+ // OLD VERSION UNTILL 3.0.9
37
+ const express = require('express');
38
+ const keycloackAdapter = require('keycloak-express-middleware');
39
+
40
+ const app = express();
41
+ await keycloackAdapter.configure(app,{
42
+ "realm": "Realm-Project",
43
+ "auth-server-url": "https://YourKeycloakUrl:30040/",
44
+ "ssl-required": "external",
45
+ "resource": "keycloackclientName",
46
+ "credentials": {
47
+ "secret": "aaaaaaaaaa"
48
+ },
49
+ "confidential-port": 0
50
+ },
51
+ {
52
+ session:{
53
+ secret: 'mySecretForSession',
54
+ }
55
+ });
56
+
57
+ // Example of protection with keycloackAdapter.protectMiddleware middleware
58
+ // whith a static client role validation string
59
+ // Access is allowed only for authenticated admin users
60
+ app.get('/privateStaticClientRole', keycloackAdapter.protectMiddleware("admin"), (req, res) => {
61
+ // "Your Custom Code"
62
+ res.send("Is its admin.");
63
+ });
64
+ ```
65
+
66
+ 🆕 New Version (Object-Oriented Design) Up to 4.0.0
67
+
68
+ ```js
69
+ // NEW VERSION UP TO 4.0.0
70
+ const express = require('express');
71
+ const { keycloackAdapter } = require('keycloak-express-middleware');
72
+
73
+ const app = express();
74
+
75
+ // Create independent Keycloak clients
76
+ const keycloakA = new keycloackAdapter(app,{
77
+ "realm": "Realm-Project",
78
+ "auth-server-url": "https://YourKeycloakUrl:30040/",
79
+ "ssl-required": "external",
80
+ "resource": "keycloackclientName_A",
81
+ "credentials": {
82
+ "secret": "aaaaaaaaaa"
83
+ },
84
+ "confidential-port": 0
85
+ },
86
+ {
87
+ session:{
88
+ secret: 'mySecretForSession',
89
+ }
90
+ });
91
+
92
+ const keycloakB = new keycloackAdapter(app,{
93
+ "realm": "Realm-Project",
94
+ "auth-server-url": "https://YourKeycloakUrl:30040/",
95
+ "ssl-required": "external",
96
+ "resource": "keycloackclientName_B",
97
+ "credentials": {
98
+ "secret": "aaaaaaaaaa"
99
+ },
100
+ "confidential-port": 0
101
+ },
102
+ {
103
+ session:{
104
+ secret: 'mySecretForSession',
105
+ }
106
+ });
107
+
108
+
109
+
110
+ // Example protected routes
111
+ app.get('/clientA/secure', keycloakA.protect(), (req, res) => {
112
+ res.send('Protected route for Client A');
113
+ });
114
+
115
+ app.get('/clientB/secure', keycloakB.protect(), (req, res) => {
116
+ res.send('Protected route for Client B');
117
+ });
118
+
119
+ app.listen(3000, () => console.log('Server running on port 3000'));
120
+ ```
121
+
16
122
  ---
17
123
  ## 🚀 Installation
18
124
  ```bash
@@ -42,11 +148,35 @@ the Keycloak Admin Console → clients (left sidebar) → choose your client →
42
148
  ## 📄 Usage Example
43
149
  ```js
44
150
  const express = require('express');
45
- const keycloackAdapter = require('keycloak-express-middleware');
151
+ const keycloackAdapterClass = require('keycloak-express-middleware'); // import keycloackAdapter from 'keycloak-express-middleware';
152
+
153
+ /*
154
+ Old Style until version 3.0.9
155
+ const keycloackAdapter = require('keycloak-express-middleware'); // import keycloackAdapter from 'keycloak-express-middleware';
156
+ */
46
157
 
47
158
  const app = express();
48
159
 
49
160
 
161
+ // Configure and Initialize Keycloak adapter
162
+ keycloackAdapter= new keycloackAdapterClass(app,{
163
+ "realm": "Realm-Project",
164
+ "auth-server-url": "https://YourKeycloakUrl:30040/",
165
+ "ssl-required": "external",
166
+ "resource": "keycloackclientName",
167
+ "credentials": {
168
+ "secret": "aaaaaaaaaa"
169
+ },
170
+ "confidential-port": 0
171
+ },
172
+ {
173
+ session:{
174
+ secret: 'mySecretForSession',
175
+ }
176
+ });
177
+
178
+ /*
179
+ OLD STYLE UNTIL VERSION 3.0.9
50
180
  // Configure and Initialize Keycloak adapter
51
181
  await keycloackAdapter.configure(app,{
52
182
  "realm": "Realm-Project",
@@ -63,6 +193,8 @@ await keycloackAdapter.configure(app,{
63
193
  secret: 'mySecretForSession',
64
194
  }
65
195
  });
196
+ */
197
+
66
198
 
67
199
 
68
200
  // -------------- Public route -----------------------
@@ -275,7 +407,9 @@ It is an async function and returns a promise
275
407
 
276
408
  **` -- @parameters -- `**
277
409
  - **app**: `[required]` Express application instance (e.g., const app = express();)
278
- - **keyCloakConfig:** `[required]`JSON object containing the Keycloak client configuration. This can be obtained from the Keycloak admin console: Clients → [client name] → Installation → "Keycloak OIDC JSON" → Download
410
+ - **keyCloakConfig:** `[required]`JSON object containing the Keycloak client configuration. This can be obtained from the Keycloak admin console: Clients → [client name] → Installation → "Keycloak OIDC JSON" → Download. It accepts other parameter not defined in downloaded config like:
411
+ - "verifyTokenAudience": If verify-token-audience = true, the adapter rejects the token if its audience does not match the client that receives it.
412
+ - "bearerOnly": for public client. if it is set to true the client cannot call login services
279
413
  Example:
280
414
  ```json
281
415
 
@@ -439,7 +573,9 @@ protected by flexible policies.
439
573
 
440
574
  **` -- @parameters -- `**
441
575
  - **conditions:** a check control string or function
442
- - ***As a string:*** contain the name of the resource or permission to check
576
+ - ***As a string or array of strings:*** contain the name of the resource or permission to check. String Examples:
577
+ - ui-admin-resource: Apply the policies associated to the `ui-admin-resource` resource
578
+ - ui-admin-resource:write: Apply the policies associateo to `ui-admin-resource`resource and `write` scope
443
579
  - ***as a function:*** custom check function with signature:
444
580
  ***`function(token, req, callback)`***
445
581
  - token: decoded Keycloak token
@@ -484,6 +620,10 @@ app.get('/onlyAdminroute', keycloakAdapter.enforcerMiddleware('ui-admin-resource
484
620
  res.send('You are an authorized admin for this resource');
485
621
  });
486
622
 
623
+ app.get('/onlyAdminrouteByScope', keycloakAdapter.enforcerMiddleware('ui-admin-resource:write'), (req, res) => {
624
+ res.send('You are an authorized admin for this resource');
625
+ });
626
+
487
627
  // Check with custom function (async with callback)
488
628
  app.get('/onlyAdminrouteByfunction', keycloakAdapter.enforcerMiddleware(function(token, req, callback) {
489
629
  token.hasPermission('ui-admin-resource', function(permission) {