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