ngx-oauth 3.0.2 → 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, inject, 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, firstValueFrom, 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,7 @@ 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' });
20
21
  class OAuthConfig {
21
22
  }
22
23
  OAuthConfig.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthConfig, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
@@ -53,6 +54,65 @@ var OAuthStatus;
53
54
  OAuthStatus["DENIED"] = "DENIED";
54
55
  })(OAuthStatus || (OAuthStatus = {}));
55
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
+
56
116
  const arrToString = (buf) => buf.reduce((s, b) => s + String.fromCharCode(b), '');
57
117
  const base64url = (str) => btoa(str)
58
118
  .replace(/\+/g, '-')
@@ -66,7 +126,6 @@ const pkce = (value) => __awaiter(void 0, void 0, void 0, function* () {
66
126
  const buff = yield crypto.subtle.digest('SHA-256', new TextEncoder().encode(value));
67
127
  return base64url(arrToString(new Uint8Array(buff)));
68
128
  });
69
- const REQUEST_HEADER = new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' });
70
129
  const parseOauthUri = (hash) => {
71
130
  const regex = /([^&=]+)=([^&]*)/g;
72
131
  const params = {};
@@ -75,126 +134,86 @@ const parseOauthUri = (hash) => {
75
134
  while ((m = regex.exec(hash)) !== null) {
76
135
  params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
77
136
  }
78
- if (Object.keys(params).length) {
79
- return params;
80
- }
81
- return null;
137
+ return Object.keys(params).length && params || {};
82
138
  };
83
139
  const jwt = (token) => JSON.parse(atob(token.split('.')[1]));
84
140
  class OAuthService {
85
- constructor(http, zone, authConfig, location, locationService) {
86
- this.http = http;
87
- this.zone = zone;
141
+ constructor(authConfig, tokenService, http, location, locationService) {
88
142
  this.authConfig = authConfig;
143
+ this.tokenService = tokenService;
144
+ this.http = http;
89
145
  this.location = location;
90
146
  this.locationService = locationService;
91
- this._token = null;
92
- this._status = OAuthStatus.NOT_AUTHORIZED;
93
147
  this.state$ = new ReplaySubject(1);
94
- this.status$ = new ReplaySubject(1);
95
- this.userInfo$ = this.status$.pipe(filter(s => s === OAuthStatus.AUTHORIZED), map(() => {
96
- const { config } = this.authConfig;
97
- return config.userPath;
98
- }), filter(p => !!p), switchMap(path => this.http.get(path)), shareReplay());
99
- setTimeout(() => this.init()); // decouple for http interceptor
100
- }
101
- /**
102
- * Get the oauth config for initialize. If OpenId with issuerPath is configured then configure from server openid configuration.
103
- * @protected
104
- */
105
- get config$() {
106
- let { config } = this.authConfig;
107
- if (config && config.clientId) {
108
- const { issuerPath, scope } = config;
109
- if (issuerPath) {
110
- return this.http.get(`${issuerPath}/.well-known/openid-configuration`).pipe(tap(v => this.type && 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));
111
- }
112
- return of(config);
113
- }
114
- console.warn('clientId is missing in oauth config');
115
- return EMPTY;
116
- }
117
- /**
118
- * Init. Will check the url implicit or authorization flow or existing saved token.
119
- * @protected
120
- */
121
- init() {
122
- const { hash, search, origin, pathname } = this.location;
123
- const isImplicitRedirect = hash && /(access_token=)|(error=)/.test(hash);
124
- const isAuthCodeRedirect = search && /(code=)|(error=)/.test(search);
125
- const { storageKey } = this.authConfig;
126
- const savedToken = storageKey && this.authConfig.storage && this.authConfig.storage[storageKey] &&
127
- JSON.parse(this.authConfig.storage[storageKey]);
128
- 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);
129
153
  if (isImplicitRedirect) {
130
- const parameters = parseOauthUri(hash.substr(1));
131
- this.token = parameters;
132
- 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);
133
157
  }
134
158
  else if (isAuthCodeRedirect) {
135
- const parameters = parseOauthUri(search.substr(1));
136
- if (!this.checkResponse(savedToken, parameters)) {
159
+ const parameters = parseOauthUri(search.substring(1));
160
+ if (!this.checkResponse(this.token, parameters)) {
137
161
  this.token = parameters;
138
- this.status = OAuthStatus.DENIED;
139
162
  }
140
163
  else {
141
164
  const newParametersString = this.getCleanedUnSearchParameters();
142
165
  const { clientId, clientSecret, tokenPath, scope } = config;
143
- const codeVerifier = savedToken && savedToken.codeVerifier;
166
+ const { codeVerifier } = this.token || {}; //should be set by autorizationUrl construction
144
167
  this.http.post(tokenPath, new HttpParams({
145
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 } || {})
146
- }), { headers: REQUEST_HEADER }).pipe(catchError((err) => {
147
- this.token = err;
148
- this.status = OAuthStatus.DENIED;
149
- this.locationService.replaceState(`${pathname}${newParametersString}`);
150
- return EMPTY;
151
- })).subscribe(token => {
152
- this.token = token;
153
- this.status = OAuthStatus.AUTHORIZED;
169
+ }), { headers: HEADER_APPLICATION }).pipe().subscribe(token => {
170
+ this.token = Object.assign(Object.assign({}, token), { type: OAuthType.AUTHORIZATION_CODE });
154
171
  this.locationService.replaceState(`${pathname}${newParametersString}`);
155
172
  });
156
173
  }
157
174
  }
