ngx-oauth 3.0.0 → 4.0.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,11 +1,11 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Injectable, Inject, EventEmitter, Component, ViewEncapsulation, Input, Output, ContentChild, HostListener, PLATFORM_ID, Optional, NgModule } from '@angular/core';
3
- import { __awaiter } from 'tslib';
4
- 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';
5
4
  import { HttpHeaders, HttpParams, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
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
- import * as i2 from '@angular/common';
5
+ import { __classPrivateFieldGet, __awaiter, __classPrivateFieldSet } from 'tslib';
6
+ import { shareReplay, map, catchError, filter, switchMap as switchMap$1, tap, concatMap, delay } from 'rxjs/operators';
7
+ import { BehaviorSubject, distinctUntilChanged, switchMap, of, ReplaySubject, from, noop, firstValueFrom, throwError, take, Subscription } from 'rxjs';
8
+ import * as i2$1 from '@angular/common';
9
9
  import { isPlatformBrowser, CommonModule } from '@angular/common';
10
10
  import * as i3 from '@angular/forms';
11
11
  import { FormsModule } from '@angular/forms';
@@ -17,6 +17,29 @@ const LOCATION = new InjectionToken('Location');
17
17
  const STORAGE = new InjectionToken('Storage');
18
18
  const OAUTH_CONFIG = new InjectionToken('OAuthConfig');
19
19
  const OAUTH_TOKEN = new InjectionToken('OAuthToken');
20
+ const HEADER_APPLICATION = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });
21
+ class OAuthConfig {
22
+ }
23
+ OAuthConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
24
+ OAuthConfig.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthConfig, providedIn: 'root', useFactory: () => inject(OAUTH_CONFIG).reduce((p, c) => (Object.assign(Object.assign({}, p), c)), {}) });
25
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthConfig, decorators: [{
26
+ type: Injectable,
27
+ args: [{
28
+ providedIn: 'root',
29
+ useFactory: () => inject(OAUTH_CONFIG).reduce((p, c) => (Object.assign(Object.assign({}, p), c)), {})
30
+ }]
31
+ }] });
32
+ const provideOAuthConfig = (config = {}) => ({
33
+ provide: OAUTH_CONFIG,
34
+ useValue: config,
35
+ multi: true
36
+ });
37
+ const provideOAuthConfigFactory = (factory, deps) => ({
38
+ provide: OAUTH_CONFIG,
39
+ useFactory: factory,
40
+ deps: deps,
41
+ multi: true
42
+ });
20
43
  var OAuthType;
21
44
  (function (OAuthType) {
22
45
  OAuthType["RESOURCE"] = "password";
@@ -31,6 +54,65 @@ var OAuthStatus;
31
54
  OAuthStatus["DENIED"] = "DENIED";
32
55
  })(OAuthStatus || (OAuthStatus = {}));
33
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 === null || token === void 0 ? void 0 : token.type), shareReplay(1));
67
+ this.accessToken$ = this.token$.pipe(map(token => token === null || token === void 0 ? void 0 : 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 = Object.assign(Object.assign({}, token), expiresIn && { expires: Date.now() + expiresIn * 1000 } || {});
75
+ this.saved = result;
76
+ __classPrivateFieldGet(this, _TokenService_token$, "f").next(result);
77
+ }
78
+ get saved() {
79
+ const { storageKey, storage } = this.authConfig;
80
+ return storageKey && storage && storage[storageKey] && JSON.parse(storage[storageKey]) || {};
81
+ }
82
+ set saved(token) {
83
+ const { storageKey, storage } = this.authConfig;
84
+ if (storage && storageKey) {
85
+ if (token) {
86
+ storage[storageKey] = JSON.stringify(token);
87
+ }
88
+ else {
89
+ delete storage[storageKey];
90
+ }
91
+ }
92
+ }
93
+ refreshToken(token) {
94
+ const { tokenPath, clientId, clientSecret, scope } = this.authConfig.config;
95
+ const { refresh_token } = token || {};
96
+ return tokenPath && refresh_token && this.http.post(tokenPath, new HttpParams({
97
+ fromObject: Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: 'refresh_token', refresh_token }), scope && { scope } || {})
98
+ }), {
99
+ headers: HEADER_APPLICATION
100
+ }).pipe(catchError(() => {
101
+ this.token = {};
102
+ return of(this.token);
103
+ }), map(token => {
104
+ this.token = Object.assign(Object.assign({}, this.token), token);
105
+ return this.token;
106
+ })) || of(token);
107
+ }
108
+ }
109
+ _TokenService_token$ = new WeakMap();
110
+ TokenService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: TokenService, deps: [{ token: OAuthConfig }, { token: i2.HttpClient }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
111
+ TokenService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: TokenService });
112
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: TokenService, decorators: [{
113
+ type: Injectable
114
+ }], ctorParameters: function () { return [{ type: OAuthConfig }, { type: i2.HttpClient }, { type: i0.NgZone }]; } });
115
+
34
116
  const arrToString = (buf) => buf.reduce((s, b) => s + String.fromCharCode(b), '');
