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