158
- else if (savedToken) {
159
- this._token = savedToken;
160
- const { access_token, refresh_token, error } = savedToken;
161
- if (access_token) {
162
- if (refresh_token) { // force refresh since might be a manual page refresh
163
- this.refreshToken();
164
- }
165
- else {
166
- this.status = OAuthStatus.AUTHORIZED;
167
- }
168
- }
169
- else {
170
- this.status = error && OAuthStatus.DENIED || OAuthStatus.NOT_AUTHORIZED;
171
- }
172
- }
173
- else {
174
- this.status = OAuthStatus.NOT_AUTHORIZED;
175
- }
176
- });
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
+ }
177
197
  }
178
198
  login(parameters) {
179
199
  return __awaiter(this, void 0, void 0, function* () {
180
- if (this.isResourceType(parameters)) {
200
+ if (!!parameters && parameters.password) {
181
201
  yield this.resourceLogin(parameters);
182
202
  }
183
- else if (this.isAuthorizationCodeType(parameters)) {
184
- yield this.authorizationCodeLogin(parameters);
185
- }
186
- else if (this.isImplicitType(parameters)) {
187
- 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);
188
208
  }
189
- else if (this.isClientCredentialType()) {
209
+ else {
190
210
  yield this.clientCredentialLogin();
191
211
  }
192
212
  });
193
213
  }
194
214
  logout(useLogoutUrl) {
195
215
  this.revoke();
196
- this.token = null;
197
- this.status = OAuthStatus.NOT_AUTHORIZED;
216
+ this.token = {};
198
217
  const { logoutPath, logoutRedirectUri } = this.authConfig.config;
199
218
  if (useLogoutUrl && logoutPath) {
200
219
  const { origin, pathname } = this.location;
@@ -205,7 +224,7 @@ class OAuthService {
205
224
  revoke() {
206
225
  const { revokePath, clientId, clientSecret } = this.authConfig.config;
207
226
  if (revokePath) {
208
- const { access_token, refresh_token } = this.token;
227
+ const { access_token, refresh_token } = this.token || {};
209
228
  const toRevoke = [];
210
229
  if (access_token) {
211
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' }));
@@ -214,95 +233,44 @@ class OAuthService {
214
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' }));
215
234
  }
216
235
  from(toRevoke).pipe(concatMap(o => of(o).pipe(delay(300))), // space request to avoid cancellation
217
- switchMap(o => this.http.post(revokePath, new HttpParams({ fromObject: o })))).subscribe(noop);
218
- }
219
- }
220
- get status() {
221
- return this._status;
222
- }
223
- set status(status) {
224
- this._status = status;
225
- this.status$.next(status);
226
- }
227
- set(type, config) {
228
- this.authConfig.type = type;
229
- if (config) {
230
- 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);
231
237
  }
232
238
  }
233
- get type() {
234
- return this.authConfig.type;
235
- }
236
- get ignorePaths() {
237
- return this.authConfig.ignorePaths || [];
238
- }
239
239
  clientCredentialLogin() {
240
- return __awaiter(this, void 0, void 0, function* () {
241
- const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
242
- yield firstValueFrom(this.http.post(tokenPath, new HttpParams({
243
- fromObject: Object.assign({ client_id: clientId, client_secret: clientSecret, grant_type: OAuthType.CLIENT_CREDENTIAL }, scope ? { scope } : {})
244
- }), { headers: REQUEST_HEADER }).pipe(catchError((err) => {
245
- this.token = err;
246
- this.status = OAuthStatus.DENIED;
247
- return EMPTY;
248
- }), tap(params => {
249
- this.token = params;
250
- this.status = OAuthStatus.AUTHORIZED;
251
- })));
252
- });
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
+ })));
253
249
  }
