keycloak-angular 7.3.0 → 8.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.
Files changed (44) hide show
  1. package/README.md +136 -155
  2. package/bundles/keycloak-angular.umd.js +401 -327
  3. package/bundles/keycloak-angular.umd.js.map +1 -1
  4. package/bundles/keycloak-angular.umd.min.js +1 -15
  5. package/bundles/keycloak-angular.umd.min.js.map +1 -1
  6. package/esm2015/keycloak-angular.js +1 -1
  7. package/esm2015/lib/core/core.module.js +16 -18
  8. package/esm2015/lib/core/interceptors/keycloak-bearer.interceptor.js +6 -9
  9. package/esm2015/lib/core/interfaces/keycloak-event.js +1 -1
  10. package/esm2015/lib/core/interfaces/keycloak-options.js +2 -1
  11. package/esm2015/lib/core/services/keycloak-auth-guard.js +1 -1
  12. package/esm2015/lib/core/services/keycloak.service.js +28 -42
  13. package/esm2015/lib/keycloak-angular.module.js +8 -10
  14. package/esm2015/public_api.js +1 -1
  15. package/fesm2015/keycloak-angular.js +54 -78
  16. package/fesm2015/keycloak-angular.js.map +1 -1
  17. package/keycloak-angular.d.ts +0 -0
  18. package/keycloak-angular.metadata.json +1 -1
  19. package/lib/core/core.module.d.ts +0 -0
  20. package/lib/core/interceptors/keycloak-bearer.interceptor.d.ts +0 -0
  21. package/lib/core/interfaces/keycloak-event.d.ts +0 -0
  22. package/lib/core/interfaces/keycloak-options.d.ts +1 -2
  23. package/lib/core/services/keycloak-auth-guard.d.ts +0 -0
  24. package/lib/core/services/keycloak.service.d.ts +2 -2
  25. package/lib/keycloak-angular.module.d.ts +0 -0
  26. package/package.json +9 -14
  27. package/public_api.d.ts +0 -2
  28. package/esm2015/lib/core/interfaces/keycloak-config.js +0 -1
  29. package/esm2015/lib/core/utils/to-promise.js +0 -10
  30. package/esm5/keycloak-angular.js +0 -2
  31. package/esm5/lib/core/core.module.js +0 -26
  32. package/esm5/lib/core/interceptors/keycloak-bearer.interceptor.js +0 -48
  33. package/esm5/lib/core/interfaces/keycloak-config.js +0 -1
  34. package/esm5/lib/core/interfaces/keycloak-event.js +0 -11
  35. package/esm5/lib/core/interfaces/keycloak-options.js +0 -1
  36. package/esm5/lib/core/services/keycloak-auth-guard.js +0 -40
  37. package/esm5/lib/core/services/keycloak.service.js +0 -328
  38. package/esm5/lib/core/utils/to-promise.js +0 -10
  39. package/esm5/lib/keycloak-angular.module.js +0 -15
  40. package/esm5/public_api.js +0 -7
  41. package/fesm5/keycloak-angular.js +0 -461
  42. package/fesm5/keycloak-angular.js.map +0 -1
  43. package/lib/core/interfaces/keycloak-config.d.ts +0 -9
  44. package/lib/core/utils/to-promise.d.ts +0 -7
