keycloak-angular 7.3.1 → 8.2.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 (38) hide show
  1. package/README.md +133 -158
  2. package/bundles/keycloak-angular.umd.js +404 -310
  3. package/bundles/keycloak-angular.umd.js.map +1 -1
  4. package/esm2015/keycloak-angular.js +1 -1
  5. package/esm2015/lib/core/core.module.js +16 -18
  6. package/esm2015/lib/core/interceptors/keycloak-bearer.interceptor.js +6 -9
  7. package/esm2015/lib/core/interfaces/keycloak-event.js +1 -1
  8. package/esm2015/lib/core/interfaces/keycloak-options.js +2 -1
  9. package/esm2015/lib/core/services/keycloak-auth-guard.js +1 -1
  10. package/esm2015/lib/core/services/keycloak.service.js +18 -30
  11. package/esm2015/lib/keycloak-angular.module.js +8 -10
  12. package/esm2015/public_api.js +1 -1
  13. package/fesm2015/keycloak-angular.js +44 -65
  14. package/fesm2015/keycloak-angular.js.map +1 -1
  15. package/keycloak-angular.metadata.json +1 -1
  16. package/lib/core/interfaces/keycloak-options.d.ts +1 -2
  17. package/lib/core/services/keycloak.service.d.ts +1 -1
  18. package/package.json +10 -16
  19. package/public_api.d.ts +0 -2
  20. package/bundles/keycloak-angular.umd.min.js +0 -16
  21. package/bundles/keycloak-angular.umd.min.js.map +0 -1
  22. package/esm2015/lib/core/interfaces/keycloak-config.js +0 -1
  23. package/esm2015/lib/core/utils/to-promise.js +0 -10
  24. package/esm5/keycloak-angular.js +0 -2
  25. package/esm5/lib/core/core.module.js +0 -26
  26. package/esm5/lib/core/interceptors/keycloak-bearer.interceptor.js +0 -48
  27. package/esm5/lib/core/interfaces/keycloak-config.js +0 -1
  28. package/esm5/lib/core/interfaces/keycloak-event.js +0 -11
  29. package/esm5/lib/core/interfaces/keycloak-options.js +0 -1
  30. package/esm5/lib/core/services/keycloak-auth-guard.js +0 -40
  31. package/esm5/lib/core/services/keycloak.service.js +0 -321
  32. package/esm5/lib/core/utils/to-promise.js +0 -10
  33. package/esm5/lib/keycloak-angular.module.js +0 -15
  34. package/esm5/public_api.js +0 -7
  35. package/fesm5/keycloak-angular.js +0 -453
  36. package/fesm5/keycloak-angular.js.map +0 -1
  37. package/lib/core/interfaces/keycloak-config.d.ts +0 -9
  38. 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,178 +38,146 @@ 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
- **Note about versions**:
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
- - For Angular v9, please use keycloak-angular v7.3 or higher.
51
- - For Angular v8 and bellow, keycloak-angular v7.2.
51
+ ### Versions
52
52
 
53
- ### keycloak-js
53
+ | Angular | keycloak-angular | keycloak-js | Support |
54
+ | :---------: | :--------------: | :-----------------------: | :-----------------: |
55
+ | 11.x - 12.x | 8.2.x | 10 - 13 | Bugs / New Features |
56
+ | 10.x | 8.x.x | 10 - 11 | Bugs |
57
+ | 9.x | 7.3.x | 3.4.3 - 10 (excluding v7) | Bugs |
54
58
 