254
250
  resourceLogin(parameters) {
255
- return __awaiter(this, void 0, void 0, function* () {
256
- const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
257
- const { username, password } = parameters;
258
- yield firstValueFrom(this.http.post(tokenPath, new HttpParams({
259
- fromObject: Object.assign(Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: OAuthType.RESOURCE }), scope && { scope } || {}), { username,
260
- password })
261
- }), { headers: REQUEST_HEADER }).pipe(catchError(err => {
262
- this.token = err;
263
- this.status = OAuthStatus.DENIED;
264
- return EMPTY;
265
- }), tap(params => {
266
- this.token = params;
267
- this.status = OAuthStatus.AUTHORIZED;
268
- })));
269
- });
270
- }
271
- implicitLogin(parameters) {
272
- return __awaiter(this, void 0, void 0, function* () {
273
- const authUrl = yield this.toAuthorizationUrl(parameters, OAuthType.IMPLICIT);
274
- this.location.replace(authUrl);
275
- });
276
- }
277
- authorizationCodeLogin(parameters) {
278
- return __awaiter(this, void 0, void 0, function* () {
279
- const authUrl = yield this.toAuthorizationUrl(parameters, OAuthType.AUTHORIZATION_CODE);
280
- this.location.replace(authUrl);
281
- });
282
- }
283
- isClientCredentialType() {
284
- return this.authConfig.type === OAuthType.CLIENT_CREDENTIAL;
285
- }
286
- isResourceType(parameters) {
287
- return this.authConfig.type === OAuthType.RESOURCE && !!(parameters === null || parameters === void 0 ? void 0 : parameters.password);
288
- }
289
- isImplicitType(parameters) {
290
- return this.authConfig.type === OAuthType.IMPLICIT && !!(parameters === null || parameters === void 0 ? void 0 : parameters.redirectUri);
291
- }
292
- isAuthorizationCodeType(parameters) {
293
- return this.authConfig.type === OAuthType.AUTHORIZATION_CODE && !!(parameters === null || parameters === void 0 ? void 0 : parameters.redirectUri);
294
- }
295
- toAuthorizationUrl(parameters, responseType) {
251
+ const { clientId, clientSecret, tokenPath, scope } = this.authConfig.config;
252
+ const { username, password } = parameters;
253
+ return firstValueFrom(this.http.post(tokenPath, new HttpParams({
254
+ fromObject: Object.assign(Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: OAuthType.RESOURCE }), scope && { scope } || {}), { username,
255
+ password })
256
+ }), { headers: HEADER_APPLICATION }).pipe(catchError(err => {
257
+ this.token = err;
258
+ return throwError(() => err);
259
+ }), tap(params => {
260
+ this.token = Object.assign(Object.assign({}, params), { type: OAuthType.RESOURCE });
261
+ })));
262
+ }
263
+ toAuthorizationUrl(parameters) {
296
264
  return __awaiter(this, void 0, void 0, function* () {
297
265
  const { config } = this.authConfig;
298
266
  let authorizationUrl = `${config.authorizePath}`;
299
267
  authorizationUrl += config.authorizePath.includes('?') && '&' || '?';
300
268
  authorizationUrl += `client_id=${config.clientId}`;
301
269
  authorizationUrl += `&redirect_uri=${encodeURIComponent(parameters.redirectUri)}`;
302
- authorizationUrl += `&response_type=${responseType}`;
270
+ authorizationUrl += `&response_type=${parameters.responseType}`;
303
271
  authorizationUrl += `&scope=${encodeURIComponent(config.scope || '')}`;
304
272
  authorizationUrl += `&state=${encodeURIComponent(parameters.state || '')}`;
305
- return `${authorizationUrl}${this.generateNonce(config)}${yield this.generateCodeChallenge(config)}`;
273
+ return this.location.replace(`${authorizationUrl}${this.generateNonce(config)}${yield this.generateCodeChallenge(config)}`);
306
274
  });
307
275
  }
