ngx-oauth 3.0.1 → 4.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.
@@ -1,10 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, Inject, EventEmitter, Component, ViewEncapsulation, Input, Output, ContentChild, HostListener, PLATFORM_ID, Optional, NgModule } from '@angular/core';
3
- import * as i1 from '@angular/common/http';
2
+ import { InjectionToken, inject, Injectable, Inject, Component, ViewEncapsulation, Input, Output, ContentChild, HostListener, PLATFORM_ID, Optional, NgModule } from '@angular/core';
3
+ import * as i2 from '@angular/common/http';
4
4
  import { HttpHeaders, HttpParams, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
5
- import { filter, map, switchMap, shareReplay, tap, catchError, concatMap, delay } from 'rxjs/operators';
6
- import { ReplaySubject, of, EMPTY, from, noop, throwError, Subscription, take } from 'rxjs';
7
- import * as i2 from '@angular/common';
5
+ import { shareReplay, map, catchError, filter, switchMap as switchMap$1, tap, concatMap, delay } from 'rxjs/operators';
6
+ import { BehaviorSubject, distinctUntilChanged, switchMap, of, ReplaySubject, from, noop, firstValueFrom, throwError, take, Subscription } from 'rxjs';
7
+ import { __classPrivateFieldGet, __classPrivateFieldSet } from 'tslib';
8
+ import * as i2$1 from '@angular/common';
8
9
  import { isPlatformBrowser, CommonModule } from '@angular/common';
9
10
  import * as i3 from '@angular/forms';
10
11
  import { FormsModule } from '@angular/forms';
@@ -16,11 +17,12 @@ const LOCATION = new InjectionToken('Location');
16
17
  const STORAGE = new InjectionToken('Storage');
17
18
  const OAUTH_CONFIG = new InjectionToken('OAuthConfig');
18
19
  const OAUTH_TOKEN = new InjectionToken('OAuthToken');
20
+ const HEADER_APPLICATION = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });
19
21
  class OAuthConfig {
20
22
  }
21
- OAuthConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
22
- OAuthConfig.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthConfig, providedIn: 'root', useFactory: () => inject(OAUTH_CONFIG).reduce((p, c) => ({ ...p, ...c }), {}) });
23
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthConfig, decorators: [{
23
+ OAuthConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
24
+ OAuthConfig.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthConfig, providedIn: 'root', useFactory: () => inject(OAUTH_CONFIG).reduce((p, c) => ({ ...p, ...c }), {}) });
25
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthConfig, decorators: [{
24
26
  type: Injectable,
25
27
  args: [{
26
28
  providedIn: 'root',
@@ -52,6 +54,77 @@ var OAuthStatus;
52
54
  OAuthStatus["DENIED"] = "DENIED";
53
55
  })(OAuthStatus || (OAuthStatus = {}));
54
56
 
57
+ var _TokenService_token$;
58
+ const isExpiredToken = (token) => token && token.expires && Date.now() > token.expires || false;
59
+ class TokenService {
60
+ constructor(authConfig, http, zone) {
61
+ this.authConfig = authConfig;
62
+ this.http = http;
63
+ this.zone = zone;
64
+ _TokenService_token$.set(this, new BehaviorSubject(this.saved));
65
+ this.token$ = __classPrivateFieldGet(this, _TokenService_token$, "f").pipe(distinctUntilChanged((p, c) => JSON.stringify(p || null) === JSON.stringify(c || null)), switchMap(token => !isExpiredToken(token) && of(token) || this.refreshToken(token)), shareReplay(1));
66
+ this.type$ = this.token$.pipe(map(token => token?.type), shareReplay(1));
67
+ this.accessToken$ = this.token$.pipe(map(token => token?.access_token), shareReplay(1));
68
+ }
69
+ get token() {
70
+ return __classPrivateFieldGet(this, _TokenService_token$, "f").value;
71
+ }
72
+ set token(token) {
73
+ const expiresIn = Number(token.expires_in) || 0;
74
+ const result = {
75
+ ...token,
76
+ ...expiresIn && { expires: Date.now() + expiresIn * 1000 } || {}
77
+ };
78
+ this.saved = result;
79
+ __classPrivateFieldGet(this, _TokenService_token$, "f").next(result);
80
+ }
81
+ get saved() {
82
+ const { storageKey, storage } = this.authConfig;
83
+ return storageKey && storage && storage[storageKey] && JSON.parse(storage[storageKey]) || {};
84
+ }
85
+ set saved(token) {
86
+ const { storageKey, storage } = this.authConfig;
87
+ if (storage && storageKey) {
88
+ if (token) {
89
+ storage[storageKey] = JSON.stringify(token);
90
+ }
91
+ else {
92
+ delete storage[storageKey];
93
+ }
94
+ }
95
+ }
96
+ refreshToken(token) {
97
+ const { tokenPath, clientId, clientSecret, scope } = this.authConfig.config;
98
+ const { refresh_token } = token || {};
99
+ return tokenPath && refresh_token && this.http.post(tokenPath, new HttpParams({
100
+ fromObject: {
101
+ client_id: clientId,
102
+ ...clientSecret && { client_secret: clientSecret } || {},
103
+ grant_type: 'refresh_token',
104
+ refresh_token,
105
+ ...scope && { scope } || {},
106
+ }
107
+ }), {
108
+ headers: HEADER_APPLICATION
109
+ }).pipe(catchError(() => {
110
+ this.token = {};
111
+ return of(this.token);
112
+ }), map(token => {
113
+ this.token = {
114
+ ...this.token,
115
+ ...token
116
+ };
117
+ return this.token;
118
+ })) || of(token);
119
+ }
120
+ }
121
+ _TokenService_token$ = new WeakMap();
122
+ TokenService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: TokenService, deps: [{ token: OAuthConfig }, { token: i2.HttpClient }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
123
+ TokenService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: TokenService });
124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: TokenService, decorators: [{
125
+ type: Injectable
126
+ }], ctorParameters: function () { return [{ type: OAuthConfig }, { type: i2.HttpClient }, { type: i0.NgZone }]; } });
127
+
55
128
  const arrToString = (buf) => buf.reduce((s, b) => s + String.fromCharCode(b), '');
