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