308
276
  generateCodeChallenge(config) {
@@ -335,52 +303,11 @@ class OAuthService {
335
303
  }
336
304
  return parameters['access_token'] || parameters['code'];
337
305
  }
338
- set token(token) {
339
- this._token = token;
340
- const { storageKey } = this.authConfig;
341
- if (token) {
342
- // @ts-ignore
343
- this.authConfig.storage[storageKey] = JSON.stringify(this.token);
344
- clearTimeout(this.timer);
345
- if (this.token && this.token.expires_in) {
346
- this.zone.runOutsideAngular(() => {
347
- var _a;
348
- this.timer = setTimeout(() => {
349
- this.zone.run(() => {
350
- this.refreshToken();
351
- });
352
- }, Number((_a = this.token) === null || _a === void 0 ? void 0 : _a.expires_in) * 1000);
353
- });
354
- }
355
- }
356
- else {
357
- // @ts-ignore
358
- delete this.authConfig.storage[storageKey];
359
- }
360
- }
361
- get token() {
362
- return this._token;
363
- }
364
- refreshToken() {
365
- const { tokenPath, clientId, clientSecret, scope } = this.authConfig.config;
366
- const { refresh_token } = this.token;
367
- if (tokenPath && refresh_token) {
368
- this.http.post(tokenPath, new HttpParams({
369
- fromObject: Object.assign(Object.assign(Object.assign({ client_id: clientId }, clientSecret && { client_secret: clientSecret } || {}), { grant_type: 'refresh_token', refresh_token }), scope && { scope } || {})
370
- }), { headers: REQUEST_HEADER }).pipe(catchError(() => {
371
- this.logout();
372
- return EMPTY;
373
- })).subscribe(params => {
374
- this.token = Object.assign(Object.assign({}, this.token), params);
375
- this.status = OAuthStatus.AUTHORIZED;
376
- });
377
- }
378
- }
379
306
  getCleanedUnSearchParameters() {
380
307
  const { search } = this.location;
381
- let searchString = search.substr(1);
308
+ let searchString = search && search.substring(1) || '';
382
309
  const hashKeys = ['code', 'state', 'error', 'error_description', 'session_state', 'scope', 'authuser', 'prompt'];
383
- hashKeys.forEach((hashKey) => {
310
+ hashKeys.forEach(hashKey => {
384
311
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
385
312
  searchString = searchString.replace(re, '');
386
313
  });
@@ -388,64 +315,59 @@ class OAuthService {
388
315
  }
389
316
  cleanLocationHash() {
390
317
  const { hash } = this.location;
391
- let curHash = hash.substr(1);
318
+ let curHash = hash && hash.substring(1) || '';
392
319
  const hashKeys = ['access_token', 'token_type', 'expires_in', 'scope', 'state', 'error', 'error_description', 'session_state', 'nonce'];
393
- hashKeys.forEach((hashKey) => {
320
+ hashKeys.forEach(hashKey => {
394
321
  const re = new RegExp('&' + hashKey + '(=[^&]*)?|^' + hashKey + '(=[^&]*)?&?');
395
322
  curHash = curHash.replace(re, '');
396
323
  });
397
324
  this.location.hash = curHash;
398
325
  }
399
326
  emitState(parameters) {
400
- const { state } = parameters;
401
- if (state) {
402
- this.state$.next(state);
403
- }
327
+ const { state } = parameters || {};
328
+ state && this.state$.next(state);
404
329
  }
405
330
  }
406
- OAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthService, deps: [{ token: i1.HttpClient }, { token: i0.NgZone }, { token: OAuthConfig }, { token: LOCATION }, { token: i2.Location }], target: i0.ɵɵFactoryTarget.Injectable });
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 });
407
332
  OAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthService });
408
333
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthService, decorators: [{
409
334
  type: Injectable
410
335
  }], ctorParameters: function () {
411
- return [{ type: i1.HttpClient }, { type: i0.NgZone }, { type: OAuthConfig }, { type: Location, decorators: [{
336
+ return [{ type: OAuthConfig }, { type: TokenService }, { type: i2.HttpClient }, { type: Location, decorators: [{
412
337
  type: Inject,
413
338
  args: [LOCATION]
414
- }] }, { type: i2.Location }];
339
+ }] }, { type: i2$1.Location }];
415
340
  } });