55
- > 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).
59
+ We try to support the same Angular versions that are [supported](https://angular.io/guide/releases#support-policy-and-schedule) by the Angular team. That said, it's always best to keep up to date with the latest version of Angular for optimal support.
56
60
 
57
- ```sh
58
- npm i --save keycloak-js@version
59
- ```
60
-
61
- #### Choosing the keycloak-js version
61
+ #### Choosing the right keycloak-js version
62
62
 
63
- The keycloak-js adapter documentation recommends to use the same version of your Keycloak / RH-SSO (Red Hat Single Sign On) installation.
63
+ The Keycloak client documentation recommends to use the same version of your Keycloak installation.
64
64
 
65
65
  > 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.
66
66
 
67
67
  ## Setup
68
68
 
69
- ### Angular
70
-
71
- 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.
72
-
73
- #### Using APP_INITIALIZER
69
+ 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.
74
70
 
75
- The KeycloakService can be initialized during the application loading, using the [APP_INITIALIZER](https://angular.io/api/core/APP_INITIALIZER) token.
71
+ 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.
76
72
 
77
- ##### AppModule
78
-
79
- ```js
80
- import { NgModule, APP_INITIALIZER } from '@angular/core';
81
- import { KeycloakService, KeycloakAngularModule } from 'keycloak-angular';
82
- import { initializer } from './utils/app-init';
73
+ ```ts
74
+ import { APP_INITIALIZER, NgModule } from '@angular/core';
75
+ import { BrowserModule } from '@angular/platform-browser';
76
+ import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
77
+ import { AppRoutingModule } from './app-routing.module';
78
+ import { AppComponent } from './app.component';
79
+
80
+ function initializeKeycloak(keycloak: KeycloakService) {
81
+ return () =>
82
+ keycloak.init({
83
+ config: {
84
+ url: 'http://localhost:8080/auth',
85
+ realm: 'your-realm',
86
+ clientId: 'your-client-id',
87
+ },
88
+ initOptions: {
89
+ onLoad: 'check-sso',
90
+ silentCheckSsoRedirectUri:
91
+ window.location.origin + '/assets/silent-check-sso.html',
92
+ },
93
+ });
94
+ }
83
95
 
84
96
  @NgModule({
85
- imports: [KeycloakAngularModule],
97
+ declarations: [AppComponent],
98
+ imports: [AppRoutingModule, BrowserModule, KeycloakAngularModule],
86
99
  providers: [
87
100
  {
88
101
  provide: APP_INITIALIZER,
89
- useFactory: initializer,
102
+ useFactory: initializeKeycloak,
90
103
  multi: true,
91
104
  deps: [KeycloakService],
92
105
  },
93
106
  ],
107
+ bootstrap: [AppComponent],
94
108
  })
95
109
  export class AppModule {}
96
110
  ```
97
111
 
98
- ##### Initializer Function
112
+ 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.
99
113
 
100
- This function can be named and placed in the way you think is most appropriate. In the
101
- underneath example it was placed in a separate file `app-init.ts` and the function was called
102
- `initializer`.
114
+ 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`.
103
115
 
104
- ```js
105
- import { KeycloakService } from 'keycloak-angular';
116
+ Create a file called `silent-check-sso.html` in the `assets` directory of your application and paste in the contents as seen below.
106
117
 
107
- export function initializer(keycloak: KeycloakService): () => Promise<any> {
108
- return (): Promise<any> => keycloak.init();
109
- }
118
+ ```html
119
+ <html>
120
+ <body>
121
+ <script>
122
+ parent.postMessage(location.href, location.origin);
123
+ </script>
124
+ </body>
125
+ </html>
110
126
  ```
111
127
 
112
- #### Using ngDoBootstrap
128
+ 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).
113
129
 
114
- The KeycloakService can be initialized before the application loading. When the Keycloak initialization is successful the application is bootstrapped.
130
+ ## Example project
115
131
 
116
- This has two major benefits.
117
-
118
- 1. This is faster because the application isn't fully bootstrapped and
119
- 1. It prevents a moment when you see the application without having the authorization.
120
-
121
- #### AppModule
122
-
123
- ```js
124
- import { NgModule, DoBootstrap, ApplicationRef } from '@angular/core';
125
- import { KeycloakAngularModule, KeycloakService } from 'keycloak-angular';
126
-
127
- const keycloakService = new KeycloakService();
128
-
129
- @NgModule({
130
- imports: [KeycloakAngularModule],
131
- providers: [
132
- {
133
- provide: KeycloakService,
134
- useValue: keycloakService,
135
- },
136
- ],
137
- entryComponents: [AppComponent],
138
- })
139
- export class AppModule implements DoBootstrap {
140
- ngDoBootstrap(appRef: ApplicationRef) {
141
- keycloakService
142
- .init()
143
- .then(() => {
144
- console.log('[ngDoBootstrap] bootstrap app');
145
-
146
- appRef.bootstrap(AppComponent);
147
- })
148
- .catch((error) =>
149
- console.error('[ngDoBootstrap] init Keycloak failed', error)
150
- );
151
- }
152
- }
153
- ```
154
-
155
- **Hint:** Do not forget to remove `bootstrap: [AppComponent]` from NgModule decorator options.
156
-
157
- ### Keycloak
158
-
159
- Besides configuring the keycloak lib in your application it is also necessary to setup the
160
- access - scope for the **account** client.
161
-
162
- In this documentation we assume that you already installed and configured your Keycloak
163
- instance, as well created the client app.
164
-
165
- **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/).
166
-
167
- #### Client configuration
168
-
169
- 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.
170
-
171
- ![keycloak-account-scope](./docs/images/keycloak-account-scope.png)
172
-
173
- 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.
132
+ 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.
174
133
 
175
134
  ## AuthGuard
176
135
 
177
- 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.
136
+ 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.
178
137
 
179
- Example:
138
+ 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.
180
139
 
181
- ```js
140
+ ```ts
182
141
  import { Injectable } from '@angular/core';
183
- import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
142
+ import {
143
+ ActivatedRouteSnapshot,
144
+ Router,
145
+ RouterStateSnapshot,
146
+ } from '@angular/router';
184
147
  import { KeycloakAuthGuard, KeycloakService } from 'keycloak-angular';
185
148
 
186
149
  @Injectable({
187
- providedIn: 'root'
150
+ providedIn: 'root',
188
151
  })
189
- export class CanAuthenticationGuard extends KeycloakAuthGuard implements CanActivate {
190
- constructor(protected router: Router, protected keycloakAngular: KeycloakService) {
191
- super(router, keycloakAngular);
152
+ export class AuthGuard extends KeycloakAuthGuard {
153
+ constructor(
154
+ protected readonly router: Router,
155
+ protected readonly keycloak: KeycloakService
156
+ ) {
157
+ super(router, keycloak);
192
158
  }
193
159
 
194
- isAccessAllowed(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
195
- return new Promise((resolve, reject) => {
196
- if (!this.authenticated) {
197
- this.keycloakAngular.login()
198
- .catch(e => console.error(e));
199
- return reject(false);
200
- }
201
-
202
- const requiredRoles: string[] = route.data.roles;
203
- if (!requiredRoles || requiredRoles.length === 0) {
204
- return resolve(true);
205
- } else {
206
- if (!this.roles || this.roles.length === 0) {
207
- resolve(false);
208
- }
209
- resolve(requiredRoles.every(role => this.roles.indexOf(role) > -1));
210
- }
211
- });
160
+ public async isAccessAllowed(
161
+ route: ActivatedRouteSnapshot,
162
+ state: RouterStateSnapshot
163
+ ) {
164
+ // Force the user to log in if currently unauthenticated.
165
+ if (!this.authenticated) {
166
+ await this.keycloak.login({
167
+ redirectUri: window.location.origin + state.url,
168
+ });
169
+ }
170
+
171
+ // Get the roles required from the route.
172
+ const requiredRoles = route.data.roles;
173
+
174
+ // Allow the user to to proceed if no additional roles are required to access the route.
175
+ if (!(requiredRoles instanceof Array) || requiredRoles.length === 0) {
176
+ return true;
177
+ }
178
+
179
+ // Allow the user to proceed if all the required roles are present.
180
+ return requiredRoles.every((role) => this.roles.includes(role));
212
181
  }
213
182
  }
214
183
  ```
@@ -217,25 +186,17 @@ export class CanAuthenticationGuard extends KeycloakAuthGuard implements CanActi
217
186
 
218
187
  By default all HttpClient requests will add the Authorization header in the format of: Authorization: Bearer **_TOKEN_**.
219
188
 
220
- 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:
221
-
222
- ```js
223
- try {
224
- await keycloak.init({
225
- config: {
226
- url: 'http://localhost:8080/auth',
227
- realm: 'your-realm',
228
- clientId: 'client-id',
229
- },
230
- initOptions: {
231
- onLoad: 'login-required',
232
- checkLoginIframe: false,
233
- },
234
- enableBearerInterceptor: true,
235
- bearerExcludedUrls: ['/assets', '/clients/public'],
236
- });
237
- resolve();
238
- } catch (error) {}
189
+ 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:
190
+
191
+ ```ts
192
+ await keycloak.init({
193
+ config: {
194
+ url: 'http://localhost:8080/auth',
195
+ realm: 'your-realm',
196
+ clientId: 'your-client-id',
197
+ },
198
+ bearerExcludedUrls: ['/assets', '/clients/public'],
199
+ });
239
200
  ```
240
201
 
241
202
  ## Contributors
@@ -248,11 +209,25 @@ try {
248
209
 
249
210
  <!-- ALL-CONTRIBUTORS-LIST:END -->
250
211
 
251
- If you want to contribute to the project, please check out the [contributing](docs/contributing.md)
212
+ If you want to contribute to the project, please check out the [contributing](CONTRIBUTING.md)
252
213
  document.
253
214
 
254
215
  ## License
255
216
 
256
- **keycloak-angular** is licensed under the **[MIT](LICENSE)**.
257
-
258
- [keycloak-js](https://github.com/keycloak/keycloak-js-bower) is licensed under the **Apache 2.0**.
217
+ **keycloak-angular** is licensed under the **[MIT license](LICENSE)**.
218
+
219
+ <!-- prettier-ignore-start -->
220
+ [license-mit-badge]: https://img.shields.io/badge/License-MIT-yellow.svg
221
+ [license-mit]: https://opensource.org/licenses/MIT
222
+ [build-badge]: https://travis-ci.org/mauriciovigolo/keycloak-angular.svg?branch=master
223
+ [build]: https://travis-ci.org/mauriciovigolo/keycloak-angular
224
+ [vulnerabilities-badge]: https://snyk.io/test/github/mauriciovigolo/keycloak-angular/badge.svg
225
+ [vulnerabilities]: https://snyk.io/test/github/mauriciovigolo/keycloak-angular
226
+ [npm-version-badge]: https://badge.fury.io/js/keycloak-angular.svg
227
+ [npm-version]: https://badge.fury.io/js/keycloak-angular
228
+ [npm-badge]: https://img.shields.io/npm/dm/keycloak-angular.svg
229
+ [npm]: https://www.npmjs.com/package/keycloak-angular
230
+ [contributors-badge]: https://img.shields.io/badge/all_contributors-5-orange.svg?style=flat-square
231
+ [discord-badge]: https://img.shields.io/discord/790617227853692958.svg?color=7389D8&labelColor=6A7EC2&logo=discord&logoColor=ffffff&style=flat-square
232
+ [discord]: https://discord.gg/mmzEhYXXDG
233
+ <!-- prettier-ignore-end -->