56
129
  const base64url = (str) => btoa(str)
57
130
  .replace(/\+/g, '-')
@@ -65,7 +138,6 @@ const pkce = async (value) => {
65
138
  const buff = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));
66
139
  return base64url(arrToString(new Uint8Array(buff)));
67
140
  };
68
- const REQUEST_HEADER = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });
69
141
  const parseOauthUri = (hash) => {
70
142
  const regex = /([^&=]+)=([^&]*)/g;
71
143
  const params = {};
@@ -74,81 +146,49 @@ const parseOauthUri = (hash) => {
74
146
  while ((m = regex.exec(hash)) !== null) {
75
147
  params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
76
148
  }
77
- if (Object.keys(params).length) {
78
- return params;
79
- }
80
- return null;
149
+ return Object.keys(params).length && params || {};
81
150
  };
82
151
  const jwt = (token) => JSON.parse(atob(token.split('.')[1]));
83
152
  class OAuthService {
84
- constructor(http, zone, authConfig, location, locationService) {
85
- this.http = http;
86
- this.zone = zone;
153
+ constructor(authConfig, tokenService, http, location, locationService) {
87
154
  this.authConfig = authConfig;
155
+ this.tokenService = tokenService;
156
+ this.http = http;
88
157
  this.location = location;
89
158
  this.locationService = locationService;
90
- this._token = null;
91
- this._status = OAuthStatus.NOT_AUTHORIZED;
92
159
  this.state$ = new ReplaySubject(1);
93
- this.status$ = new ReplaySubject(1);
94
- this.userInfo$ = this.status$.pipe(filter(s => s === OAuthStatus.AUTHORIZED), map(() => {
95
- const { config } = this.authConfig;
96
- return config.userPath;
97
- }), filter(p => !!p), switchMap(path => this.http.get(path)), shareReplay());
98
- setTimeout(() => this.init()); // decouple for http interceptor
99
- }
100
- /**
101
- * Get the oauth config for initialize. If OpenId with issuerPath is configured then configure from server openid configuration.
102
- * @protected
103
- */
104
- get config$() {
105
- let { config } = this.authConfig;
106
- if (config && config.clientId) {
107
- const { issuerPath, scope } = config;
108
- if (issuerPath) {
109
- return this.http.get(`${issuerPath}/.well-known/openid-configuration`).pipe(tap(v => this.type && this.set(this.type, {
110
- ...v.authorization_endpoint && { authorizePath: v.authorization_endpoint } || {},
111
- ...v.token_endpoint && { tokenPath: v.token_endpoint } || {},
112
- ...v.revocation_endpoint && { revokePath: v.revocation_endpoint } || {},
113
- ...v.code_challenge_methods_supported && { pkce: v.code_challenge_methods_supported.indexOf('S256') > -1 } || {},
114
- ...v.userinfo_endpoint && { userPath: v.userinfo_endpoint } || {},
115
- ...v.introspection_endpoint && { introspectionPath: v.introspection_endpoint } || {},
116
- ...v.end_session_endpoint && { logoutPath: v.end_session_endpoint } || {},
117
- ...scope && {} || { scope: 'openid' }
118
- })), map(() => this.authConfig.config));
119
- }
120
- return of(config);
121
- }
122
- console.warn('clientId is missing in oauth config');
123
- return EMPTY;
124
- }
125
- /**
126
- * Init. Will check the url implicit or authorization flow or existing saved token.
127
- * @protected
128
- */
129
- init() {
130
- const { hash, search, origin, pathname } = this.location;
131
- const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
132
- const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search);
133
- const { storageKey } = this.authConfig;
134
- const savedToken = storageKey && this.authConfig.storage && this.authConfig.storage[storageKey] &&
135
- JSON.parse(this.authConfig.storage[storageKey]);
136
- this.config$.subscribe(config => {
160
+ this.config$ = of(this.config).pipe(filter(Boolean), filter(config => !!config?.clientId), map(config => config), switchMap$1(config => !config.issuerPath && of(config) || this.http.get(`${config.issuerPath}/.well-known/openid-configuration`).pipe(tap(v => this.config = {
161
+ ...v.authorization_endpoint && { authorizePath: v.authorization_endpoint } || {},
162
+ ...v.token_endpoint && { tokenPath: v.token_endpoint } || {},
163
+ ...v.revocation_endpoint && { revokePath: v.revocation_endpoint } || {},
164
+ ...v.code_challenge_methods_supported && { pkce: v.code_challenge_methods_supported.indexOf('S256') > -1 } || {},
165
+ ...v.userinfo_endpoint && { userPath: v.userinfo_endpoint } || {},
166
+ ...v.introspection_endpoint && { introspectionPath: v.introspection_endpoint } || {},
167
+ ...v.end_session_endpoint && { logoutPath: v.end_session_endpoint } || {},
168
+ ...{ scope: config.scope || 'openid' }
169
+ }), map(() => this.config))), shareReplay(1));
170
+ this.token$ = this.config$.pipe(tap(config => {
171
+ const { hash, search, origin, pathname } = this.location;
172
+ const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
173
+ const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search) || hash && /(code=)|(error=)/.test(hash);
137
174
  if (isImplicitRedirect) {
138
- const parameters = parseOauthUri(hash.substr(1));
139
- this.token = parameters;
140
- this.status = this.checkResponse(savedToken, parameters) && OAuthStatus.AUTHORIZED || OAuthStatus.DENIED;
175
+ const parameters = parseOauthUri(hash.substring(1));
176
+ this.token = {
177
+ ...parameters,
178
+ type: OAuthType.IMPLICIT,
179
+ };
180
+ this.checkResponse(this.token, parameters);
141
181
  }
142
182
  else if (isAuthCodeRedirect) {
143
- const parameters = parseOauthUri(search.substr(1));
144
- if (!this.checkResponse(savedToken, parameters)) {
183
+ const parameters = parseOauthUri(search && search.substring(1) || hash && hash.substring(1));
184
+ console.log(parameters);
185
+ if (!this.checkResponse(this.token, parameters)) {
145
186
  this.token = parameters;
146
- this.status = OAuthStatus.DENIED;
147
187
  }
148
188
  else {
149
189
  const newParametersString = this.getCleanedUnSearchParameters();
150
190
  const { clientId, clientSecret, tokenPath, scope } = config;
151
- const codeVerifier = savedToken && savedToken.codeVerifier;
191
+ const { codeVerifier } = this.token || {}; //should be set by authorizationUrl construction
152
192
  this.http.post(tokenPath, new HttpParams({
153
193
  fromObject: {
154
194
  code: parameters?.['code'],
@@ -159,56 +199,55 @@ class OAuthService {
159
199
  ...scope && { scope } || {},
160
200
  ...codeVerifier && { code_verifier: codeVerifier } || {}
161
201
  }
162
- }), { headers: REQUEST_HEADER }).pipe(catchError((err) => {
163
- this.token = err;
164
- this.status = OAuthStatus.DENIED;
165
- this.locationService.replaceState(`${pathname}${newParametersString}`);
166
- return EMPTY;
167
- })).subscribe(token => {
168
- this.token = token;
169
- this.status = OAuthStatus.AUTHORIZED;
202
+ }), { headers: HEADER_APPLICATION }).pipe().subscribe(token => {
203
+ this.token = {
204
+ ...token,
205
+ type: OAuthType.AUTHORIZATION_CODE
206
+ };
170
207
  this.locationService.replaceState(`${pathname}${newParametersString}`);
171
208
  });
172
209
  }
173
210
  }
174
- else if (savedToken) {
175
- this._token = savedToken;
176
- const { access_token, refresh_token, error } = savedToken;
177
- if (access_token) {
178
- if (refresh_token) { // force refresh since might be a manual page refresh
179
- this.refreshToken();
180
- }
181
- else {
182
- this.status = OAuthStatus.AUTHORIZED;
183
- }
184
- }
185
- else {
186
- this.status = error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED;
187
- }
188
- }
189
- else {
190
- this.status = OAuthStatus.NOT_AUTHORIZED;
191
- }
192
- });
211
+ }), switchMap$1(() => this.tokenService.token$), shareReplay(1));
212
+ this.status$ = this.token$.pipe(map(token => token.access_token && OAuthStatus.AUTHORIZED || token.error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED), shareReplay(1));
213
+ this.userInfo$ = this.status$.pipe(filter(s => s === OAuthStatus.AUTHORIZED), map(() => {
214
+ const { config } = this.authConfig;
215
+ return config.userPath;
216
+ }), filter(Boolean), switchMap$1(path => this.http.get(path)), shareReplay(1));
217
+ this.type$ = this.tokenService.type$;
218
+ this.ignorePaths = this.authConfig.ignorePaths || [];
193
219
  }
194
- async login(parameters) {
195
- if (this.isResourceType(parameters)) {
196
- this.resourceLogin(parameters);
220
+ get token() {
221
+ return this.tokenService.token;
222
+ }
223
+ set token(token) {
224
+ this.tokenService.token = token;
225
+ }
226
+ get config() {
227
+ return this.authConfig.config;
228
+ }
229
+ set config(config) {
230
+ if (config) {
231
+ this.authConfig.config = {
232
+ ...this.authConfig.config,
233
+ ...config
234
+ };
197
235
  }
198
- else if (this.isAuthorizationCodeType(parameters)) {
199
- await this.authorizationCodeLogin(parameters);
236
+ }
237
+ async login(parameters) {
238
+ if (!!parameters && parameters.password) {
239
+ await this.resourceLogin(parameters);
200
240
  }
201
- else if (this.isImplicitType(parameters)) {
202
- await this.implicitLogin(parameters);
241
+ else if (!!parameters && parameters.redirectUri && parameters.responseType) {
242
+ await this.toAuthorizationUrl(parameters);
203
243
  }
204
- else if (this.isClientCredentialType()) {
205
- this.clientCredentialLogin();
244
+ else {
245
+ await this.clientCredentialLogin();
206
246
  }
207
247
  }
208
248
  logout(useLogoutUrl) {
209
249
  this.revoke();
210
- this.token = null;
211
- this.status = OAuthStatus.NOT_AUTHORIZED;
250
+ this.token = {};
212
251
  const { logoutPath, logoutRedirectUri } = this.authConfig.config;
213
252
  if (useLogoutUrl && logoutPath) {
214
253
  const { origin, pathname } = this.location;
@@ -219,7 +258,7 @@ class OAuthService {
219
258
  revoke() {
220
259
  const { revokePath, clientId, clientSecret } = this.authConfig.config;
221
260
  if (revokePath) {
222
- const { access_token, refresh_token } = this.token;
261
+ const { access_token, refresh_token } = this.token || {};
223
262
  const toRevoke = [];
224
263
  if (access_token) {
225
264
  toRevoke.push({
@@ -238,35 +277,32 @@ class OAuthService {
238
277
  });
239
278
  }
240
279
  from(toRevoke).pipe(concatMap(o => of(o).pipe(delay(300))), // space request to avoid cancellation
241
- switchMap(o => this.http.post(revokePath, new HttpParams({ fromObject: o })))).subscribe(noop);
280
+ switchMap$1(o => this.http.post(revokePath, new HttpParams({ fromObject: o })))).subscribe(noop);
242
281
  }
243
282
  }
244
- get status() {
245
- return this._status;
246
- }
247
- set status(status) {
248
- this._status = status;
249
- this.status$.next(status);
250
- }
251
- set(type, config) {
252
- this.authConfig.type = type;
253
- if (config) {
254
- this.authConfig.config = {
255
- ...this.authConfig.config,
256
- ...config
283
+ clientCredentialLogin() {
284
+ const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
285
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
286
+ fromObject: {
287
+ client_id: clientId,
288
+ client_secret: clientSecret,
289
+ grant_type: OAuthType.CLIENT_CREDENTIAL,
290
+ ...scope ? { scope } : {},
291
+ }
292
+ }), { headers: HEADER_APPLICATION }).pipe(catchError((err) => {
293
+ this.token = err;
294
+ return throwError(() => err);
295
+ }), tap(params => {
296
+ this.token = {
297
+ ...params,
298
+ type: OAuthType.CLIENT_CREDENTIAL,
257
299
  };
258
- }
259
- }
260
- get type() {
261
- return this.authConfig.type;
262
- }
263
- get ignorePaths() {
264
- return this.authConfig.ignorePaths || [];
300
+ })));
265
301
  }
266
302
  resourceLogin(parameters) {
267
303
  const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
268
304
  const { username, password } = parameters;
269
- this.http.post(tokenPath, new HttpParams({
305
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
270
306
  fromObject: {
271
307
  client_id: clientId,
272
308
  ...clientSecret && { client_secret: clientSecret } || {},
@@ -275,63 +311,26 @@ class OAuthService {
275
311
  username,
276
312
  password
277
313
  }
278
- }), { headers: REQUEST_HEADER }).pipe(catchError(err => {
314
+ }), { headers: HEADER_APPLICATION }).pipe(catchError(err => {
279
315
  this.token = err;
280
- this.status = OAuthStatus.DENIED;
281
- return EMPTY;
282
- })).subscribe(params => {
283
- this.token = params;
284
- this.status = OAuthStatus.AUTHORIZED;
285
- });
286
- }
287
- async authorizationCodeLogin(parameters) {
288
- const authUrl = await this.toAuthorizationUrl(parameters, OAuthType.AUTHORIZATION_CODE);
289
- this.location.replace(authUrl);
290
- }
291
- async implicitLogin(parameters) {
292
- const authUrl = await this.toAuthorizationUrl(parameters, OAuthType.IMPLICIT);
293
- this.location.replace(authUrl);
294
- }
295
- clientCredentialLogin() {
296
- const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
297
- this.http.post(tokenPath, new HttpParams({
298
- fromObject: {
299
- client_id: clientId,
300
- client_secret: clientSecret,
301
- grant_type: OAuthType.CLIENT_CREDENTIAL,
302
- ...scope ? { scope } : {},
303
- }
304
- }), { headers: REQUEST_HEADER }).pipe(catchError((err) => {
305
- this.token = err;
306
- this.status = OAuthStatus.DENIED;
307
- return EMPTY;
308
- })).subscribe(params => {
309
- this.token = params;
310
- this.status = OAuthStatus.AUTHORIZED;
311
- });
312
- }
313
- isClientCredentialType() {
314
- return this.authConfig.type === OAuthType.CLIENT_CREDENTIAL;
315
- }
316
- isResourceType(parameters) {
317
- return this.authConfig.type === OAuthType.RESOURCE && !!parameters?.password;
318
- }
319
- isImplicitType(parameters) {
320
- return this.authConfig.type === OAuthType.IMPLICIT && !!parameters?.redirectUri;
321
- }
322
- isAuthorizationCodeType(parameters) {
323
- return this.authConfig.type === OAuthType.AUTHORIZATION_CODE && !!parameters?.redirectUri;
316
+ return throwError(() => err);
317
+ }), tap(params => {
318
+ this.token = {
319
+ ...params,
320
+ type: OAuthType.RESOURCE,
321
+ };
322
+ })));
324
323
  }
325
- async toAuthorizationUrl(parameters, responseType) {
324
+ async toAuthorizationUrl(parameters) {
326
325
  const { config } = this.authConfig;
327
326
  let authorizationUrl = `${config.authorizePath}`;
328
327
  authorizationUrl += config.authorizePath.includes('?') && '&' || '?';
329
328
  authorizationUrl += `client_id=${config.clientId}`;
330
329
  authorizationUrl += `&redirect_uri=${encodeURIComponent(parameters.redirectUri)}`;
331
- authorizationUrl += `&response_type=${responseType}`;
330
+ authorizationUrl += `&response_type=${parameters.responseType}`;
332
331
  authorizationUrl += `&scope=${encodeURIComponent(config.scope || '')}`;
333
332
  authorizationUrl += `&state=${encodeURIComponent(parameters.state || '')}`;
334
- return `${authorizationUrl}${this.generateNonce(config)}${await this.generateCodeChallenge(config)}`;
333
+ return this.location.replace(`${authorizationUrl}${this.generateNonce(config)}${await this.generateCodeChallenge(config)}`);
335
334
  }
336
335
  async generateCodeChallenge(config) {
337
336
  if (config.pkce) {
@@ -361,60 +360,11 @@ class OAuthService {
361
360
  }
362
361
  return parameters['access_token'] || parameters['code'];
363
362
  }
364
- set token(token) {
365
- this._token = token;
366
- const { storageKey } = this.authConfig;
367
- if (token) {
368
- // @ts-ignore
369
- this.authConfig.storage[storageKey] = JSON.stringify(this.token);
370
- clearTimeout(this.timer);
371
- if (this.token && this.token.expires_in) {
372
- this.zone.runOutsideAngular(() => {
373
- this.timer = setTimeout(() => {
374
- this.zone.run(() => {
375
- this.refreshToken();
376
- });
377
- }, Number(this.token?.expires_in) * 1000);
378
- });
379
- }
380
- }
381
- else {
382
- // @ts-ignore
383
- delete this.authConfig.storage[storageKey];
384
- }
385
- }
386
- get token() {
387
- return this._token;
388
- }
389
- refreshToken() {
390
- const { tokenPath, clientId, clientSecret, scope } = this.authConfig.config;
391
- const { refresh_token } = this.token;
392
- if (tokenPath && refresh_token) {
393
- this.http.post(tokenPath, new HttpParams({
394
- fromObject: {
395
- client_id: clientId,
396
- ...clientSecret && { client_secret: clientSecret } || {},
397
- grant_type: 'refresh_token',
398
- refresh_token,
399
- ...scope && { scope } || {},
400
- }
401
- }), { headers: REQUEST_HEADER }).pipe(catchError(() => {
402
- this.logout();
403
- return EMPTY;
404
- })).subscribe(params => {
405
- this.token = {
406
- ...this.token,
407
- ...params
408
- };
409
- this.status = OAuthStatus.AUTHORIZED;
410
- });
411
- }
412
- }
413
363
  getCleanedUnSearchParameters() {
414
364
  const { search } = this.location;
415
- let searchString = search.substr(1);
365
+ let searchString = search && search.substring(1) || '';
416
366
  const hashKeys = ['code', 'state', 'error', 'error_description', 'session_state', 'scope', 'authuser', 'prompt'];
417
- hashKeys.forEach((hashKey) => {
367
+ hashKeys.forEach(hashKey => {
418
368
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
419
369
  searchString = searchString.replace(re, '');
420
370
  });
@@ -422,62 +372,69 @@ class OAuthService {
422
372
  }
423
373
  cleanLocationHash() {
424
374
  const { hash } = this.location;
425
- let curHash = hash.substr(1);
426
- const hashKeys = ['access_token', 'token_type', 'expires_in', 'scope', 'state', 'error', 'error_description', 'session_state', 'nonce'];
427
- hashKeys.forEach((hashKey) => {
375
+ let curHash = hash && hash.substring(1) || '';
376
+ const hashKeys = [
377
+ 'access_token',
378
+ 'token_type',
379
+ 'expires_in',
380
+ 'scope',
381
+ 'state',
382
+ 'error',
383
+ 'error_description',
384
+ 'session_state',
385
+ 'nonce',
386
+ 'id_token',
387
+ 'code'
388
+ ];
389
+ hashKeys.forEach(hashKey => {
428
390
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
429
391
  curHash = curHash.replace(re, '');
430
392
  });
431
393
  this.location.hash = curHash;
432
394
  }
433
395
  emitState(parameters) {
434
- const { state } = parameters;
435
- if (state) {
436
- this.state$.next(state);
437
- }
396
+ const { state } = parameters || {};
397
+ state && this.state$.next(state);
438
398
  }
439
399
  }
440
- OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthService, deps: [{ token: i1.HttpClient }, { token: i0.NgZone }, { token: OAuthConfig }, { token: LOCATION }, { token: i2.Location }], target: i0.ɵɵFactoryTarget.Injectable });
441
- OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthService });
442
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthService, decorators: [{
400
+ OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthService, deps: [{ token: OAuthConfig }, { token: TokenService }, { token: i2.HttpClient }, { token: LOCATION }, { token: i2$1.Location }], target: i0.ɵɵFactoryTarget.Injectable });
401
+ OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthService });
402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthService, decorators: [{
443
403
  type: Injectable
444
- }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i0.NgZone }, { type: OAuthConfig }, { type: Location, decorators: [{
404
+ }], ctorParameters: function () { return [{ type: OAuthConfig }, { type: TokenService }, { type: i2.HttpClient }, { type: Location, decorators: [{
445
405
  type: Inject,
446
406
  args: [LOCATION]
447
- }] }, { type: i2.Location }]; } });
407
+ }] }, { type: i2$1.Location }]; } });
448
408
 