416
341
 
417
342
  class OAuthInterceptor {
418
- constructor(oauthService) {
419
- this.oauthService = oauthService;
343
+ constructor(tokenService, authConfig) {
344
+ this.tokenService = tokenService;
345
+ this.authConfig = authConfig;
420
346
  }
421
347
  intercept(req, next) {
422
- if (this.oauthService) {
423
- if (!this.isPathExcepted(req)) {
424
- const { token } = this.oauthService;
425
- if (token && token.access_token) {
426
- req = req.clone({
427
- setHeaders: {
428
- Authorization: `${token.token_type} ${token.access_token}`
429
- }
430
- });
431
- }
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
+ });
432
355
  }
433
- return next.handle(req).pipe(catchError((err) => {
434
- if (err.status === 401 && !this.isPathExcepted(req)) {
435
- this.oauthService.token = null;
436
- this.oauthService.status = OAuthStatus.DENIED;
437
- }
438
- return throwError(err);
439
- }));
440
- }
441
- else {
442
- return next.handle(req);
443
- }
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
+ }));
444
366
  }
445
367
  isPathExcepted(req) {
446
- const { ignorePaths } = this.oauthService;
368
+ const { ignorePaths } = this.authConfig || {};
447
369
  if (ignorePaths) {
448
- for (const ignorePath of this.oauthService.ignorePaths) {
370
+ for (const ignorePath of ignorePaths) {
449
371
  try {
450
372
  if (req.url.match(ignorePath)) {
451
373
  return true;
@@ -458,39 +380,40 @@ class OAuthInterceptor {
458
380
  return false;
459
381
  }
460
382
  }
461
- OAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthInterceptor, deps: [{ token: OAuthService }], target: i0.ɵɵFactoryTarget.Injectable });
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 });
462
384
  OAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthInterceptor });
463
385
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthInterceptor, decorators: [{
464
386
  type: Injectable
465
- }], ctorParameters: function () { return [{ type: OAuthService }]; } });
387
+ }], ctorParameters: function () { return [{ type: TokenService }, { type: OAuthConfig }]; } });
466
388
 