35
117
  const base64url = (str) => btoa(str)
36
118
  .replace(/\+/g, '-')
@@ -44,7 +126,6 @@ const pkce = (value) => __awaiter(void 0, void 0, void 0, function* () {
44
126
  const buff = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));
45
127
  return base64url(arrToString(new Uint8Array(buff)));
46
128
  });
47
- const REQUEST_HEADER = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });
48
129
  const parseOauthUri = (hash) => {
49
130
  const regex = /([^&=]+)=([^&]*)/g;
50
131
  const params = {};
@@ -53,126 +134,86 @@ const parseOauthUri = (hash) => {
53
134
  while ((m = regex.exec(hash)) !== null) {
54
135
  params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
55
136
  }
56
- if (Object.keys(params).length) {
57
- return params;
58
- }
59
- return null;
137
+ return Object.keys(params).length && params || {};
60
138
  };
61
139
  const jwt = (token) => JSON.parse(atob(token.split('.')[1]));
62
140
  class OAuthService {
63
- constructor(http, zone, authConfig, location, locationService) {
64
- this.http = http;
65
- this.zone = zone;
141
+ constructor(authConfig, tokenService, http, location, locationService) {
66
142
  this.authConfig = authConfig;
143
+ this.tokenService = tokenService;
144
+ this.http = http;
67
145
  this.location = location;
68
146
  this.locationService = locationService;
69
- this._token = null;
70
- this._status = OAuthStatus.NOT_AUTHORIZED;
71
147
  this.state$ = new ReplaySubject(1);
72
- this.status$ = new ReplaySubject(1);
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;
94
- }
95
- /**
96
- * Init. Will check the url implicit or authorization flow or existing saved token.
97
- * @protected
98
- */
99
- init() {
100
- const { hash, search, origin, pathname } = this.location;
101
- const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
102
- const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search);
103
- const { storageKey } = this.authConfig;
104
- const savedToken = storageKey && this.authConfig.storage && this.authConfig.storage[storageKey] &&
105
- JSON.parse(this.authConfig.storage[storageKey]);
106
- this.config$.subscribe(config => {
148
+ this.config$ = of(this.config).pipe(filter(Boolean), filter(config => !!(config === null || config === void 0 ? void 0 : 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 = 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: config.scope || 'openid' })), map(() => this.config))), shareReplay(1));
149
+ this.token$ = this.config$.pipe(tap(config => {
150
+ const { hash, search, origin, pathname } = this.location;
151
+ const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
152
+ const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search);
107
153
  if (isImplicitRedirect) {
108
- const parameters = parseOauthUri(hash.substr(1));
109
- this.token = parameters;
110
- this.status = this.checkResponse(savedToken, parameters) && OAuthStatus.AUTHORIZED || OAuthStatus.DENIED;
154
+ const parameters = parseOauthUri(hash.substring(1));
155
+ this.token = Object.assign(Object.assign({}, parameters), { type: OAuthType.IMPLICIT });
156
+ this.checkResponse(this.token, parameters);
111
157
  }
112
158
  else if (isAuthCodeRedirect) {
113
- const parameters = parseOauthUri(search.substr(1));
114
- if (!this.checkResponse(savedToken, parameters)) {
159
+ const parameters = parseOauthUri(search.substring(1));
160
+ if (!this.checkResponse(this.token, parameters)) {
115
161
  this.token = parameters;
116
- this.status = OAuthStatus.DENIED;
117
162
  }
118
163
  else {
119
164
  const newParametersString = this.getCleanedUnSearchParameters();
120
165
  const { clientId, clientSecret, tokenPath, scope } = config;
121
- const codeVerifier = savedToken && savedToken.codeVerifier;
166
+ const { codeVerifier } = this.token || {}; //should be set by autorizationUrl construction
122
167
  this.http.post(tokenPath, new HttpParams({
123
168
  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;
126
- this.status = OAuthStatus.DENIED;
127
- this.locationService.replaceState(`${pathname}${newParametersString}`);
128
- return EMPTY;
129
- })).subscribe(token => {
130
- this.token = token;
131
- this.status = OAuthStatus.AUTHORIZED;
169
+ }), { headers: HEADER_APPLICATION }).pipe().subscribe(token => {
170
+ this.token = Object.assign(Object.assign({}, token), { type: OAuthType.AUTHORIZATION_CODE });
132
171
  this.locationService.replaceState(`${pathname}${newParametersString}`);
133
172
  });
134
173
  }
135
174
  }
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
141
- this.refreshToken();
142
- }
143
- else {
144
- this.status = OAuthStatus.AUTHORIZED;
145
- }
146
- }
147
- else {
148
- this.status = error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED;
149
- }
150
- }
151
- else {
152
- this.status = OAuthStatus.NOT_AUTHORIZED;
153
- }
154
- });
175
+ }), switchMap$1(() => this.tokenService.token$), shareReplay(1));
176
+ this.status$ = this.token$.pipe(map(token => token.access_token && OAuthStatus.AUTHORIZED || token.error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED), shareReplay(1));
177
+ this.userInfo$ = this.status$.pipe(filter(s => s === OAuthStatus.AUTHORIZED), map(() => {
178
+ const { config } = this.authConfig;
179
+ return config.userPath;
180
+ }), filter(Boolean), switchMap$1(path => this.http.get(path)), shareReplay(1));
181
+ this.type$ = this.tokenService.type$;
182
+ this.ignorePaths = this.authConfig.ignorePaths || [];
183
+ }
184
+ get token() {
185
+ return this.tokenService.token;
186
+ }
187
+ set token(token) {
188
+ this.tokenService.token = token;
189
+ }
190
+ get config() {
191
+ return this.authConfig.config;
192
+ }
193
+ set config(config) {
194
+ if (config) {
195
+ this.authConfig.config = Object.assign(Object.assign({}, this.authConfig.config), config);
196
+ }
155
197
  }
