ngx-oauth 2.0.0 → 2.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.
@@ -1,10 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, Inject, EventEmitter, Component, Input, Output, ContentChild, HostListener, PLATFORM_ID, Optional, NgModule } from '@angular/core';
2
+ import { InjectionToken, Injectable, Inject, EventEmitter, Component, ViewEncapsulation, Input, Output, ContentChild, HostListener, PLATFORM_ID, Optional, NgModule } from '@angular/core';
3
3
  import { __awaiter } from 'tslib';
4
4
  import * as i1 from '@angular/common/http';
5
5
  import { HttpHeaders, HttpParams, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
6
- import { catchError, concatMap, delay, switchMap, tap } from 'rxjs/operators';
7
- import { ReplaySubject, EMPTY, from, of, noop, throwError, Subscription } from 'rxjs';
6
+ import { filter, map, switchMap, shareReplay, tap, catchError, concatMap, delay } from 'rxjs/operators';
7
+ import { ReplaySubject, of, EMPTY, from, noop, throwError, Subscription, take } from 'rxjs';
8
8
  import * as i2 from '@angular/common';
9
9
  import { isPlatformBrowser, CommonModule } from '@angular/common';
10
10
  import * as i3 from '@angular/forms';
@@ -16,6 +16,7 @@ const SERVER_PATH = new InjectionToken('SERVER_PATH');
16
16
  const LOCATION = new InjectionToken('Location');
17
17
  const STORAGE = new InjectionToken('Storage');
18
18
  const OAUTH_CONFIG = new InjectionToken('OAuthConfig');
19
+ const OAUTH_TOKEN = new InjectionToken('OAuthToken');
19
20
  var OAuthType;
20
21
  (function (OAuthType) {
21
22
  OAuthType["RESOURCE"] = "password";
@@ -57,105 +58,127 @@ const parseOauthUri = (hash) => {
57
58
  }
58
59
  return null;
59
60
  };
61
+ const jwt = (token) => JSON.parse(atob(token.split('.')[1]));
60
62
  class OAuthService {
61
- constructor(http, zone, authConfig, locationService) {
63
+ constructor(http, zone, authConfig, location, locationService) {
62
64
  this.http = http;
63
65
  this.zone = zone;
64
66
  this.authConfig = authConfig;
67
+ this.location = location;
65
68
  this.locationService = locationService;
66
69
  this._token = null;
67
70
  this._status = OAuthStatus.NOT_AUTHORIZED;
68
71
  this.state$ = new ReplaySubject(1);
69
72
  this.status$ = new ReplaySubject(1);
70
- this.init();
73
+ this.userInfo$ = this.status$.pipe(filter(s => s === OAuthStatus.AUTHORIZED), map(() => {
74
+ const { config } = this.authConfig;
75
+ return config.userPath;
76
+ }), filter(p => !!p), switchMap(path => this.http.get(path)), shareReplay());
77
+ setTimeout(() => this.init()); // decouple for http interceptor
78
+ }
79
+ /**
80
+ * Get the oauth config for initialize. If OpenId with issuerPath is configured then configure from server openid configuration.
81
+ * @protected
82
+ */
83
+ get config$() {
84
+ let { config } = this.authConfig;
85
+ if (config && config.clientId) {
86
+ const { issuerPath, scope } = config;
87
+ if (issuerPath) {
88
+ return this.http.get(`${issuerPath}/.well-known/openid-configuration`).pipe(tap(v => this.set(this.type, Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, v.authorization_endpoint && { authorizePath: v.authorization_endpoint } || {}), v.token_endpoint && { tokenPath: v.token_endpoint } || {}), v.revocation_endpoint && { revokePath: v.revocation_endpoint } || {}), v.code_challenge_methods_supported && { pkce: v.code_challenge_methods_supported.indexOf('S256') > -1 } || {}), v.userinfo_endpoint && { userPath: v.userinfo_endpoint } || {}), v.introspection_endpoint && { introspectionPath: v.introspection_endpoint } || {}), v.end_session_endpoint && { logoutPath: v.end_session_endpoint } || {}), scope && {} || { scope: 'openid' }))), map(() => this.authConfig.config));
89
+ }
90
+ return of(config);
91
+ }
92
+ console.warn('clientId is missing in oauth config');
93
+ return EMPTY;
71
94
  }