389
+ var _OAuthLoginComponent_subscription, _OAuthLoginComponent_redirectUri, _OAuthLoginComponent_i18n;
467
390
  class OAuthLoginComponent {
468
391
  constructor(oauthService, locationService, location) {
469
392
  this.oauthService = oauthService;
470
393
  this.locationService = locationService;
471
394
  this.location = location;
472
- this.subscription = new Subscription();
473
- this._i18n = {
395
+ _OAuthLoginComponent_subscription.set(this, new Subscription());
396
+ _OAuthLoginComponent_redirectUri.set(this, void 0);
397
+ _OAuthLoginComponent_i18n.set(this, {
474
398
  username: 'Username',
475
399
  password: 'Password',
476
400
  submit: 'Sign in',
477
401
  notAuthorized: 'Sign in',
478
402
  authorized: 'Welcome',
479
403
  denied: 'Access Denied. Try again!'
480
- };
404
+ });
481
405
  this.useLogoutUrl = false;
482
406
  this.state = '';
483
- this.stateChange = new EventEmitter();
407
+ this.stateChange = this.oauthService.state$.asObservable();
484
408
  this.username = '';
485
409
  this.password = '';
486
410
  this.OAuthStatus = OAuthStatus;
487
411
  this.OAuthType = OAuthType;
488
412
  this.collapse = false;
489
- this.type = this.oauthService.type;
490
- this.state$ = this.oauthService.state$.pipe(tap(s => this.stateChange.emit(s)));
413
+ this.type = OAuthType.RESOURCE;
491
414
  this.status$ = this.oauthService.status$.pipe(tap(s => {
492
415
  if (s === OAuthStatus.AUTHORIZED && this.profileName$) {
493
- 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));
494
417
  }
495
418
  else {
496
419
  const { token } = this.oauthService;
@@ -502,30 +425,28 @@ class OAuthLoginComponent {
502
425
  this.logoutFunction = () => this.logout();
503
426
  }
504
427
  get i18n() {
505
- return this._i18n;
428
+ return __classPrivateFieldGet(this, _OAuthLoginComponent_i18n, "f");
506
429
  }
507
430
  set i18n(i18n) {
508
- 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) || '/'}`;
509
435
  }
510
436
  set redirectUri(redirectUri) {
511
437
  if (redirectUri) {
512
- this._redirectUri = redirectUri;
438
+ __classPrivateFieldSet(this, _OAuthLoginComponent_redirectUri, redirectUri, "f");
513
439
  }
514
440
  }
515
- get redirectUri() {
516
- return this._redirectUri || `${this.location.origin}${this.locationService.path(true) || '/'}`;
517
- }
518
441
  ngOnDestroy() {
519
- this.subscription.unsubscribe();
442
+ __classPrivateFieldGet(this, _OAuthLoginComponent_subscription, "f").unsubscribe();
520
443
  }
521
444
  logout() {
522
445
  this.oauthService.logout(this.useLogoutUrl);
523
446
  }
524
447
  login(parameters) {
525
- return __awaiter(this, void 0, void 0, function* () {
526
- yield this.oauthService.login(parameters);
527
- this.collapse = false;
528
- });
448
+ this.collapse = false;
449
+ return this.oauthService.login(parameters);
529
450
  }
530
451
  toggleCollapse() {
531
452
  this.collapse = !this.collapse;
@@ -533,14 +454,18 @@ class OAuthLoginComponent {
533
454
  keyboardEvent() {
534
455
  this.collapse = false;
535
456
  }
457
+ get responseType() {
458
+ return this.type; //avoid complains
459
+ }
536
460
  }
537
- OAuthLoginComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthLoginComponent, deps: [{ token: OAuthService }, { token: i2.Location }, { token: LOCATION }], target: i0.ɵɵFactoryTarget.Component });
538
- 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$" }, 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 });
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 });
539
464
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: OAuthLoginComponent, decorators: [{
540
465
  type: Component,
541
- 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"] }]
542
467
  }], ctorParameters: function () {
543
- return [{ type: OAuthService }, { type: i2.Location }, { type: Location, decorators: [{
468
+ return [{ type: OAuthService }, { type: i2$1.Location }, { type: Location, decorators: [{
544
469
  type: Inject,
545
470
  args: [LOCATION]
546
471
  }] }];
@@ -559,6 +484,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImpor
559
484
  }], loginTemplate: [{
560
485
  type: ContentChild,
561
486
  args: ['login', { static: false }]
487
+ }], type: [{
488
+ type: Input
562
489
  }], keyboardEvent: [{
563
490
  type: HostListener,
564
491
  args: ['window:keydown.escape']
@@ -571,10 +498,10 @@ const mockLocation = (serverHost, serverPath) => {
571
498
  href, origin, protocol, host, hostname, port, pathname, search, hash,
572
499
  reload() {
573
500
  },
574
- assign(u) {
501
+ assign(_) {
575
502
  },
576
503
  ancestorOrigins: {},
577
- replace(u) {
504
+ replace(_) {
578
505
  }
579
506
  };
580
507
  };
@@ -630,9 +557,10 @@ class OAuthModule {
630
557
  providers: [
631
558
  LocationService,
632
559
  StorageService,
633
- OAuthService,
634
- OAuthInterceptorService,
635
560
  provideOAuthConfigFactory((storage) => (Object.assign(Object.assign({}, defaultConfig(storage)), config)), [STORAGE]),
561
+ TokenService,
562
+ OAuthInterceptorService,
563
+ OAuthService,
636
564
  ]
637
565
  };
638
566
  }
@@ -668,5 +596,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImpor
668
596
  * Generated bundle index. Do not edit.
669
597
  */
670
598
 
671
- export { LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthConfig, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE, provideOAuthConfig, provideOAuthConfigFactory };
599
+ export { HEADER_APPLICATION, LOCATION, OAUTH_CONFIG, OAUTH_TOKEN, OAuthConfig, OAuthInterceptor, OAuthLoginComponent, OAuthModule, OAuthService, OAuthStatus, OAuthType, SERVER_HOST, SERVER_PATH, STORAGE, provideOAuthConfig, provideOAuthConfigFactory };
672
600
  //# sourceMappingURL=ngx-oauth.mjs.map