156
198
  login(parameters) {
157
199
  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);
200
+ if (!!parameters && parameters.password) {
201
+ yield this.resourceLogin(parameters);
163
202
  }
164
- else if (this.isImplicitType(parameters)) {
165
- yield this.implicitLogin(parameters);
203
+ else if (!!parameters
204
+ && parameters.redirectUri
205
+ && (parameters.responseType === OAuthType.IMPLICIT
206
+ || parameters.responseType === OAuthType.AUTHORIZATION_CODE)) {
207
+ yield this.toAuthorizationUrl(parameters);
166
208
  }
167
- else if (this.isClientCredentialType()) {
168
- this.clientCredentialLogin();
209
+ else {
210
+ yield this.clientCredentialLogin();
169
211
  }
170
212
  });
171
213
  }
172
214
  logout(useLogoutUrl) {
173
215
  this.revoke();
174
- this.token = null;
175
- this.status = OAuthStatus.NOT_AUTHORIZED;
216
+ this.token = {};
176
217
  const { logoutPath, logoutRedirectUri } = this.authConfig.config;
177
218
  if (useLogoutUrl && logoutPath) {
178
219
  const { origin, pathname } = this.location;
@@ -183,7 +224,7 @@ class OAuthService {
183
224
  revoke() {
184
225
  const { revokePath, clientId, clientSecret } = this.authConfig.config;
185
226
  if (revokePath) {
186
- const { access_token, refresh_token } = this.token;
227
+ const { access_token, refresh_token } = this.token || {};
187
228
  const toRevoke = [];
188
229
  if (access_token) {
189
230
  toRevoke.push(Object.assign(Object.assign(Object.assign({}, clientId && { client_id: clientId } || {}), clientSecret && { client_secret: clientSecret } || {}), { token: access_token, token_type_hint: 'access_token' }));
@@ -192,91 +233,44 @@ class OAuthService {
192
233
  toRevoke.push(Object.assign(Object.assign(Object.assign({}, clientId && { client_id: clientId } || {}), clientSecret && { client_secret: clientSecret } || {}), { token: refresh_token, token_type_hint: 'refresh_token' }));
193
234
  }
194
235
  from(toRevoke).pipe(concatMap(o => of(o).pipe(delay(300))), // space request to avoid cancellation
195
- switchMap(o => this.http.post(revokePath, new HttpParams({ fromObject: o })))).subscribe(noop);
196
- }
197
- }
198
- get status() {
199
- return this._status;
200
- }
201
- set status(status) {
202
- this._status = status;
203
- this.status$.next(status);
204
- }
205
- set(type, config) {
206
- this.authConfig.type = type;
207
- if (config) {
208
- this.authConfig.config = Object.assign(Object.assign({}, this.authConfig.config), config);
236
+ switchMap$1(o => this.http.post(revokePath, new HttpParams({ fromObject: o })))).subscribe(noop);
209
237
  }
210
238
  }
211
- get type() {
212
- return this.authConfig.type;
213
- }
214
- get ignorePaths() {
215
- return this.authConfig.ignorePaths || [];
239
+ clientCredentialLogin() {
240
+ const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
241
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
242
+ fromObject: Object.assign({ client_id: clientId, client_secret: clientSecret, grant_type: OAuthType.CLIENT_CREDENTIAL }, scope ? { scope } : {})
243
+ }), { headers: HEADER_APPLICATION }).pipe(catchError((err) => {
244
+ this.token = err;
245
+ return throwError(() => err);
246
+ }), tap(params => {
247
+ this.token = Object.assign(Object.assign({}, params), { type: OAuthType.CLIENT_CREDENTIAL });
248
+ })));
216
249
  }