449
409
  class OAuthInterceptor {
450
- constructor(oauthService) {
451
- this.oauthService = oauthService;
410
+ constructor(tokenService, authConfig) {
411
+ this.tokenService = tokenService;
412
+ this.authConfig = authConfig;
452
413
  }
453
414
  intercept(req, next) {
454
- if (this.oauthService) {
455
- if (!this.isPathExcepted(req)) {
456
- const { token } = this.oauthService;
457
- if (token && token.access_token) {
458
- req = req.clone({
459
- setHeaders: {
460
- Authorization: `${token.token_type} ${token.access_token}`
461
- }
462
- });
463
- }
415
+ return this.tokenService.token$.pipe(take(1), map(token => {
416
+ if (token?.access_token && !this.isPathExcepted(req)) {
417
+ req = req.clone({
418
+ setHeaders: {
419
+ Authorization: `${token.token_type} ${token.access_token}`
420
+ }
421
+ });
464
422
  }
465
- return next.handle(req).pipe(catchError((err) => {
466
- if (err.status === 401 && !this.isPathExcepted(req)) {
467
- this.oauthService.token = null;
468
- this.oauthService.status = OAuthStatus.DENIED;
469
- }
470
- return throwError(err);
471
- }));
472
- }
473
- else {
474
- return next.handle(req);
475
- }
423
+ return req;
424
+ }), switchMap(req => next.handle(req)), catchError((err) => {
425
+ if (err.status === 401 && !this.isPathExcepted(req)) {
426
+ this.tokenService.token = {
427
+ error: `${err.status}`,
428
+ error_description: err.message
429
+ };
430
+ }
431
+ return throwError(() => err);
432
+ }));
476
433
  }
477
434
  isPathExcepted(req) {
478
- const { ignorePaths } = this.oauthService;
435
+ const { ignorePaths } = this.authConfig || {};
479
436
  if (ignorePaths) {
480
- for (const ignorePath of this.oauthService.ignorePaths) {
437
+ for (const ignorePath of ignorePaths) {
481
438
  try {
482
439
  if (req.url.match(ignorePath)) {
483
440
  return true;
@@ -490,39 +447,41 @@ class OAuthInterceptor {
490
447
  return false;
491
448
  }
492
449
  }
493
- OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthInterceptor, deps: [{ token: OAuthService }], target: i0.ɵɵFactoryTarget.Injectable });
494
- OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthInterceptor });
495
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthInterceptor, decorators: [{
450
+ OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthInterceptor, deps: [{ token: TokenService }, { token: OAuthConfig }], target: i0.ɵɵFactoryTarget.Injectable });
451
+ OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthInterceptor });
452
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthInterceptor, decorators: [{
496
453
  type: Injectable
497
- }], ctorParameters: function () { return [{ type: OAuthService }]; } });
454
+ }], ctorParameters: function () { return [{ type: TokenService }, { type: OAuthConfig }]; } });
498
455
 