package/README.md CHANGED
@@ -1,22 +1,23 @@
1
1
  # Keycloak Angular
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
- [![Build Status](https://travis-ci.org/mauriciovigolo/keycloak-angular.svg?branch=master)](https://travis-ci.org/mauriciovigolo/keycloak-angular)
5
- [![Known Vulnerabilities](https://snyk.io/test/github/mauriciovigolo/keycloak-angular/badge.svg)](https://snyk.io/test/github/mauriciovigolo/keycloak-angular)
6
- [![npm version](https://badge.fury.io/js/keycloak-angular.svg)](https://badge.fury.io/js/keycloak-angular)
7
- ![npm](https://img.shields.io/npm/dm/keycloak-angular.svg)
8
- [![All Contributors](https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square)](#contributors)
9
- [![Slack](https://slackin-iijwrzzihr.now.sh/badge.svg)](https://slackin-iijwrzzihr.now.sh)
3
+ <!-- prettier-ignore-start -->
4
+ [![License: MIT][license-mit-badge]][license-mit]
5
+ [![Build Status][build-badge]][build]
6
+ [![Known Vulnerabilities][vulnerabilities-badge]][vulnerabilities]
7
+ [![npm version][npm-version-badge]][npm-version]
8
+ [![npm][npm-badge]][npm]
9
+ [![All Contributors][contributors-badge]](#contributors)
10
+ [![Discord][discord-badge]][discord]
11
+ <!-- prettier-ignore-end -->
10
12
 
11
13
  > Easy Keycloak setup for Angular applications.
12
14
 
13
15
  ---
14
16
 
15
17
  - [About](#about)
16
- - [Install](#install)
18
+ - [Installation](#installation)
17
19
  - [Setup](#setup)
18
- - [Angular](#angular)
19
- - [Keycloak](#keycloak)
20
+ - [Example project](#example-project)
20
21
  - [AuthGuard](#authguard)
21
22
  - [HttpClient Interceptor](#httpclient-interceptor)
22
23
  - [Contributors](#contributors)
@@ -26,9 +27,9 @@
26
27
 
27
28
  ## About
28
29
 
29
- This library helps you to use [keycloak-js](https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter) in Angular > v4.3 applications providing the following features:
30
+ This library helps you to use [keycloak-js](https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter) in Angular applications providing the following features:
30
31
 
31
- - A **Keycloak Service** which wraps the keycloak-js methods to be used in Angular, giving extra
32
+ - A **Keycloak Service** which wraps the `keycloak-js` methods to be used in Angular, giving extra
32
33
  functionalities to the original functions and adding new methods to make it easier to be consumed by
33
34
  Angular applications.
34
35
  - Generic **AuthGuard implementation**, so you can customize your own AuthGuard logic inheriting the authentication logic and the roles load.
@@ -37,171 +38,145 @@ This library helps you to use [keycloak-js](https://www.keycloak.org/docs/latest
37
38
  - This documentation also assists you to configure the keycloak in your Angular applications and with
38
39
  the client setup in the admin console of your keycloak installation.
39
40
 
40
- ## Install
41
+ ## Installation
41
42
 
42
- ### keycloak-angular
43
+ Run the following command to install both Keycloak Angular and the official Keycloak client library:
43
44
 
44
45
  ```sh
45
- npm i --save keycloak-angular
46
+ npm install keycloak-angular keycloak-js
46
47
  ```
47
48
 
48
- ### keycloak-js
49
+ Note that `keycloak-js` is a peer dependency of Keycloak Angular. This change allows greater flexibility of choosing the right version of the Keycloak client version for your project.
49
50
 
50
- > Since keycloak-angular v.7.0.0, the [keycloak-js](https://www.npmjs.com/package/keycloak-js) dependency became a peer dependency. This change allows greater flexibility for choosing the keycloak-js adapter version and follows the [project documentation recommendation](https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter).
51
+ ### Versions
51
52
 
52
- ```sh
53
- npm i --save keycloak-js@version
54
- ```
53
+ | Angular | keycloak-angular | keycloak-js | Support |
54
+ | :-----: | :--------------: | :-----------------------: | :-----------------: |
55
+ | 11.x.x | 8.1.x | 10 - 12 | Bugs / New Features |
56
+ | 10.x.x | 8.x.x | 10 - 11 | Bugs |
57
+ | 9.x.x | 7.3.x | 3.4.3 - 10 (excluding v7) | Bugs |
58
+ | 8.x.x | 7.2.x | 3.4.3 - 9 (excluding v7) | Bugs |
55
59
 
56
- #### Choosing the keycloak-js version
60
+ #### Choosing the right keycloak-js version
57
61
 
58
- The keycloak-js adapter documentation recommends to use the same version of your Keycloak / RH-SSO (Red Hat Single Sign On) installation.
62
+ The Keycloak client documentation recommends to use the same version of your Keycloak installation.
59
63
 
60
64
  > A best practice is to load the JavaScript adapter directly from Keycloak Server as it will automatically be updated when you upgrade the server. If you copy the adapter to your web application instead, make sure you upgrade the adapter only after you have upgraded the server.
61
65
 
62
66
  ## Setup
63
67
 
64
- ### Angular
65
-
66
- The following topics explain two different ways to bootstrap the library and configure keycloak-angular. The first one is by using the APP_INITIALIZER token and the second option uses ngDoBootstrap. You will have to choose one of them.
68
+ In order to make sure Keycloak is initialized when your application is bootstrapped you will have to add an `APP_INITIALIZER` provider to your `AppModule`. This provider will call the `initializeKeycloak` factory function shown below which will set up the Keycloak service so that it can be used in your application.
67
69
 
68
- #### Using APP_INITIALIZER
70
+ Use the code provided below as an example and implement it's functionality in your application. In this process ensure that the configuration you are providing matches that of your client as configured in Keycloak.
69
71
 
70
- The KeycloakService can be initialized during the application loading, using the [APP_INITIALIZER](https://angular.io/api/core/APP_INITIALIZER) token.
71
-
72
- ##### AppModule
73
-
74
- ```js
75
- import { NgModule, APP_INITIALIZER } from '@angular/core';
76
- import { KeycloakService, KeycloakAngularModule } from 'keycloak-angular';
77
- import { initializer } from './utils/app-init';
72
+ ```ts
73
+ import { APP_INITIALIZER, NgModule } from '@angular/core';
74
+ import { BrowserModule } from '@angular/platform-browser';
75
+ import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
76
+ import { AppRoutingModule } from './app-routing.module';
77
+ import { AppComponent } from './app.component';
78
+
79
+ function initializeKeycloak(keycloak: KeycloakService) {
80
+ return () =>
81
+ keycloak.init({
82
+ config: {
83
+ url: 'http://localhost:8080/auth',
84
+ realm: 'your-realm',
85
+ clientId: 'your-client-id',
86
+ },
87
+ initOptions: {
88
+ onLoad: 'check-sso',
89
+ silentCheckSsoRedirectUri:
90
+ window.location.origin + '/assets/silent-check-sso.html',
91
+ },
92
+ });
93
+ }
78
94
 
79
95
  @NgModule({
80
- imports: [KeycloakAngularModule],
96
+ declarations: [AppComponent],
97
+ imports: [AppRoutingModule, BrowserModule, KeycloakAngularModule],
81
98
  providers: [
82
99
  {
83
100
  provide: APP_INITIALIZER,
84
- useFactory: initializer,
101
+ useFactory: initializeKeycloak,
85
102
  multi: true,
86
- deps: [KeycloakService]
87
- }
88
- ]
103
+ deps: [KeycloakService],
104
+ },
105
+ ],
106
+ bootstrap: [AppComponent],
89
107
  })
90
108
  export class AppModule {}
91
109
  ```
92
110
 
93
- ##### Initializer Function
111
+ In the example we have set up Keycloak to use a silent `check-sso`. With this feature enabled, your browser will not do a full redirect to the Keycloak server and back to your application, instead this action will be performed in a hidden iframe, so your application resources only need to be loaded and parsed once by the browser when the app is initialized and not again after the redirect back from Keycloak to your app.
94
112
 
95
- This function can be named and placed in the way you think is most appropriate. In the
96
- underneath example it was placed in a separate file `app-init.ts` and the function was called
97
- `initializer`.
113
+ To ensure that Keycloak can communicate through the iframe you will have to serve a static HTML asset from your application at the location provided in `silentCheckSsoRedirectUri`.
98
114
 
99
- ```js
100
- import { KeycloakService } from 'keycloak-angular';
115
+ Create a file called `silent-check-sso.html` in the `assets` directory of your application and paste in the contents as seen below.
101
116
 
102
- export function initializer(keycloak: KeycloakService): () => Promise<any> {
103
- return (): Promise<any> => keycloak.init();
104
- }
105
- ```
106
-
107
- #### Using ngDoBootstrap
108
-
109
- The KeycloakService can be initialized before the application loading. When the Keycloak initialization is successful the application is bootstrapped.
110
-
111
- This has two major benefits.
112
-
113
- 1. This is faster because the application isn't fully bootstrapped and
114
- 1. It prevents a moment when you see the application without having the authorization.
115
-
116
- #### AppModule
117
-
118
- ```js
119
- import { NgModule, DoBootstrap, ApplicationRef } from '@angular/core';
120
- import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
121
-
122
- const keycloakService = new KeycloakService();
123
-
124
- @NgModule({
125
- imports: [KeycloakAngularModule],
126
- providers: [
127
- {
128
- provide: KeycloakService,
129
- useValue: keycloakService
130
- }
131
- ],
132
- entryComponents: [AppComponent]
133
- })
134
- export class AppModule implements DoBootstrap {
135
- ngDoBootstrap(appRef: ApplicationRef) {
136
- keycloakService
137
- .init()
138
- .then(() => {
139
- console.log('[ngDoBootstrap] bootstrap app');
140
-
141
- appRef.bootstrap(AppComponent);
142
- })
143
- .catch(error => console.error('[ngDoBootstrap] init Keycloak failed', error));
144
- }
145
- }
117
+ ```html
118
+ <html>
119
+ <body>
120
+ <script>
121
+ parent.postMessage(location.href, location.origin);
122
+ </script>
123
+ </body>
124
+ </html>
146
125
  ```
147
126
 
148
- **Hint:** Do not forget to remove `bootstrap: [AppComponent]` from NgModule decorator options.
149
-
150
- ### Keycloak
151
-
152
- Besides configuring the keycloak lib in your application it is also necessary to setup the
153
- access - scope for the **account** client.
154
-
155
- In this documentation we assume that you already installed and configured your Keycloak
156
- instance, as well created the client app.
157
-
158
- **Hint:** If you need to create an environment for testing purposes, try out the [Keycloak demo](http://www.keycloak.org/downloads.html) or the official [keycloak docker image](https://hub.docker.com/r/jboss/keycloak/).
159
-
160
- #### Client configuration
127
+ If you want to know more about these options and various other capabilities of the Keycloak client is recommended to read the [JavaScript Adapter documentation](https://www.keycloak.org/docs/latest/securing_apps/#_javascript_adapter).
161
128
 
162
- When requesting the method to get the User's Profile, the client app should have the scope and access to the account **view-profile** role. To do it, access **Clients** :arrow_right: **My-app** :arrow_right: **Scope**. Select the **account** app in Client Roles and assign the view-profile role.
129
+ ## Example project
163
130
 
164
- ![keycloak-account-scope](./docs/images/keycloak-account-scope.png)
165
-
166
- Please be aware that when accessing the `https://keycloak/auth/realms/REALM/account` endpoint, if this role is not configured, a misleading `No 'Access-Control-Allow-Origin'` error might show up. If that happens, this role should be enough to fix it, no changes in the Web Origin of the account client is needed.
131
+ If you want to see an complete overview a pre-configured client together with a working Keycloak server make sure to check out the [example project](example/README.md) in this repository.
167
132
 
168
133
  ## AuthGuard
169
134
 
170
- A generic AuthGuard, `KeycloakAuthGuard`, was created to help you bootstrap your security configuration and avoid duplicate code. This class already checks if the user is logged in and get the list of roles from the authenticated user, provided by the keycloak instance. In your implementation you just need to implement the desired security logic.
135
+ A generic AuthGuard, `KeycloakAuthGuard` is provided to help you protect authenticated routes in your application. This guard provides you with information to see if the user is logged in and a list of roles from that belong to the user. In your implementation you just need to implement the desired logic to protect your routes.
171
136
 
172
- Example:
137
+ To write your own implementation extend the `KeycloakAuthGuard` class and implement the `isAccessAllowed` method. For example the code provided below checks if the user is authenticated and if not the user is requested to sign in. It also checks if the user has the correct roles which could be provided by passing the `roles` field into the data of the route.
173
138
 
174
- ```js
139
+ ```ts
175
140
  import { Injectable } from '@angular/core';
176
- import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
141
+ import {
142
+ ActivatedRouteSnapshot,
143
+ Router,
144
+ RouterStateSnapshot,
145
+ } from '@angular/router';
177
146
  import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
178
147
 
179
148
  @Injectable({
180
- providedIn: 'root'
149
+ providedIn: 'root',
181
150
  })
182
- export class CanAuthenticationGuard extends KeycloakAuthGuard implements CanActivate {
183
- constructor(protected router: Router, protected keycloakAngular: KeycloakService) {
184
- super(router, keycloakAngular);
151
+ export class AuthGuard extends KeycloakAuthGuard {
152
+ constructor(
153
+ protected readonly router: Router,
154
+ protected readonly keycloak: KeycloakService
155
+ ) {
156
+ super(router, keycloak);
185
157
  }
186
158
 
187
- isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
188
- return new Promise((resolve, reject) => {
189
- if (!this.authenticated) {
190
- this.keycloakAngular.login()
191
- .catch(e => console.error(e));
192
- return reject(false);
193
- }
194
-
195
- const requiredRoles: string[] = route.data.roles;
196
- if (!requiredRoles || requiredRoles.length === 0) {
197
- return resolve(true);
198
- } else {
199
- if (!this.roles || this.roles.length === 0) {
200
- resolve(false);
201
- }
202
- resolve(requiredRoles.every(role => this.roles.indexOf(role) > -1));
203
- }
204
- });
159
+ public async isAccessAllowed(
160
+ route: ActivatedRouteSnapshot,
161
+ state: RouterStateSnapshot
162
+ ) {
163
+ // Force the user to log in if currently unauthenticated.
164
+ if (!this.authenticated) {
165
+ await this.keycloak.login({
166
+ redirectUri: window.location.origin + state.url,
167
+ });
168
+ }
169
+
170
+ // Get the roles required from the route.
171
+ const requiredRoles = route.data.roles;
172
+
173
+ // Allow the user to to proceed if no additional roles are required to access the route.
174
+ if (!(requiredRoles instanceof Array) || requiredRoles.length === 0) {
175
+ return true;
176
+ }
177
+
178
+ // Allow the user to proceed if all the required roles are present.
179
+ return requiredRoles.every((role) => this.roles.includes(role));
205
180
  }
206
181
  }
207
182
  ```
@@ -210,25 +185,17 @@ export class CanAuthenticationGuard extends KeycloakAuthGuard implements CanActi
210
185
 
211
186
  By default all HttpClient requests will add the Authorization header in the format of: Authorization: Bearer **_TOKEN_**.
212
187
 
213
- There is also the possibility to exclude a list of URLs that should not have the authorization header. The excluded list must be informed in the keycloak initialization. For example:
214
-
215
- ```js
216
- try {
217
- await keycloak.init({
218
- config: {
219
- url: 'http://localhost:8080/auth',
220
- realm: 'your-realm',
221
- clientId: 'client-id'
222
- },
223
- initOptions: {
224
- onLoad: 'login-required',
225
- checkLoginIframe: false
226
- },
227
- enableBearerInterceptor: true,
228
- bearerExcludedUrls: ['/assets', '/clients/public']
229
- });
230
- resolve();
231
- } catch (error) {}
188
+ There is also the possibility to exclude a list of URLs that should not have the authorization header. The excluded list must be provided in the keycloak initialization. For example:
189
+
190
+ ```ts
191
+ await keycloak.init({
192
+ config: {
193
+ url: 'http://localhost:8080/auth',
194
+ realm: 'your-realm',
195
+ clientId: 'your-client-id',
196
+ },
197
+ bearerExcludedUrls: ['/assets', '/clients/public'],
198
+ });
232
199
  ```
233
200
 
234
201
  ## Contributors
@@ -241,11 +208,25 @@ try {
241
208
 
242
209
  <!-- ALL-CONTRIBUTORS-LIST:END -->
243
210
 
244
- If you want to contribute to the project, please check out the [contributing](docs/contributing.md)
211
+ If you want to contribute to the project, please check out the [contributing](CONTRIBUTING.md)
245
212
  document.
246
213
 
247
214
  ## License
248
215
 
249
- **keycloak-angular** is licensed under the **[MIT](LICENSE)**.
250
-
251
- [keycloak-js](https://github.com/keycloak/keycloak-js-bower) is licensed under the **Apache 2.0**.
216
+ **keycloak-angular** is licensed under the **[MIT license](LICENSE)**.
217
+
218
+ <!-- prettier-ignore-start -->
219
+ [license-mit-badge]: https://img.shields.io/badge/License-MIT-yellow.svg
220
+ [license-mit]: https://opensource.org/licenses/MIT
221
+ [build-badge]: https://travis-ci.org/mauriciovigolo/keycloak-angular.svg?branch=master
222
+ [build]: https://travis-ci.org/mauriciovigolo/keycloak-angular
223
+ [vulnerabilities-badge]: https://snyk.io/test/github/mauriciovigolo/keycloak-angular/badge.svg
224
+ [vulnerabilities]: https://snyk.io/test/github/mauriciovigolo/keycloak-angular
225
+ [npm-version-badge]: https://badge.fury.io/js/keycloak-angular.svg
226
+ [npm-version]: https://badge.fury.io/js/keycloak-angular
227
+ [npm-badge]: https://img.shields.io/npm/dm/keycloak-angular.svg
228
+ [npm]: https://www.npmjs.com/package/keycloak-angular
229
+ [contributors-badge]: https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square
230
+ [discord-badge]: https://img.shields.io/discord/790617227853692958.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square
231
+ [discord]: https://discord.gg/mmzEhYXXDG
232
+ <!-- prettier-ignore-end -->