217
250
  resourceLogin(parameters) {
218
251
  const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
219
252
  const { username, password } = parameters;
220
- this.http.post(tokenPath, new HttpParams({
253
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
221
254
  fromObject: Object.assign(Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: OAuthType.RESOURCE }), scope && { scope } || {}), { username,
222
255
  password })
223
- }), { headers: REQUEST_HEADER }).pipe(catchError(err => {
256
+ }), { headers: HEADER_APPLICATION }).pipe(catchError(err => {
224
257
  this.token = err;
225
- this.status = OAuthStatus.DENIED;
226
- return EMPTY;
227
- })).subscribe(params => {
228
- this.token = params;
229
- this.status = OAuthStatus.AUTHORIZED;
230
- });
231
- }
232
- authorizationCodeLogin(parameters) {
233
- return __awaiter(this, void 0, void 0, function* () {
234
- const authUrl = yield this.toAuthorizationUrl(parameters, OAuthType.AUTHORIZATION_CODE);
235
- this.location.replace(authUrl);
236
- });
258
+ return throwError(() => err);
259
+ }), tap(params => {
260
+ this.token = Object.assign(Object.assign({}, params), { type: OAuthType.RESOURCE });
261
+ })));
237
262
  }
238
- implicitLogin(parameters) {
239
- return __awaiter(this, void 0, void 0, function* () {
240
- const authUrl = yield this.toAuthorizationUrl(parameters, OAuthType.IMPLICIT);
241
- this.location.replace(authUrl);
242
- });
243
- }
244
- clientCredentialLogin() {
245
- const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
246
- this.http.post(tokenPath, new HttpParams({
247
- fromObject: Object.assign({ client_id: clientId, client_secret: clientSecret, grant_type: OAuthType.CLIENT_CREDENTIAL }, scope ? { scope } : {})
248
- }), { headers: REQUEST_HEADER }).pipe(catchError((err) => {
249
- this.token = err;
250
- this.status = OAuthStatus.DENIED;
251
- return EMPTY;
252
- })).subscribe(params => {
253
- this.token = params;
254
- this.status = OAuthStatus.AUTHORIZED;
255
- });
256
- }
257
- isClientCredentialType() {
258
- return this.authConfig.type === OAuthType.CLIENT_CREDENTIAL;
259
- }
260
- isResourceType(parameters) {
261
- return this.authConfig.type === OAuthType.RESOURCE && !!(parameters === null || parameters === void 0 ? void 0 : parameters.password);
262
- }
263
- isImplicitType(parameters) {
264
- return this.authConfig.type === OAuthType.IMPLICIT && !!(parameters === null || parameters === void 0 ? void 0 : parameters.redirectUri);
265
- }
266
- isAuthorizationCodeType(parameters) {
267
- return this.authConfig.type === OAuthType.AUTHORIZATION_CODE && !!(parameters === null || parameters === void 0 ? void 0 : parameters.redirectUri);
268
- }
269
- toAuthorizationUrl(parameters, responseType) {
263
+ toAuthorizationUrl(parameters) {
270
264
  return __awaiter(this, void 0, void 0, function* () {
271
265
  const { config } = this.authConfig;
272
266
  let authorizationUrl = `${config.authorizePath}`;
273
267
  authorizationUrl += config.authorizePath.includes('?') && '&' || '?';
274
268
  authorizationUrl += `client_id=${config.clientId}`;
275
269
  authorizationUrl += `&redirect_uri=${encodeURIComponent(parameters.redirectUri)}`;
276
- authorizationUrl += `&response_type=${responseType}`;
270
+ authorizationUrl += `&response_type=${parameters.responseType}`;
277
271
  authorizationUrl += `&scope=${encodeURIComponent(config.scope || '')}`;
278
272
  authorizationUrl += `&state=${encodeURIComponent(parameters.state || '')}`;
279
- return `${authorizationUrl}${this.generateNonce(config)}${yield this.generateCodeChallenge(config)}`;
273
+ return this.location.replace(`${authorizationUrl}${this.generateNonce(config)}${yield this.generateCodeChallenge(config)}`);
280
274
  });
281
275
  }
282
276
  generateCodeChallenge(config) {
@@ -309,52 +303,11 @@ class OAuthService {
309
303
  }
310
304
  return parameters['access_token'] || parameters['code'];
311
305
  }
312
- set token(token) {
313
- this._token = token;
314
- const { storageKey } = this.authConfig;
315
- if (token) {
316
- // @ts-ignore
317
- this.authConfig.storage[storageKey] = JSON.stringify(this.token);
318
- clearTimeout(this.timer);
319
- if (this.token && this.token.expires_in) {
320
- this.zone.runOutsideAngular(() => {
321
- var _a;
322
- this.timer = setTimeout(() => {
323
- this.zone.run(() => {
324
- this.refreshToken();
325
- });
326
- }, Number((_a = this.token) === null || _a === void 0 ? void 0 : _a.expires_in) * 1000);
327
- });
328
- }
329
- }
330
- else {
331
- // @ts-ignore
332
- delete this.authConfig.storage[storageKey];
333
- }
334
- }
335
- get token() {
336
- return this._token;
337
- }
338
- refreshToken() {
339
- const { tokenPath, clientId, clientSecret, scope } = this.authConfig.config;
340
- const { refresh_token } = this.token;
341
- if (tokenPath && refresh_token) {
342
- this.http.post(tokenPath, new HttpParams({
343
- fromObject: Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: 'refresh_token', refresh_token }), scope && { scope } || {})
344
- }), { headers: REQUEST_HEADER }).pipe(catchError(() => {
345
- this.logout();
346
- return EMPTY;
347
- })).subscribe(params => {
348
- this.token = Object.assign(Object.assign({}, this.token), params);
349
- this.status = OAuthStatus.AUTHORIZED;
350
- });
351
- }
352
- }
353
306
  getCleanedUnSearchParameters() {
354
307
  const { search } = this.location;
355
- let searchString = search.substr(1);
308
+ let searchString = search && search.substring(1) || '';
356
309
  const hashKeys = ['code', 'state', 'error', 'error_description', 'session_state', 'scope', 'authuser', 'prompt'];
357
- hashKeys.forEach((hashKey) => {
310
+ hashKeys.forEach(hashKey => {
358
311
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
359
312
  searchString = searchString.replace(re, '');
360
313
  });
@@ -362,67 +315,59 @@ class OAuthService {
362
315
  }
363
316
  cleanLocationHash() {
364
317
  const { hash } = this.location;
365
- let curHash = hash.substr(1);
318
+ let curHash = hash && hash.substring(1) || '';
366
319
  const hashKeys = ['access_token', 'token_type', 'expires_in', 'scope', 'state', 'error', 'error_description', 'session_state', 'nonce'];
367
- hashKeys.forEach((hashKey) => {
320
+ hashKeys.forEach(hashKey => {
368
321
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
369
322
  curHash = curHash.replace(re, '');
370
323
  });
371
324
  this.location.hash = curHash;
372
325
  }
373
326
  emitState(parameters) {
374
- const { state } = parameters;
375
- if (state) {
376
- this.state$.next(state);
377
- }
327
+ const { state } = parameters || {};
328
+ state && this.state$.next(state);
378
329
  }
379
330
  }
380
- OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", 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: "14.0.0", ngImport: i0, type: OAuthService });
382
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthService, decorators: [{
331
+ OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthService, deps: [{ token: OAuthConfig }, { token: TokenService }, { token: i2.HttpClient }, { token: LOCATION }, { token: i2$1.Location }], target: i0.ɵɵFactoryTarget.Injectable });
332
+ OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthService });
333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthService, decorators: [{
383
334
  type: Injectable
384
335
  }], ctorParameters: function () {
385
- return [{ type: i1.HttpClient }, { type: i0.NgZone }, { type: undefined, decorators: [{
386
- type: Inject,
387
- args: [OAUTH_CONFIG]
388
- }] }, { type: Location, decorators: [{
336
+ return [{ type: OAuthConfig }, { type: TokenService }, { type: i2.HttpClient }, { type: Location, decorators: [{
389
337
  type: Inject,
390
338
  args: [LOCATION]
391
- }] }, { type: i2.Location }];
339
+ }] }, { type: i2$1.Location }];
392
340
  } });