456
+ var _OAuthLoginComponent_subscription, _OAuthLoginComponent_redirectUri, _OAuthLoginComponent_responseType, _OAuthLoginComponent_i18n;
499
457
  class OAuthLoginComponent {
500
458
  constructor(oauthService, locationService, location) {
501
459
  this.oauthService = oauthService;
502
460
  this.locationService = locationService;
503
461
  this.location = location;
504
- this.subscription = new Subscription();
505
- this._i18n = {
462
+ _OAuthLoginComponent_subscription.set(this, new Subscription());
463
+ _OAuthLoginComponent_redirectUri.set(this, void 0);
464
+ _OAuthLoginComponent_responseType.set(this, void 0);
465
+ _OAuthLoginComponent_i18n.set(this, {
506
466
  username: 'Username',
507
467
  password: 'Password',
508
468
  submit: 'Sign in',
509
469
  notAuthorized: 'Sign in',
510
470
  authorized: 'Welcome',
511
471
  denied: 'Access Denied. Try again!'
512
- };
472
+ });
473
+ this.type = OAuthType.RESOURCE;
513
474
  this.useLogoutUrl = false;
514
475
  this.state = '';
515
- this.stateChange = new EventEmitter();
476
+ this.stateChange = this.oauthService.state$.asObservable();
516
477
  this.username = '';
517
478
  this.password = '';
518
479
  this.OAuthStatus = OAuthStatus;
519
480
  this.OAuthType = OAuthType;
520
481
  this.collapse = false;
521
- this.type = this.oauthService.type;
522
- this.state$ = this.oauthService.state$.pipe(tap(s => this.stateChange.emit(s)));
523
482
  this.status$ = this.oauthService.status$.pipe(tap(s => {
524
483
  if (s === OAuthStatus.AUTHORIZED && this.profileName$) {
525
- this.subscription.add(this.profileName$.pipe(take(1)).subscribe(n => this.profileName = n));
484
+ __classPrivateFieldGet(this, _OAuthLoginComponent_subscription, "f").add(this.profileName$.pipe(take(1)).subscribe(n => this.profileName = n));
526
485
  }
527
486
  else {
528
487
  const { token } = this.oauthService;
@@ -534,31 +493,39 @@ class OAuthLoginComponent {
534
493
  this.logoutFunction = () => this.logout();
535
494
  }
536
495
  get i18n() {
537
- return this._i18n;
496
+ return __classPrivateFieldGet(this, _OAuthLoginComponent_i18n, "f");
538
497
  }
539
498
  set i18n(i18n) {
540
- this._i18n = {
541
- ...this._i18n,
499
+ __classPrivateFieldSet(this, _OAuthLoginComponent_i18n, {
500
+ ...__classPrivateFieldGet(this, _OAuthLoginComponent_i18n, "f"),
542
501
  ...i18n
543
- };
502
+ }, "f");
503
+ }
504
+ get redirectUri() {
505
+ return __classPrivateFieldGet(this, _OAuthLoginComponent_redirectUri, "f") || `${this.location.origin}${this.locationService.path(true) || '/'}`;
544
506
  }
545
507
  set redirectUri(redirectUri) {
546
508
  if (redirectUri) {
547
- this._redirectUri = redirectUri;
509
+ __classPrivateFieldSet(this, _OAuthLoginComponent_redirectUri, redirectUri, "f");
548
510
  }
549
511
  }
550
- get redirectUri() {
551
- return this._redirectUri || `${this.location.origin}${this.locationService.path(true) || '/'}`;
512
+ set responseType(responseType) {
513
+ if (this.responseType) {
514
+ __classPrivateFieldSet(this, _OAuthLoginComponent_responseType, responseType, "f");
515
+ }
516
+ }
517
+ get responseType() {
518
+ return __classPrivateFieldGet(this, _OAuthLoginComponent_responseType, "f") || this.type;
552
519
  }
553
520
  ngOnDestroy() {
554
- this.subscription.unsubscribe();
521
+ __classPrivateFieldGet(this, _OAuthLoginComponent_subscription, "f").unsubscribe();
555
522
  }
556
523
  logout() {
557
524
  this.oauthService.logout(this.useLogoutUrl);
558
525
  }
559
- async login(parameters) {
560
- await this.oauthService.login(parameters);
526
+ login(parameters) {
561
527
  this.collapse = false;
528
+ return this.oauthService.login(parameters);
562
529
  }
563
530
  toggleCollapse() {
564
531
  this.collapse = !this.collapse;
@@ -567,18 +534,23 @@ class OAuthLoginComponent {
567
534
  this.collapse = false;
568
535
  }
569
536
  }
570
- OAuthLoginComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthLoginComponent, deps: [{ token: OAuthService }, { token: i2.Location }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Component });
571
- OAuthLoginComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.0", 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"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", 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]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None });
572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthLoginComponent, decorators: [{
537
+ _OAuthLoginComponent_subscription = new WeakMap(), _OAuthLoginComponent_redirectUri = new WeakMap(), _OAuthLoginComponent_responseType = new WeakMap(), _OAuthLoginComponent_i18n = new WeakMap();
538
+ OAuthLoginComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthLoginComponent, deps: [{ token: OAuthService }, { token: i2$1.Location }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Component });
539
+ OAuthLoginComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.3", type: OAuthLoginComponent, selector: "oauth-login", inputs: { type: "type", i18n: "i18n", redirectUri: "redirectUri", responseType: "responseType", 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=\"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 {{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\"\r\n #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\"\r\n class=\"oauth\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : login({responseType: responseType, 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 class=\"not-authorized\"\r\n *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED\"\r\n [innerHTML]=\"i18n.notAuthorized\"></span>\r\n <span class=\"authorized\"\r\n *ngIf=\"status === OAuthStatus.AUTHORIZED\">\r\n <span class=\"welcome\" [innerHTML]=\"i18n.authorized + '&nbsp;'\"></span>\r\n <strong class=\"profile-name\"\r\n [innerHTML]=\"profileName\"></strong>\r\n </span>\r\n <span class=\"denied\"\r\n *ngIf=\"status === OAuthStatus.DENIED\"\r\n [innerHTML]=\"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"], dependencies: [{ kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", 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]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: i2$1.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None });
540
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthLoginComponent, decorators: [{
573
541
  type: Component,
574
- 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"] }]
575
- }], ctorParameters: function () { return [{ type: OAuthService }, { type: i2.Location }, { type: Location, decorators: [{
542
+ args: [{ selector: 'oauth-login', encapsulation: ViewEncapsulation.None, template: "<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 {{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\"\r\n #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\"\r\n class=\"oauth\"\r\n (click)=\"status === OAuthStatus.AUTHORIZED ? logout() : login({responseType: responseType, 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 class=\"not-authorized\"\r\n *ngIf=\"status === OAuthStatus.NOT_AUTHORIZED\"\r\n [innerHTML]=\"i18n.notAuthorized\"></span>\r\n <span class=\"authorized\"\r\n *ngIf=\"status === OAuthStatus.AUTHORIZED\">\r\n <span class=\"welcome\" [innerHTML]=\"i18n.authorized + '&nbsp;'\"></span>\r\n <strong class=\"profile-name\"\r\n [innerHTML]=\"profileName\"></strong>\r\n </span>\r\n <span class=\"denied\"\r\n *ngIf=\"status === OAuthStatus.DENIED\"\r\n [innerHTML]=\"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"] }]
543
+ }], ctorParameters: function () { return [{ type: OAuthService }, { type: i2$1.Location }, { type: Location, decorators: [{
576
544
  type: Inject,
577
545
  args: [LOCATION]
578
- }] }]; }, propDecorators: { i18n: [{
546
+ }] }]; }, propDecorators: { type: [{
547
+ type: Input
548
+ }], i18n: [{
579
549
  type: Input
580
550
  }], redirectUri: [{
581
551
  type: Input
552
+ }], responseType: [{
553
+ type: Input
582
554
  }], useLogoutUrl: [{
583
555
  type: Input
584
556
  }], state: [{
@@ -602,10 +574,10 @@ const mockLocation = (serverHost, serverPath) => {
602
574
  href, origin, protocol, host, hostname, port, pathname, search, hash,
603
575
  reload() {
604
576
  },
605
- assign(u) {
577
+ assign(_) {
606
578
  },
607
579
  ancestorOrigins: {},
608
- replace(u) {
580
+ replace(_) {
609
581
  }
610
582
  };
611
583
  };
@@ -661,26 +633,27 @@ class OAuthModule {
661
633
  providers: [
662
634
  LocationService,
663
635
  StorageService,
664
- OAuthService,
665
- OAuthInterceptorService,
666
636
  provideOAuthConfigFactory((storage) => ({
667
637
  ...defaultConfig(storage),
668
638
  ...config
669
639
  }), [STORAGE]),
640
+ TokenService,
641
+ OAuthInterceptorService,
642
+ OAuthService,
670
643
  ]
671
644
  };
672
645
  }
673
646
  }
674
- OAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
675
- OAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, declarations: [OAuthLoginComponent], imports: [CommonModule,
647
+ OAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
648
+ OAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.3", ngImport: i0, type: OAuthModule, declarations: [OAuthLoginComponent], imports: [CommonModule,
676
649
  FormsModule,
677
650
  HttpClientModule,
678
651
  RouterModule], exports: [OAuthLoginComponent] });
679
- OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, imports: [CommonModule,
652
+ OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthModule, imports: [CommonModule,
680
653
  FormsModule,
681
654
  HttpClientModule,
682
655
  RouterModule] });
683
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, decorators: [{
656
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.3", ngImport: i0, type: OAuthModule, decorators: [{
684
657
  type: NgModule,
685
658
  args: [{
686
659
  imports: [
@@ -702,5 +675,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImpor
702
675
  * Generated bundle index. Do not edit.
703
676
  */
704
677
 
705
- export { LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthConfig, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE, provideOAuthConfig, provideOAuthConfigFactory };
678
+ export { HEADER_APPLICATION, LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthConfig, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE, provideOAuthConfig, provideOAuthConfigFactory };
706
679
  //# sourceMappingURL=ngx-oauth.mjs.map