95
+ /**
96
+ * Init. Will check the url implicit or authorization flow or existing saved token.
97
+ * @protected
98
+ */
72
99
  init() {
73
- const { hash, search, origin, pathname } = this.locationService;
74
- const isImplicitRedirect = hash && /(#access_token=)|(#error=)/.test(hash);
100
+ const { hash, search, origin, pathname } = this.location;
101
+ const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
75
102
  const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search);
76
103
  const { storageKey } = this.authConfig;
77
104
  const savedToken = storageKey && this.authConfig.storage && this.authConfig.storage[storageKey] &&
78
105
  JSON.parse(this.authConfig.storage[storageKey]);
79
- if (isImplicitRedirect) {
80
- const parameters = parseOauthUri(hash.substr(1));
81
- this.emitState(parameters);
82
- this.cleanLocationHash();
83
- if (!parameters || parameters.error) {
84
- this.token = null;
85
- this.status = OAuthStatus.DENIED;
86
- }
87
- else {
106
+ this.config$.subscribe(config => {
107
+ if (isImplicitRedirect) {
108
+ const parameters = parseOauthUri(hash.substr(1));
88
109
  this.token = parameters;
89
- this.status = OAuthStatus.AUTHORIZED;
110
+ this.status = this.checkResponse(savedToken, parameters) && OAuthStatus.AUTHORIZED || OAuthStatus.DENIED;
90
111
  }
91
- }
92
- else if (isAuthCodeRedirect) {
93
- const parameters = parseOauthUri(search.substr(1));
94
- this.emitState(parameters);
95
- const newParametersString = this.getCleanedUnSearchParameters();
96
- if (parameters && parameters.code) {
97
- const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
98
- const codeVerifier = savedToken && savedToken.codeVerifier;
99
- setTimeout(() => {
112
+ else if (isAuthCodeRedirect) {
113
+ const parameters = parseOauthUri(search.substr(1));
114
+ if (!this.checkResponse(savedToken, parameters)) {
115
+ this.token = parameters;
116
+ this.status = OAuthStatus.DENIED;
117
+ }
118
+ else {
119
+ const newParametersString = this.getCleanedUnSearchParameters();
120
+ const { clientId, clientSecret, tokenPath, scope } = config;
121
+ const codeVerifier = savedToken && savedToken.codeVerifier;
100
122
  this.http.post(tokenPath, new HttpParams({
101
- fromObject: Object.assign(Object.assign(Object.assign(Object.assign({ code: parameters.code, client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { redirect_uri: `${origin}${pathname}${newParametersString}`, grant_type: 'authorization_code' }), scope && { scope } || {}), codeVerifier && { code_verifier: codeVerifier } || {})
102
- }), { headers: REQUEST_HEADER }).pipe(catchError(() => {
103
- this.token = { error: 'error' };
123
+ fromObject: Object.assign(Object.assign(Object.assign(Object.assign({ code: parameters === null || parameters === void 0 ? void 0 : parameters.code, client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { redirect_uri: `${origin}${pathname}`, grant_type: 'authorization_code' }), scope && { scope } || {}), codeVerifier && { code_verifier: codeVerifier } || {})
124
+ }), { headers: REQUEST_HEADER }).pipe(catchError((err) => {
125
+ this.token = err;
104
126
  this.status = OAuthStatus.DENIED;
105
- this.locationService.href = `${origin}${pathname}${newParametersString}`;
127
+ this.locationService.replaceState(`${pathname}${newParametersString}`);
106
128
  return EMPTY;
107
129
  })).subscribe(token => {
108
130
  this.token = token;
109
- // authorized event will be triggered after redirect
110
- this.locationService.href = `${origin}${pathname}${newParametersString}`;
131
+ this.status = OAuthStatus.AUTHORIZED;
132
+ this.locationService.replaceState(`${pathname}${newParametersString}`);
111
133
  });
112
- });
113
- }
114
- else {
115
- this.token = null;
116
- this.status = OAuthStatus.DENIED;
117
- }
118
- }
119
- else if (savedToken) {
120
- const { access_token, refresh_token, error } = savedToken;
121
- if (error) {
122
- this.token = null;
123
- this.status = OAuthStatus.DENIED;
134
+ }
124
135
  }
125
- else if (access_token) {
126
- this.token = savedToken;
127
- if (refresh_token) {
128
- setTimeout(() => {
136
+ else if (savedToken) {
137
+ this._token = savedToken;
138
+ const { access_token, refresh_token, error } = savedToken;
139
+ if (access_token) {
140
+ if (refresh_token) { // force refresh since might be a manual page refresh
129
141
  this.refreshToken();
130
- });
142
+ }
143
+ else {
144
+ this.status = OAuthStatus.AUTHORIZED;
145
+ }
131
146
  }
132
147
  else {
133
- this.status = OAuthStatus.AUTHORIZED;
148
+ this.status = error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED;
134
149
  }
135
150
  }
136
- }
137
- else {
138
- this.status = OAuthStatus.NOT_AUTHORIZED;
139
- }
151
+ else {
152
+ this.status = OAuthStatus.NOT_AUTHORIZED;
153
+ }
154
+ });
140
155
  }
141
156
  login(parameters) {
142
- if (this.isResourceType(parameters)) {
143
- this.resourceLogin(parameters);
144
- }
145
- else if (this.isAuthorizationCodeType(parameters)) {
146
- this.authorizationCodeLogin(parameters).then();
147
- }
148
- else if (this.isImplicitType(parameters)) {
149
- this.implicitLogin(parameters).then();
150
- }
151
- else if (this.isClientCredentialType()) {
152
- this.clientCredentialLogin();
153
- }
157
+ return __awaiter(this, void 0, void 0, function* () {
158
+ if (this.isResourceType(parameters)) {
159
+ this.resourceLogin(parameters);
160
+ }
161
+ else if (this.isAuthorizationCodeType(parameters)) {
162
+ yield this.authorizationCodeLogin(parameters);
163
+ }
164
+ else if (this.isImplicitType(parameters)) {
165
+ yield this.implicitLogin(parameters);
166
+ }
167
+ else if (this.isClientCredentialType()) {
168
+ this.clientCredentialLogin();
169
+ }
170
+ });
154
171
  }
155
- logout() {
172
+ logout(useLogoutUrl) {
156
173
  this.revoke();
157
174
  this.token = null;
158
175
  this.status = OAuthStatus.NOT_AUTHORIZED;
176
+ const { logoutPath, logoutRedirectUri } = this.authConfig.config;
177
+ if (useLogoutUrl && logoutPath) {
178
+ const { origin, pathname } = this.location;
179
+ const currentPath = `${origin}${pathname}`;
180
+ this.location.replace(`${logoutPath}?post_logout_redirect_uri=${logoutRedirectUri || currentPath}`);
181
+ }
159
182
  }
160
183
  revoke() {
161
184
  const { revokePath, clientId, clientSecret } = this.authConfig.config;
@@ -195,10 +218,10 @@ class OAuthService {
195
218
  const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
196
219
  const { username, password } = parameters;
197
220
  this.http.post(tokenPath, new HttpParams({
198
- fromObject: Object.assign(Object.assign({ client_id: clientId, client_secret: clientSecret, grant_type: OAuthType.RESOURCE }, scope ? { scope } : {}), { username,
221
+ fromObject: Object.assign(Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: OAuthType.RESOURCE }), scope && { scope } || {}), { username,
199
222
  password })
200
- }), { headers: REQUEST_HEADER }).pipe(catchError(() => {
201
- this.token = null;
223
+ }), { headers: REQUEST_HEADER }).pipe(catchError(err => {
224
+ this.token = err;
202
225
  this.status = OAuthStatus.DENIED;
203
226
  return EMPTY;
204
227
  })).subscribe(params => {
@@ -209,13 +232,13 @@ class OAuthService {
209
232
  authorizationCodeLogin(parameters) {
210
233
  return __awaiter(this, void 0, void 0, function* () {
211
234
  const authUrl = yield this.toAuthorizationUrl(parameters, OAuthType.AUTHORIZATION_CODE);
212
- this.locationService.replace(authUrl);
235
+ this.location.replace(authUrl);
213
236
  });
214
237
  }
215
238
  implicitLogin(parameters) {
216
239
  return __awaiter(this, void 0, void 0, function* () {
217
240
  const authUrl = yield this.toAuthorizationUrl(parameters, OAuthType.IMPLICIT);
218
- this.locationService.replace(authUrl);
241
+ this.location.replace(authUrl);
219
242
  });
220
243
  }
221
244
  clientCredentialLogin() {
@@ -246,21 +269,46 @@ class OAuthService {
246
269
  toAuthorizationUrl(parameters, responseType) {
247
270
  return __awaiter(this, void 0, void 0, function* () {
248
271
  const { config } = this.authConfig;
249
- const appendChar = config.authorizePath.includes('?') ? '&' : '?';
250
- const clientId = `${appendChar}client_id=${config.clientId}`;
251
- const redirectUri = `&redirect_uri=${encodeURIComponent(parameters.redirectUri)}`;
252
- const responseTypeString = `&response_type=${responseType}`;
253
- const scope = `&scope=${encodeURIComponent(config.scope || '')}`;
254
- const state = `&state=${encodeURIComponent(parameters.state || '')}`;
255
- const codeVerifier = config.pkce && randomString() || null;
256
- if (codeVerifier) {
257
- this.token = { codeVerifier }; //save the code verifier before we redirect
272
+ let authorizationUrl = `${config.authorizePath}`;
273
+ authorizationUrl += config.authorizePath.includes('?') && '&' || '?';
274
+ authorizationUrl += `client_id=${config.clientId}`;
275
+ authorizationUrl += `&redirect_uri=${encodeURIComponent(parameters.redirectUri)}`;
276
+ authorizationUrl += `&response_type=${responseType}`;
277
+ authorizationUrl += `&scope=${encodeURIComponent(config.scope || '')}`;
278
+ authorizationUrl += `&state=${encodeURIComponent(parameters.state || '')}`;
279
+ return `${authorizationUrl}${this.generateNonce(config)}${yield this.generateCodeChallenge(config)}`;
280
+ });
281
+ }
282
+ generateCodeChallenge(config) {
283
+ return __awaiter(this, void 0, void 0, function* () {
284
+ if (config.pkce) {
285
+ const codeVerifier = randomString();
286
+ this.token = Object.assign(Object.assign({}, this.token), { codeVerifier });
287
+ return `&code_challenge=${yield pkce(codeVerifier)}&code_challenge_method=S256`;
258
288
  }
259
- const codeChallenge = codeVerifier ? `&code_challenge=${yield pkce(codeVerifier)}&code_challenge_method=S256` : '';
260
- const parametersString = `${clientId}${redirectUri}${responseTypeString}${scope}${state}${codeChallenge}`;
261
- return `${config.authorizePath}${parametersString}`;
289
+ return '';
262
290
  });
263
291
  }
292
+ generateNonce(config) {
293
+ if (config && config.scope && config.scope.indexOf('openid') > -1) {
294
+ const nonce = randomString(10);
295
+ this.token = Object.assign(Object.assign({}, this.token), { nonce });
296
+ return `&nonce=${nonce}`;
297
+ }
298
+ return '';
299
+ }
300
+ checkResponse(token, parameters) {
301
+ this.emitState(parameters);
302
+ this.cleanLocationHash();
303
+ if (!parameters || parameters.error) {
304
+ return false;
305
+ }
306
+ if (token && token.nonce && parameters.access_token) {
307
+ const jwtToken = jwt(parameters.access_token);
308
+ return token.nonce === jwtToken.nonce;
309
+ }
310
+ return parameters.access_token || parameters.code;
311
+ }
264
312
  set token(token) {
265
313
  this._token = token;
266
314
  const { storageKey } = this.authConfig;
@@ -292,7 +340,7 @@ class OAuthService {
292
340
  const { refresh_token } = this.token;
293
341
  if (tokenPath && refresh_token) {
294
342
  this.http.post(tokenPath, new HttpParams({
295
- fromObject: Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret ? { client_secret: clientSecret } : {}), { grant_type: 'refresh_token', refresh_token }), scope ? { scope } : {})
343
+ fromObject: Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: 'refresh_token', refresh_token }), scope && { scope } || {})
296
344
  }), { headers: REQUEST_HEADER }).pipe(catchError(() => {
297
345
  this.logout();
298
346
  return EMPTY;
@@ -303,24 +351,24 @@ class OAuthService {
303
351
  }
304
352
  }
305
353
  getCleanedUnSearchParameters() {
306
- const { search } = this.locationService;
354
+ const { search } = this.location;
307
355
  let searchString = search.substr(1);
308
- const hashKeys = ['code', 'state', 'error', 'error_description', 'session_state'];
356
+ const hashKeys = ['code', 'state', 'error', 'error_description', 'session_state', 'scope', 'authuser', 'prompt'];
309
357
  hashKeys.forEach((hashKey) => {
310
358
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
311
359
  searchString = searchString.replace(re, '');
312
360
  });
313
- return searchString.length ? `?${searchString}` : '';
361
+ return searchString.length && `?${searchString}` || '';
314
362
  }
315
363
  cleanLocationHash() {
316
- const { hash } = this.locationService;
364
+ const { hash } = this.location;
317
365
  let curHash = hash.substr(1);
318
- const hashKeys = ['access_token', 'token_type', 'expires_in', 'scope', 'state', 'error', 'error_description', 'session_state'];
366
+ const hashKeys = ['access_token', 'token_type', 'expires_in', 'scope', 'state', 'error', 'error_description', 'session_state', 'nonce'];
319
367
  hashKeys.forEach((hashKey) => {
320
368
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
321
369
  curHash = curHash.replace(re, '');
322
370
  });
323
- this.locationService.hash = curHash;
371
+ this.location.hash = curHash;
324
372
  }
325
373
  emitState(parameters) {
326
374
  const { state } = parameters;
@@ -329,9 +377,9 @@ class OAuthService {
329
377
  }
330
378
  }
331
379
  }
332
- OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthService, deps: [{ token: i1.HttpClient }, { token: i0.NgZone }, { token: OAUTH_CONFIG }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Injectable });
333
- OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthService });
334
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthService, decorators: [{
380
+ OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthService, deps: [{ token: i1.HttpClient }, { token: i0.NgZone }, { token: OAUTH_CONFIG }, { token: LOCATION }, { token: i2.Location }], target: i0.ɵɵFactoryTarget.Injectable });
381
+ OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthService });
382
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthService, decorators: [{
335
383
  type: Injectable
336
384
  }], ctorParameters: function () {
337
385
  return [{ type: i1.HttpClient }, { type: i0.NgZone }, { type: undefined, decorators: [{
@@ -340,7 +388,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImpor
340
388
  }] }, { type: Location, decorators: [{
341
389
  type: Inject,
342
390
  args: [LOCATION]
343
- }] }];
391
+ }] }, { type: i2.Location }];
344
392
  } });
345
393
 
346
394
  class OAuthInterceptor {
@@ -350,7 +398,7 @@ class OAuthInterceptor {
350
398
  intercept(req, next) {
351
399
  if (this.oauthService) {
352
400
  if (!this.isPathExcepted(req)) {
353
- const token = this.oauthService.token;
401
+ const { token } = this.oauthService;
354
402
  if (token && token.access_token) {
355
403
  req = req.clone({
356
404
  setHeaders: {
@@ -373,27 +421,31 @@ class OAuthInterceptor {
373
421
  }
374
422
  }
375
423
  isPathExcepted(req) {
376
- for (const ignorePath of this.oauthService.ignorePaths) {
377
- try {
378
- if (req.url.match(ignorePath)) {
379
- return true;
424
+ const { ignorePaths } = this.oauthService;
425
+ if (ignorePaths) {
426
+ for (const ignorePath of this.oauthService.ignorePaths) {
427
+ try {
428
+ if (req.url.match(ignorePath)) {
429
+ return true;
430
+ }
431
+ }
432
+ catch (err) {
380
433
  }
381
- }
382
- catch (err) {
383
434
  }
384
435
  }
385
436
  return false;
386
437
  }
387
438
  }
388
- OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthInterceptor, deps: [{ token: OAuthService }], target: i0.ɵɵFactoryTarget.Injectable });
389
- OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthInterceptor });
390
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthInterceptor, decorators: [{
439
+ OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthInterceptor, deps: [{ token: OAuthService }], target: i0.ɵɵFactoryTarget.Injectable });
440
+ OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthInterceptor });
441
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthInterceptor, decorators: [{
391
442
  type: Injectable
392
443
  }], ctorParameters: function () { return [{ type: OAuthService }]; } });
393
444
 
394
445
  class OAuthLoginComponent {
395
- constructor(oauthService, location) {
446
+ constructor(oauthService, locationService, location) {
396
447
  this.oauthService = oauthService;
448
+ this.locationService = locationService;
397
449
  this.location = location;
398
450
  this.subscription = new Subscription();
399
451
  this._i18n = {
@@ -404,6 +456,7 @@ class OAuthLoginComponent {
404
456
  authorized: 'Welcome',
405
457
  denied: 'Access Denied. Try again!'
406
458
  };
459
+ this.useLogoutUrl = false;
407
460
  this.state = '';
408
461
  this.stateChange = new EventEmitter();
409
462
  this.username = '';
@@ -412,14 +465,15 @@ class OAuthLoginComponent {
412
465
  this.OAuthType = OAuthType;
413
466
  this.collapse = false;
414
467
  this.type = this.oauthService.type;
415
- this.redirectUri = this.location.href;
416
468
  this.state$ = this.oauthService.state$.pipe(tap(s => this.stateChange.emit(s)));
417
469
  this.status$ = this.oauthService.status$.pipe(tap(s => {
418
470
  if (s === OAuthStatus.AUTHORIZED && this.profileName$) {
419
- this.subscription.add(this.profileName$.subscribe(n => this.profileName = n));
471
+ this.subscription.add(this.profileName$.pipe(take(1)).subscribe(n => this.profileName = n));
420
472
  }
421
473
  else {
422
- this.profileName = '';
474
+ const { token } = this.oauthService;
475
+ const userInfo = token && token.id_token && JSON.parse(atob(token.id_token.split('.')[1])) || {};
476
+ this.profileName = userInfo.name || userInfo.username || userInfo.email || userInfo.sub || '';
423
477
  }
424
478
  }));
425
479
  this.loginFunction = (p) => this.login(p);
@@ -431,15 +485,25 @@ class OAuthLoginComponent {
431
485
  set i18n(i18n) {
432
486
  this._i18n = Object.assign(Object.assign({}, this._i18n), i18n);
433
487
  }
488
+ set redirectUri(redirectUri) {
489
+ if (redirectUri) {
490
+ this._redirectUri = redirectUri;
491
+ }
492
+ }
493
+ get redirectUri() {
494
+ return this._redirectUri || `${this.location.origin}${this.locationService.path(true) || '/'}`;
495
+ }
434
496
  ngOnDestroy() {
435
497
  this.subscription.unsubscribe();
436
498
  }
437
499
  logout() {
438
- this.oauthService.logout();
500
+ this.oauthService.logout(this.useLogoutUrl);
439
501
  }
440
502
  login(parameters) {
441
- this.oauthService.login(parameters);
442
- this.collapse = false;
503
+ return __awaiter(this, void 0, void 0, function* () {
504
+ yield this.oauthService.login(parameters);
505
+ this.collapse = false;
506
+ });
443
507
  }
444
508
  toggleCollapse() {
445
509
  this.collapse = !this.collapse;
@@ -448,18 +512,22 @@ class OAuthLoginComponent {
448
512
  this.collapse = false;
449
513
  }
450
514
  }
451
- OAuthLoginComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthLoginComponent, deps: [{ token: OAuthService }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Component });
452
- OAuthLoginComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.2", type: OAuthLoginComponent, selector: "oauth-login", inputs: { i18n: "i18n", state: "state", profileName$: "profileName$" }, outputs: { stateChange: "stateChange" }, host: { listeners: { "window:keydown.escape": "keyboardEvent()" } }, queries: [{ propertyName: "loginTemplate", first: true, predicate: ["login"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"state$ | async\"></ng-container>\r\n<ng-container *ngIf=\"loginTemplate; else defaultLogin\"\r\n [ngTemplateOutlet]=\"loginTemplate\"\r\n [ngTemplateOutletContext]=\"{login: loginFunction, logout: logoutFunction, status: status$ | async}\">\r\n</ng-container>\r\n<ng-template #defaultLogin>\r\n <ng-container *ngIf=\"status$ | async as status\">\r\n <ng-container *ngIf=\"type === OAuthType.RESOURCE; else noResource\">\r\n <div class=\"oauth dropdown text-right p-3 {{collapse ? 'show': ''}}\">\r\n <button class=\"btn btn-link p-0 dropdown-toggle\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : toggleCollapse()\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </button>\r\n <div class=\"dropdown-menu mr-3 {{collapse ? 'show': ''}}\">\r\n <form class=\"p-3\" #form=\"ngForm\"\r\n *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED || status === OAuthStatus.DENIED\"\r\n (submit)=\"login({username: username, password: password})\">\r\n <div class=\"form-group\">\r\n <input type=\"text\"\r\n class=\"form-control\"\r\n name=\"username\"\r\n required\r\n [(ngModel)]=\"username\"\r\n [placeholder]=\"i18n.username\">\r\n </div>\r\n <div class=\"form-group\">\r\n <input type=\"password\"\r\n class=\"form-control\"\r\n name=\"password\"\r\n required\r\n [(ngModel)]=\"password\"\r\n [placeholder]=\"i18n.password\">\r\n </div>\r\n <div class=\"text-right\">\r\n <button type=\"submit\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"form.invalid\">{{i18n.submit}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #noResource>\r\n <a role=\"button\" class=\"oauth\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : login({redirectUri: redirectUri, state:state})\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </a>\r\n </ng-template>\r\n\r\n <ng-template #message>\r\n <span *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED\">{{i18n.notAuthorized}}</span>\r\n <span *ngIf=\"status === OAuthStatus.AUTHORIZED\">\r\n {{i18n.authorized}}<strong>&nbsp;{{profileName}}</strong>\r\n </span>\r\n <span *ngIf=\"status === OAuthStatus.DENIED\">{{i18n.denied}}</span>\r\n </ng-template>\r\n </ng-container>\r\n</ng-template>\r\n\r\n", styles: [".oauth .dropdown-menu{left:auto;right:0;box-shadow:0 5px 10px #0003;min-width:250px}.oauth .dropdown-menu:before{content:\"\";display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:#0003;position:absolute;top:-7px;left:auto;right:15px}.oauth .dropdown-menu:after{content:\"\";display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:auto;right:16px}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], pipes: { "async": i2.AsyncPipe } });
453
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthLoginComponent, decorators: [{
515
+ OAuthLoginComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthLoginComponent, deps: [{ token: OAuthService }, { token: i2.Location }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Component });
516
+ OAuthLoginComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.3", type: OAuthLoginComponent, selector: "oauth-login", inputs: { i18n: "i18n", redirectUri: "redirectUri", useLogoutUrl: "useLogoutUrl", state: "state", profileName$: "profileName$" }, outputs: { stateChange: "stateChange" }, host: { listeners: { "window:keydown.escape": "keyboardEvent()" } }, queries: [{ propertyName: "loginTemplate", first: true, predicate: ["login"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"state$ | async\"></ng-container>\r\n<ng-container *ngIf=\"loginTemplate; else defaultLogin\"\r\n [ngTemplateOutlet]=\"loginTemplate\"\r\n [ngTemplateOutletContext]=\"{login: loginFunction, logout: logoutFunction, status: status$ | async}\">\r\n</ng-container>\r\n<ng-template #defaultLogin>\r\n <ng-container *ngIf=\"status$ | async as status\">\r\n <ng-container *ngIf=\"type === OAuthType.RESOURCE; else noResource\">\r\n <div class=\"oauth dropdown text-end p-3 {{collapse ? 'show': ''}}\">\r\n <button class=\"btn btn-link p-0 dropdown-toggle\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : toggleCollapse()\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </button>\r\n <div class=\"dropdown-menu mr-3 {{collapse ? 'show': ''}}\">\r\n <form class=\"p-3\" #form=\"ngForm\"\r\n *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED || status === OAuthStatus.DENIED\"\r\n (submit)=\"login({username: username, password: password})\">\r\n <div class=\"mb-3\">\r\n <input type=\"text\"\r\n class=\"form-control\"\r\n name=\"username\"\r\n required\r\n [(ngModel)]=\"username\"\r\n [placeholder]=\"i18n.username\">\r\n </div>\r\n <div class=\"mb-3\">\r\n <input type=\"password\"\r\n class=\"form-control\"\r\n name=\"password\"\r\n required\r\n [(ngModel)]=\"password\"\r\n [placeholder]=\"i18n.password\">\r\n </div>\r\n <div class=\"text-end\">\r\n <button type=\"submit\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"form.invalid\">{{i18n.submit}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #noResource>\r\n <a role=\"button\" class=\"oauth\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : login({redirectUri: redirectUri, state:state})\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </a>\r\n </ng-template>\r\n\r\n <ng-template #message>\r\n <span *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED\" class=\"not-authorized\">{{i18n.notAuthorized}}</span>\r\n <span *ngIf=\"status === OAuthStatus.AUTHORIZED\" class=\"authorized\">\r\n <span class=\"welcome\">{{i18n.authorized}}&nbsp;</span>\r\n <strong class=\"profile-name\" [innerHTML]=\"profileName\"></strong>\r\n </span>\r\n <span *ngIf=\"status === OAuthStatus.DENIED\" class=\"denied\">{{i18n.denied}}</span>\r\n </ng-template>\r\n </ng-container>\r\n</ng-template>\r\n\r\n", styles: [".oauth .dropdown-menu{left:auto;right:0;box-shadow:0 5px 10px #0003;min-width:250px}.oauth .dropdown-menu:before{content:\"\";display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:#0003;position:absolute;top:-7px;left:auto;right:15px}.oauth .dropdown-menu:after{content:\"\";display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:auto;right:16px}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], pipes: { "async": i2.AsyncPipe }, encapsulation: i0.ViewEncapsulation.None });
517
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthLoginComponent, decorators: [{
454
518
  type: Component,
455
- args: [{ selector: 'oauth-login', template: "<ng-container *ngIf=\"state$ | async\"></ng-container>\r\n<ng-container *ngIf=\"loginTemplate; else defaultLogin\"\r\n [ngTemplateOutlet]=\"loginTemplate\"\r\n [ngTemplateOutletContext]=\"{login: loginFunction, logout: logoutFunction, status: status$ | async}\">\r\n</ng-container>\r\n<ng-template #defaultLogin>\r\n <ng-container *ngIf=\"status$ | async as status\">\r\n <ng-container *ngIf=\"type === OAuthType.RESOURCE; else noResource\">\r\n <div class=\"oauth dropdown text-right p-3 {{collapse ? 'show': ''}}\">\r\n <button class=\"btn btn-link p-0 dropdown-toggle\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : toggleCollapse()\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </button>\r\n <div class=\"dropdown-menu mr-3 {{collapse ? 'show': ''}}\">\r\n <form class=\"p-3\" #form=\"ngForm\"\r\n *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED || status === OAuthStatus.DENIED\"\r\n (submit)=\"login({username: username, password: password})\">\r\n <div class=\"form-group\">\r\n <input type=\"text\"\r\n class=\"form-control\"\r\n name=\"username\"\r\n required\r\n [(ngModel)]=\"username\"\r\n [placeholder]=\"i18n.username\">\r\n </div>\r\n <div class=\"form-group\">\r\n <input type=\"password\"\r\n class=\"form-control\"\r\n name=\"password\"\r\n required\r\n [(ngModel)]=\"password\"\r\n [placeholder]=\"i18n.password\">\r\n </div>\r\n <div class=\"text-right\">\r\n <button type=\"submit\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"form.invalid\">{{i18n.submit}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #noResource>\r\n <a role=\"button\" class=\"oauth\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : login({redirectUri: redirectUri, state:state})\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </a>\r\n </ng-template>\r\n\r\n <ng-template #message>\r\n <span *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED\">{{i18n.notAuthorized}}</span>\r\n <span *ngIf=\"status === OAuthStatus.AUTHORIZED\">\r\n {{i18n.authorized}}<strong>&nbsp;{{profileName}}</strong>\r\n </span>\r\n <span *ngIf=\"status === OAuthStatus.DENIED\">{{i18n.denied}}</span>\r\n </ng-template>\r\n </ng-container>\r\n</ng-template>\r\n\r\n", styles: [".oauth .dropdown-menu{left:auto;right:0;box-shadow:0 5px 10px #0003;min-width:250px}.oauth .dropdown-menu:before{content:\"\";display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:#0003;position:absolute;top:-7px;left:auto;right:15px}.oauth .dropdown-menu:after{content:\"\";display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:auto;right:16px}\n"] }]
519
+ args: [{ selector: 'oauth-login', encapsulation: ViewEncapsulation.None, template: "<ng-container *ngIf=\"state$ | async\"></ng-container>\r\n<ng-container *ngIf=\"loginTemplate; else defaultLogin\"\r\n [ngTemplateOutlet]=\"loginTemplate\"\r\n [ngTemplateOutletContext]=\"{login: loginFunction, logout: logoutFunction, status: status$ | async}\">\r\n</ng-container>\r\n<ng-template #defaultLogin>\r\n <ng-container *ngIf=\"status$ | async as status\">\r\n <ng-container *ngIf=\"type === OAuthType.RESOURCE; else noResource\">\r\n <div class=\"oauth dropdown text-end p-3 {{collapse ? 'show': ''}}\">\r\n <button class=\"btn btn-link p-0 dropdown-toggle\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : toggleCollapse()\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </button>\r\n <div class=\"dropdown-menu mr-3 {{collapse ? 'show': ''}}\">\r\n <form class=\"p-3\" #form=\"ngForm\"\r\n *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED || status === OAuthStatus.DENIED\"\r\n (submit)=\"login({username: username, password: password})\">\r\n <div class=\"mb-3\">\r\n <input type=\"text\"\r\n class=\"form-control\"\r\n name=\"username\"\r\n required\r\n [(ngModel)]=\"username\"\r\n [placeholder]=\"i18n.username\">\r\n </div>\r\n <div class=\"mb-3\">\r\n <input type=\"password\"\r\n class=\"form-control\"\r\n name=\"password\"\r\n required\r\n [(ngModel)]=\"password\"\r\n [placeholder]=\"i18n.password\">\r\n </div>\r\n <div class=\"text-end\">\r\n <button type=\"submit\"\r\n class=\"btn btn-primary\"\r\n [disabled]=\"form.invalid\">{{i18n.submit}}</button>\r\n </div>\r\n </form>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-template #noResource>\r\n <a role=\"button\" class=\"oauth\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : login({redirectUri: redirectUri, state:state})\">\r\n <ng-container *ngTemplateOutlet=\"message\"></ng-container>\r\n </a>\r\n </ng-template>\r\n\r\n <ng-template #message>\r\n <span *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED\" class=\"not-authorized\">{{i18n.notAuthorized}}</span>\r\n <span *ngIf=\"status === OAuthStatus.AUTHORIZED\" class=\"authorized\">\r\n <span class=\"welcome\">{{i18n.authorized}}&nbsp;</span>\r\n <strong class=\"profile-name\" [innerHTML]=\"profileName\"></strong>\r\n </span>\r\n <span *ngIf=\"status === OAuthStatus.DENIED\" class=\"denied\">{{i18n.denied}}</span>\r\n </ng-template>\r\n </ng-container>\r\n</ng-template>\r\n\r\n", styles: [".oauth .dropdown-menu{left:auto;right:0;box-shadow:0 5px 10px #0003;min-width:250px}.oauth .dropdown-menu:before{content:\"\";display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:#0003;position:absolute;top:-7px;left:auto;right:15px}.oauth .dropdown-menu:after{content:\"\";display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:auto;right:16px}\n"] }]
456
520
  }], ctorParameters: function () {
457
- return [{ type: OAuthService }, { type: Location, decorators: [{
521
+ return [{ type: OAuthService }, { type: i2.Location }, { type: Location, decorators: [{
458
522
  type: Inject,
459
523
  args: [LOCATION]
460
524
  }] }];
461
525
  }, propDecorators: { i18n: [{
462
526
  type: Input
527
+ }], redirectUri: [{
528
+ type: Input
529
+ }], useLogoutUrl: [{
530
+ type: Input
463
531
  }], state: [{
464
532
  type: Input
465
533
  }], stateChange: [{
@@ -530,8 +598,7 @@ const defaultConfig = (storage) => {
530
598
  return {
531
599
  storage,
532
600
  storageKey: 'token',
533
- ignorePaths: [],
534
- pkce: false
601
+ ignorePaths: []
535
602
  };
536
603
  };
537
604
  class OAuthModule {
@@ -556,12 +623,12 @@ class OAuthModule {
556
623
  };
557
624
  }
558
625
  }
559
- OAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
560
- OAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthModule, declarations: [OAuthLoginComponent], imports: [CommonModule,
626
+ OAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
627
+ OAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthModule, declarations: [OAuthLoginComponent], imports: [CommonModule,
561
628
  FormsModule,
562
629
  HttpClientModule,
563
630
  RouterModule], exports: [OAuthLoginComponent] });
564
- OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthModule, providers: [
631
+ OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthModule, providers: [
565
632
  LocationService,
566
633
  StorageService,
567
634
  OAuthService,
@@ -572,7 +639,7 @@ OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "1
572
639
  HttpClientModule,
573
640
  RouterModule,
574
641
  ]] });
575
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: OAuthModule, decorators: [{
642
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: OAuthModule, decorators: [{
576
643
  type: NgModule,
577
644
  args: [{
578
645
  imports: [
@@ -600,4 +667,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImpor
600
667
  * Generated bundle index. Do not edit.
601
668
  */
602
669
 
603
- export { LOCATION, OAUTH_CONFIG, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE };
670
+ export { LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE };
671
+ //# sourceMappingURL=ngx-oauth.mjs.map