393
341
 
394
342
  class OAuthInterceptor {
395
- constructor(oauthService) {
396
- this.oauthService = oauthService;
343
+ constructor(tokenService, authConfig) {
344
+ this.tokenService = tokenService;
345
+ this.authConfig = authConfig;
397
346
  }
398
347
  intercept(req, next) {
399
- if (this.oauthService) {
400
- if (!this.isPathExcepted(req)) {
401
- const { token } = this.oauthService;
402
- if (token && token.access_token) {
403
- req = req.clone({
404
- setHeaders: {
405
- Authorization: `${token.token_type} ${token.access_token}`
406
- }
407
- });
408
- }
348
+ return this.tokenService.token$.pipe(take(1), map(token => {
349
+ if ((token === null || token === void 0 ? void 0 : token.access_token) && !this.isPathExcepted(req)) {
350
+ req = req.clone({
351
+ setHeaders: {
352
+ Authorization: `${token.token_type} ${token.access_token}`
353
+ }
354
+ });
409
355
  }
410
- return next.handle(req).pipe(catchError((err) => {
411
- if (err.status === 401 && !this.isPathExcepted(req)) {
412
- this.oauthService.token = null;
413
- this.oauthService.status = OAuthStatus.DENIED;
414
- }
415
- return throwError(err);
416
- }));
417
- }
418
- else {
419
- return next.handle(req);
420
- }
356
+ return req;
357
+ }), switchMap(req => next.handle(req)), catchError((err) => {
358
+ if (err.status === 401 && !this.isPathExcepted(req)) {
359
+ this.tokenService.token = {
360
+ error: `${err.status}`,
361
+ error_description: err.message
362
+ };
363
+ }
364
+ return throwError(() => err);
365
+ }));
421
366
  }
422
367
  isPathExcepted(req) {
423
- const { ignorePaths } = this.oauthService;
368
+ const { ignorePaths } = this.authConfig || {};
424
369
  if (ignorePaths) {
425
- for (const ignorePath of this.oauthService.ignorePaths) {
370
+ for (const ignorePath of ignorePaths) {
426
371
  try {
427
372
  if (req.url.match(ignorePath)) {
428
373
  return true;
@@ -435,39 +380,40 @@ class OAuthInterceptor {
435
380
  return false;
436
381
  }
437
382
  }
438
- OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthInterceptor, deps: [{ token: OAuthService }], target: i0.ɵɵFactoryTarget.Injectable });
439
- OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthInterceptor });
440
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthInterceptor, decorators: [{
383
+ OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthInterceptor, deps: [{ token: TokenService }, { token: OAuthConfig }], target: i0.ɵɵFactoryTarget.Injectable });
384
+ OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthInterceptor });
385
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthInterceptor, decorators: [{
441
386
  type: Injectable
442
- }], ctorParameters: function () { return [{ type: OAuthService }]; } });
387
+ }], ctorParameters: function () { return [{ type: TokenService }, { type: OAuthConfig }]; } });
443
388
 
