|
15 | 15 | ---
|
16 | 16 |
|
17 | 17 | ## Introduction
|
18 |
| -**hapi-auth-keycloak** is a plugin for [hapi.js][hapijs] which enables to protect your endpoints in a smart but professional manner using [Keycloak][keycloak] as authentication service. It is inspired by the related [express.js middleware][keycloak-node]. The plugin validates the passed [`Bearer` token][bearer] online with help of the [Keycloak][keycloak] server and optionally caches successfully validated tokens and the related user data using [`catbox`][catbox]. The caching enables a fast processing although the user data don't get changed until the token expires. It plays well with the [hapi.js][hapijs]-integrated [authentication feature][hapi-route-options]. Besides the authentication strategy it is possible to validate tokens by yourself, e.g. to authenticate incoming websocket or queue messages. |
| 18 | +**hapi-auth-keycloak** is a plugin for [hapi.js][hapijs] which enables to protect your endpoints in a smart but professional manner using [Keycloak][keycloak] as authentication service. It is inspired by the related [express.js middleware][keycloak-node]. The plugin validates the passed [`Bearer` token][bearer] offline with a provided public key or online with help of the [Keycloak][keycloak] server. Optionally, the successfully validated tokens and the related user data get cached using [`catbox`][catbox]. The caching enables a fast processing although the user data don't get changed until the token expires. It plays well with the [hapi.js][hapijs]-integrated [authentication feature][hapi-route-options]. Besides the authentication strategy it is possible to validate tokens by yourself, e.g. to authenticate incoming websocket or queue messages. |
19 | 19 |
|
20 | 20 | This plugin is implemented in ECMAScript 6 without any transpilers like [`babel`][babel].<br/>
|
21 | 21 | Additionally [`standard`][standardjs] and [`ava`][avajs] are used to grant a high quality implementation.<br/>
|
@@ -60,11 +60,10 @@ Finally register the plugin, set the correct options and the authentication stra
|
60 | 60 | server.register({
|
61 | 61 | register: authKeycloak,
|
62 | 62 | options: {
|
63 |
| - client: { |
64 |
| - realmUrl: 'https://localhost:8080/auth/realms/testme', |
65 |
| - clientId: 'foobar', |
66 |
| - secret: '1234-bar-4321-foo' |
67 |
| - }, |
| 63 | + realmUrl: 'https://localhost:8080/auth/realms/testme', |
| 64 | + clientId: 'foobar', |
| 65 | + secret: '1234-bar-4321-foo', |
| 66 | + minTimeBetweenJwksRequests: 15, |
68 | 67 | cache: {},
|
69 | 68 | userInfo: ['name', 'email']
|
70 | 69 | }
|
@@ -108,27 +107,42 @@ server.route([
|
108 | 107 | ## API
|
109 | 108 | #### Plugin Options
|
110 | 109 |
|
111 |
| -- `client {Object}` — The configuration of [`keycloak-auth-utils`][keycloak-auth-utils] its [`GrantManager`][keycloak-auth-utils-gm]. The configuration requires at least: |
112 |
| - - `realmUrl {string}`: The absolute uri of the Keycloak realm<br/> |
113 |
| - Example: `https://localhost:8080/auth/realms/testme` |
114 |
| - - `clientId {string}` The identifier of the Keycloak client<br/> |
115 |
| - Example: `foobar` |
116 |
| - - `secret {string}` The related secret of the Keycloak client<br/> |
117 |
| - Example: `1234-bar-4321-foo` |
| 110 | +> **Hint**: By default, the Keycloak server has built-in two ways to authenticate the client: client ID and client secret, or with a signed JWT. This plugin supports both. Check the description of `secret` and `publicKey` for further information. |
| 111 | +> |
| 112 | +> If the signed JWTs are used as online strategy, ensure that the identifier of the related realm key (`kid`) is included in their header. |
| 113 | +> |
| 114 | +> | Strategy | Online | Option | |
| 115 | +> |:------------|:------:|:------------| |
| 116 | +> | ID + Secret | x | `secret` | |
| 117 | +> | Signed JWT | x | | |
| 118 | +> | Signed JWT | | `publicKey` | |
| 119 | +
|
| 120 | +- `realmUrl {string}`: The absolute uri of the Keycloak realm.<br/> |
| 121 | +Required. Example: `https://localhost:8080/auth/realms/testme`<br/> |
| 122 | + |
| 123 | +- `clientId {string}` The identifier of the Keycloak client/application.<br/> |
| 124 | +Required. Example: `foobar`<br/> |
| 125 | + |
| 126 | +- `secret {string}` The related secret of the Keycloak client/application.<br/> |
| 127 | +Defining this option enables the traditional method described in the OAuth2 specification. To perform an almost offline validation enable the cache — a simple offline verfication with symmetric keys is not provided for security reasons.<br/> |
| 128 | +Optional. Example: `1234-bar-4321-foo`<br/> |
118 | 129 |
|
119 |
| - Furthermore it may be necessary to reduce `minTimeBetweenJwksRequests`.<br/> |
120 |
| - Required. |
| 130 | +- `publicKey {string}` The related public key of the Keycloak client/application.<br/> |
| 131 | +Defining this option enables the offline validation using signed JWTs. The public key has to be in [PEM][pem] or [JWK][jwk] format. If you define neither `secret` nor `public` key, the plugin assumes that a signed JWT has to be validated – it retrieves the public key itself from `{realmUrl}/protocol/openid-connect/certs`. The offline strategy its performance is higher but the online strategy is the most flexible one.<br/> |
| 132 | +Optional. |
121 | 133 |
|
122 |
| -- `cache {Object|false}` — The configuration of the [hapi.js cache](https://hapijs.com/api#servercacheoptions) powered by [catbox][catbox].<br/> |
123 |
| -If `false` the cache is disabled. Use an empty object (`{}`) to use the built-in default cache.<br/> |
| 134 | +- `minTimeBetweenJwksRequests {number}` – The minimum time between JWKS requests in seconds.<br/> |
| 135 | +The value have to be a positive integer.<br/> |
| 136 | +Optional. Default: `0`. |
| 137 | + |
| 138 | +- `cache {Object|boolean}` — The configuration of the [hapi.js cache](https://hapijs.com/api#servercacheoptions) powered by [catbox][catbox].<br/> |
| 139 | +If `false` the cache is disabled. Use `true` or an empty object (`{}`) to use the built-in default cache.<br/> |
124 | 140 | Optional. Default: `false`.
|
125 | 141 |
|
126 | 142 | - `userInfo {Array.<?string>}` — List of properties which should be included in the `request.auth.credentials` object besides `scope` and `sub`.<br/>
|
127 | 143 | Optional. Default: `[]`.<br/>
|
128 | 144 |
|
129 | 145 | #### `server.kjwt.validate(field {string}, done {Function})`
|
130 |
| -Uses internally [`GrantManager.prototype.validateAccessToken()`][keycloak-auth-utils-gm-validate]. |
131 |
| - |
132 | 146 | - `field {string}` — The `Bearer` field, including the scheme (`bearer`) itself.<br/>
|
133 | 147 | Example: `bearer 12345.abcde.67890`.<br/>
|
134 | 148 | Required.
|
@@ -173,11 +187,10 @@ process.on('SIGINT', () => {
|
173 | 187 | server.register({
|
174 | 188 | register: authKeycloak,
|
175 | 189 | options: {
|
176 |
| - client: { |
177 |
| - realmUrl: 'https://localhost:8080/auth/realms/testme', |
178 |
| - clientId: 'foobar', |
179 |
| - secret: '1234-bar-4321-foo' |
180 |
| - }, |
| 190 | + realmUrl: 'https://localhost:8080/auth/realms/testme', |
| 191 | + clientId: 'foobar', |
| 192 | + secret: '1234-bar-4321-foo', |
| 193 | + minTimeBetweenJwksRequests: 15, |
181 | 194 | cache: {},
|
182 | 195 | userInfo: ['name', 'email']
|
183 | 196 | }
|
@@ -227,7 +240,5 @@ For further information read the [contributing guideline](CONTRIBUTING.md).
|
227 | 240 | [catbox]: https://github.com/hapijs/catbox
|
228 | 241 | [bearer]: https://tools.ietf.org/html/rfc6750
|
229 | 242 | [hapi-route-options]: https://hapijs.com/api#route-options
|
230 |
| -[keycloak-auth-utils]: http://www.keycloak.org/keycloak-nodejs-auth-utils/ |
231 |
| -[keycloak-auth-utils-gm]: http://www.keycloak.org/keycloak-nodejs-auth-utils/grant-manager.js.html |
232 |
| -[keycloak-auth-utils-gm-obtain]: http://www.keycloak.org/keycloak-nodejs-auth-utils/grant-manager.js.html#obtainDirectly |
233 |
| -[keycloak-auth-utils-gm-validate]: http://www.keycloak.org/keycloak-nodejs-auth-utils/grant-manager.js.html#validateAccessToken |
| 243 | +[jwk]: https://tools.ietf.org/html/rfc7517 |
| 244 | +[pem]: https://tools.ietf.org/html/rfc1421 |
0 commit comments