389
+ var _OAuthLoginComponent_subscription, _OAuthLoginComponent_redirectUri, _OAuthLoginComponent_i18n;
444
390
  class OAuthLoginComponent {
445
391
  constructor(oauthService, locationService, location) {
446
392
  this.oauthService = oauthService;
447
393
  this.locationService = locationService;
448
394
  this.location = location;
449
- this.subscription = new Subscription();
450
- this._i18n = {
395
+ _OAuthLoginComponent_subscription.set(this, new Subscription());
396
+ _OAuthLoginComponent_redirectUri.set(this, void 0);
397
+ _OAuthLoginComponent_i18n.set(this, {
451
398
  username: 'Username',
452
399
  password: 'Password',
453
400
  submit: 'Sign in',
454
401
  notAuthorized: 'Sign in',
455
402
  authorized: 'Welcome',
456
403
  denied: 'Access Denied. Try again!'
457
- };
404
+ });
458
405
  this.useLogoutUrl = false;
459
406
  this.state = '';
460
- this.stateChange = new EventEmitter();
407
+ this.stateChange = this.oauthService.state$.asObservable();
461
408
  this.username = '';
462
409
  this.password = '';
463
410
  this.OAuthStatus = OAuthStatus;
464
411
  this.OAuthType = OAuthType;
465
412
  this.collapse = false;
466
- this.type = this.oauthService.type;
467
- this.state$ = this.oauthService.state$.pipe(tap(s => this.stateChange.emit(s)));
413
+ this.type = OAuthType.RESOURCE;
468
414
  this.status$ = this.oauthService.status$.pipe(tap(s => {
469
415
  if (s === OAuthStatus.AUTHORIZED && this.profileName$) {
470
- this.subscription.add(this.profileName$.pipe(take(1)).subscribe(n => this.profileName = n));
416
+ __classPrivateFieldGet(this, _OAuthLoginComponent_subscription, "f").add(this.profileName$.pipe(take(1)).subscribe(n => this.profileName = n));
471
417
  }
472
418
  else {
473
419
  const { token } = this.oauthService;
@@ -479,30 +425,28 @@ class OAuthLoginComponent {
479
425
  this.logoutFunction = () => this.logout();
480
426
  }
481
427
  get i18n() {
482
- return this._i18n;
428
+ return __classPrivateFieldGet(this, _OAuthLoginComponent_i18n, "f");
483
429
  }
484
430
  set i18n(i18n) {
485
- this._i18n = Object.assign(Object.assign({}, this._i18n), i18n);
431
+ __classPrivateFieldSet(this, _OAuthLoginComponent_i18n, Object.assign(Object.assign({}, __classPrivateFieldGet(this, _OAuthLoginComponent_i18n, "f")), i18n), "f");
432
+ }
433
+ get redirectUri() {
434
+ return __classPrivateFieldGet(this, _OAuthLoginComponent_redirectUri, "f") || `${this.location.origin}${this.locationService.path(true) || '/'}`;
486
435
  }
487
436
  set redirectUri(redirectUri) {
488
437
  if (redirectUri) {
489
- this._redirectUri = redirectUri;
438
+ __classPrivateFieldSet(this, _OAuthLoginComponent_redirectUri, redirectUri, "f");
490
439
  }
491
440
  }
492
- get redirectUri() {
493
- return this._redirectUri || `${this.location.origin}${this.locationService.path(true) || '/'}`;
494
- }
495
441
  ngOnDestroy() {
496
- this.subscription.unsubscribe();
442
+ __classPrivateFieldGet(this, _OAuthLoginComponent_subscription, "f").unsubscribe();
497
443
  }
498
444
  logout() {
499
445
  this.oauthService.logout(this.useLogoutUrl);
500
446
  }
501
447
  login(parameters) {
502
- return __awaiter(this, void 0, void 0, function* () {
503
- yield this.oauthService.login(parameters);
504
- this.collapse = false;
505
- });
448
+ this.collapse = false;
449
+ return this.oauthService.login(parameters);
506
450
  }
507
451
  toggleCollapse() {
508
452
  this.collapse = !this.collapse;
@@ -510,14 +454,18 @@ class OAuthLoginComponent {
510
454
  keyboardEvent() {
511
455
  this.collapse = false;
512
456
  }
457
+ get responseType() {
458
+ return this.type; //avoid complains
459
+ }
513
460
  }
514
- 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 });
515
- 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 });
516
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthLoginComponent, decorators: [{
461
+ _OAuthLoginComponent_subscription = new WeakMap(), _OAuthLoginComponent_redirectUri = new WeakMap(), _OAuthLoginComponent_i18n = new WeakMap();
462
+ OAuthLoginComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthLoginComponent, deps: [{ token: OAuthService }, { token: i2$1.Location }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Component });
463
+ OAuthLoginComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.5", type: OAuthLoginComponent, selector: "oauth-login", inputs: { i18n: "i18n", redirectUri: "redirectUri", useLogoutUrl: "useLogoutUrl", state: "state", profileName$: "profileName$", type: "type" }, 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\" #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({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 });
464
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthLoginComponent, decorators: [{
517
465
  type: Component,
518
- 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"] }]
466
+ 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\" #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({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"] }]
519
467
  }], ctorParameters: function () {
520
- return [{ type: OAuthService }, { type: i2.Location }, { type: Location, decorators: [{
468
+ return [{ type: OAuthService }, { type: i2$1.Location }, { type: Location, decorators: [{
521
469
  type: Inject,
522
470
  args: [LOCATION]
523
471
  }] }];
@@ -536,6 +484,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImpor
536
484
  }], loginTemplate: [{
537
485
  type: ContentChild,
538
486
  args: ['login', { static: false }]
487
+ }], type: [{
488
+ type: Input
539
489
  }], keyboardEvent: [{
540
490
  type: HostListener,
541
491
  args: ['window:keydown.escape']
@@ -548,10 +498,10 @@ const mockLocation = (serverHost, serverPath) => {
548
498
  href, origin, protocol, host, hostname, port, pathname, search, hash,
549
499
  reload() {
550
500
  },
551
- assign(u) {
501
+ assign(_) {
552
502
  },
553
503
  ancestorOrigins: {},
554
- replace(u) {
504
+ replace(_) {
555
505
  }
556
506
  };
557
507
  };
@@ -601,42 +551,30 @@ const defaultConfig = (storage) => {
601
551
  };
602
552
  };
603
553
  class OAuthModule {
604
- static forRoot(config) {
554
+ static forRoot(config = {}) {
605
555
  return {
606
556
  ngModule: OAuthModule,
607
557
  providers: [
608
558
  LocationService,
609
559
  StorageService,
610
- OAuthService,
560
+ provideOAuthConfigFactory((storage) => (Object.assign(Object.assign({}, defaultConfig(storage)), config)), [STORAGE]),
561
+ TokenService,
611
562
  OAuthInterceptorService,
612
- {
613
- provide: OAUTH_CONFIG,
614
- useFactory(storage) {
615
- return Object.assign(Object.assign({}, defaultConfig(storage)), config);
616
- },
617
- deps: [
618
- STORAGE
619
- ]
620
- }
563
+ OAuthService,
621
564
  ]
622
565
  };
623
566
  }
624
567
  }
625
- OAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
626
- OAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, declarations: [OAuthLoginComponent], imports: [CommonModule,
568
+ OAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
569
+ OAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.0.5", ngImport: i0, type: OAuthModule, declarations: [OAuthLoginComponent], imports: [CommonModule,
627
570
  FormsModule,
628
571
  HttpClientModule,
629
572
  RouterModule], exports: [OAuthLoginComponent] });
630
- OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, providers: [
631
- LocationService,
632
- StorageService,
633
- OAuthService,
634
- OAuthInterceptorService,
635
- ], imports: [CommonModule,
573
+ OAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthModule, imports: [CommonModule,
636
574
  FormsModule,
637
575
  HttpClientModule,
638
576
  RouterModule] });
639
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImport: i0, type: OAuthModule, decorators: [{
577
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthModule, decorators: [{
640
578
  type: NgModule,
641
579
  args: [{
642
580
  imports: [
@@ -646,13 +584,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImpor
646
584
  RouterModule,
647
585
  ],
648
586
  declarations: [OAuthLoginComponent],
649
- exports: [OAuthLoginComponent],
650
- providers: [
651
- LocationService,
652
- StorageService,
653
- OAuthService,
654
- OAuthInterceptorService,
655
- ]
587
+ exports: [OAuthLoginComponent]
656
588
  }]
657
589
  }] });
658
590
 
@@ -664,5 +596,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.0", ngImpor
664
596
  * Generated bundle index. Do not edit.
665
597
  */
666
598
 
667
- export { LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE };
599
+ export { HEADER_APPLICATION, LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthConfig, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE, provideOAuthConfig, provideOAuthConfigFactory };
668
600
  //# sourceMappingURL=ngx-oauth.mjs.map