@kolektor/nucleus-identity 0.0.12-pre.7919 → 0.1.0-pre.124
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 -0
- package/esm2022/index.mjs +7 -0
- package/esm2022/kolektor-nucleus-identity.mjs +5 -0
- package/esm2022/lib/models/client-registration.mjs +8 -0
- package/esm2022/lib/models/device-code.mjs +19 -0
- package/esm2022/lib/models/identity.mjs +52 -0
- package/esm2022/lib/models/otp.mjs +11 -0
- package/esm2022/lib/models/service-principal.mjs +16 -0
- package/esm2022/lib/nucleus-identity-config.mjs +7 -0
- package/esm2022/lib/nucleus-identity.module.mjs +32 -0
- package/esm2022/lib/nucleus-identity.service.mjs +350 -0
- package/esm2022/lib/nucleus-token-interceptor.service.mjs +69 -0
- package/esm2022/lib/utils/angular-requestor.mjs +44 -0
- package/esm2022/lib/utils/authorization-service-configuration.mjs +28 -0
- package/esm2022/lib/utils/location.service.mjs +72 -0
- package/esm2022/lib/utils/nucleus-authorization-notifier.mjs +15 -0
- package/esm2022/lib/utils/oidc-configuration.service.mjs +95 -0
- package/esm2022/lib/utils/secrets-store.mjs +120 -0
- package/esm2022/lib/utils/token-client.mjs +140 -0
- package/{fesm2020 → fesm2022}/kolektor-nucleus-identity.mjs +980 -1012
- package/fesm2022/kolektor-nucleus-identity.mjs.map +1 -0
- package/index.d.ts +6 -5
- package/lib/models/client-registration.d.ts +11 -11
- package/lib/models/device-code.d.ts +19 -19
- package/lib/models/identity.d.ts +14 -14
- package/lib/models/otp.d.ts +14 -14
- package/lib/models/service-principal.d.ts +12 -12
- package/lib/nucleus-identity-config.d.ts +12 -12
- package/lib/nucleus-identity.module.d.ts +9 -9
- package/lib/nucleus-identity.service.d.ts +63 -63
- package/lib/nucleus-token-interceptor.service.d.ts +19 -19
- package/lib/utils/angular-requestor.d.ts +11 -11
- package/lib/utils/authorization-service-configuration.d.ts +12 -12
- package/lib/utils/location.service.d.ts +25 -25
- package/lib/utils/nucleus-authorization-notifier.d.ts +9 -9
- package/lib/utils/oidc-configuration.service.d.ts +23 -23
- package/lib/utils/secrets-store.d.ts +33 -33
- package/lib/utils/token-client.d.ts +23 -23
- package/package.json +29 -33
- package/esm2020/kolektor-nucleus-identity.mjs +0 -5
- package/esm2020/lib/models/client-registration.mjs +0 -8
- package/esm2020/lib/models/device-code.mjs +0 -19
- package/esm2020/lib/models/identity.mjs +0 -49
- package/esm2020/lib/models/otp.mjs +0 -11
- package/esm2020/lib/models/service-principal.mjs +0 -16
- package/esm2020/lib/nucleus-identity-config.mjs +0 -8
- package/esm2020/lib/nucleus-identity.module.mjs +0 -28
- package/esm2020/lib/nucleus-identity.service.mjs +0 -341
- package/esm2020/lib/nucleus-token-interceptor.service.mjs +0 -64
- package/esm2020/lib/utils/angular-requestor.mjs +0 -38
- package/esm2020/lib/utils/authorization-service-configuration.mjs +0 -23
- package/esm2020/lib/utils/location.service.mjs +0 -72
- package/esm2020/lib/utils/nucleus-authorization-notifier.mjs +0 -13
- package/esm2020/lib/utils/nucleus-crypto.mjs +0 -68
- package/esm2020/lib/utils/oidc-configuration.service.mjs +0 -90
- package/esm2020/lib/utils/secrets-store.mjs +0 -120
- package/esm2020/lib/utils/token-client.mjs +0 -140
- package/esm2020/public-api.mjs +0 -11
- package/fesm2015/kolektor-nucleus-identity.mjs +0 -1139
- package/fesm2015/kolektor-nucleus-identity.mjs.map +0 -1
- package/fesm2020/kolektor-nucleus-identity.mjs.map +0 -1
- package/lib/utils/nucleus-crypto.d.ts +0 -9
- package/public-api.d.ts +0 -7
|
@@ -3,1058 +3,1026 @@ import { Injectable, NgModule } from '@angular/core';
|
|
|
3
3
|
import * as i1$1 from '@angular/common/http';
|
|
4
4
|
import { HttpErrorResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
5
5
|
import { lastValueFrom, from, throwError } from 'rxjs';
|
|
6
|
-
import {
|
|
6
|
+
import { AuthorizationNotifier, TokenResponse, Requestor, AppAuthError, AuthorizationServiceConfiguration, JQueryRequestor, nowInSeconds, BaseTokenRequestHandler, BasicQueryStringUtils, TokenRequest, GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN, LocalStorageBackend, DefaultCrypto, RedirectRequestHandler, AuthorizationRequest } from '@openid/appauth';
|
|
7
7
|
import { App } from '@capacitor/app';
|
|
8
8
|
import { Browser } from '@capacitor/browser';
|
|
9
9
|
import { Device } from '@capacitor/device';
|
|
10
|
-
import * as base64 from 'base64-js';
|
|
11
10
|
import * as i1 from '@kolektor/nucleus-common';
|
|
12
11
|
import { SecureStoragePlugin } from 'capacitor-secure-storage-plugin';
|
|
13
12
|
import { mergeMap, catchError } from 'rxjs/operators';
|
|
14
13
|
|
|
15
|
-
class NucleusIdentityConfig {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
19
|
-
|
|
20
|
-
}
|
|
14
|
+
class NucleusIdentityConfig {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.httpInterceptorUrls = [];
|
|
17
|
+
this.automaticLoginOnHttp401 = false;
|
|
18
|
+
}
|
|
21
19
|
}
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const index = buffer[i] % CHARSET.length;
|
|
83
|
-
state.push(CHARSET[index]);
|
|
84
|
-
}
|
|
85
|
-
return state.join('');
|
|
86
|
-
}
|
|
21
|
+
class LocationService {
|
|
22
|
+
constructor(appService) {
|
|
23
|
+
this.appService = appService;
|
|
24
|
+
}
|
|
25
|
+
get hash() {
|
|
26
|
+
return window.location.hash;
|
|
27
|
+
}
|
|
28
|
+
set hash(v) {
|
|
29
|
+
window.location.hash = v;
|
|
30
|
+
}
|
|
31
|
+
get host() {
|
|
32
|
+
return window.location.host;
|
|
33
|
+
}
|
|
34
|
+
set host(v) {
|
|
35
|
+
window.location.host = v;
|
|
36
|
+
}
|
|
37
|
+
get origin() {
|
|
38
|
+
return window.location.origin;
|
|
39
|
+
}
|
|
40
|
+
get hostname() {
|
|
41
|
+
return window.location.hostname;
|
|
42
|
+
}
|
|
43
|
+
set hostname(v) {
|
|
44
|
+
window.location.hostname = v;
|
|
45
|
+
}
|
|
46
|
+
get pathname() {
|
|
47
|
+
return window.location.pathname;
|
|
48
|
+
}
|
|
49
|
+
set pathname(v) {
|
|
50
|
+
window.location.pathname = v;
|
|
51
|
+
}
|
|
52
|
+
get port() {
|
|
53
|
+
return window.location.port;
|
|
54
|
+
}
|
|
55
|
+
set port(v) {
|
|
56
|
+
window.location.port = v;
|
|
57
|
+
}
|
|
58
|
+
get protocol() {
|
|
59
|
+
return window.location.protocol;
|
|
60
|
+
}
|
|
61
|
+
set protocol(v) {
|
|
62
|
+
window.location.protocol = v;
|
|
63
|
+
}
|
|
64
|
+
get search() {
|
|
65
|
+
return window.location.search;
|
|
66
|
+
}
|
|
67
|
+
set search(v) {
|
|
68
|
+
window.location.search = v;
|
|
69
|
+
}
|
|
70
|
+
assign(url) {
|
|
71
|
+
if (this.appService.isNative) {
|
|
72
|
+
Browser.open({ url });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
window.location.assign(url);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocationService, deps: [{ token: i1.NucleusAppService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
79
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocationService, providedIn: 'root' }); }
|
|
87
80
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
get hash() {
|
|
94
|
-
return window.location.hash;
|
|
95
|
-
}
|
|
96
|
-
set hash(v) {
|
|
97
|
-
window.location.hash = v;
|
|
98
|
-
}
|
|
99
|
-
get host() {
|
|
100
|
-
return window.location.host;
|
|
101
|
-
}
|
|
102
|
-
set host(v) {
|
|
103
|
-
window.location.host = v;
|
|
104
|
-
}
|
|
105
|
-
get origin() {
|
|
106
|
-
return window.location.origin;
|
|
107
|
-
}
|
|
108
|
-
get hostname() {
|
|
109
|
-
return window.location.hostname;
|
|
110
|
-
}
|
|
111
|
-
set hostname(v) {
|
|
112
|
-
window.location.hostname = v;
|
|
113
|
-
}
|
|
114
|
-
get pathname() {
|
|
115
|
-
return window.location.pathname;
|
|
116
|
-
}
|
|
117
|
-
set pathname(v) {
|
|
118
|
-
window.location.pathname = v;
|
|
119
|
-
}
|
|
120
|
-
get port() {
|
|
121
|
-
return window.location.port;
|
|
122
|
-
}
|
|
123
|
-
set port(v) {
|
|
124
|
-
window.location.port = v;
|
|
125
|
-
}
|
|
126
|
-
get protocol() {
|
|
127
|
-
return window.location.protocol;
|
|
128
|
-
}
|
|
129
|
-
set protocol(v) {
|
|
130
|
-
window.location.protocol = v;
|
|
131
|
-
}
|
|
132
|
-
get search() {
|
|
133
|
-
return window.location.search;
|
|
134
|
-
}
|
|
135
|
-
set search(v) {
|
|
136
|
-
window.location.search = v;
|
|
137
|
-
}
|
|
138
|
-
assign(url) {
|
|
139
|
-
if (this.appService.isNative) {
|
|
140
|
-
Browser.open({ url });
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
window.location.assign(url);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
LocationService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: LocationService, deps: [{ token: i1.NucleusAppService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
148
|
-
LocationService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: LocationService, providedIn: 'root' });
|
|
149
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: LocationService, decorators: [{
|
|
150
|
-
type: Injectable,
|
|
151
|
-
args: [{
|
|
152
|
-
providedIn: 'root'
|
|
153
|
-
}]
|
|
81
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: LocationService, decorators: [{
|
|
82
|
+
type: Injectable,
|
|
83
|
+
args: [{
|
|
84
|
+
providedIn: 'root',
|
|
85
|
+
}]
|
|
154
86
|
}], ctorParameters: function () { return [{ type: i1.NucleusAppService }]; } });
|
|
155
87
|
|
|
156
|
-
class NucleusAuthorizationNotifier extends AuthorizationNotifier {
|
|
157
|
-
constructor() {
|
|
158
|
-
super();
|
|
159
|
-
this.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
this.
|
|
164
|
-
|
|
165
|
-
|
|
88
|
+
class NucleusAuthorizationNotifier extends AuthorizationNotifier {
|
|
89
|
+
constructor() {
|
|
90
|
+
super();
|
|
91
|
+
this.response = null;
|
|
92
|
+
this.error = null;
|
|
93
|
+
this.setAuthorizationListener((request, response, error) => {
|
|
94
|
+
console.log('Authorization request complete ', request, response, error);
|
|
95
|
+
this.response = response;
|
|
96
|
+
this.request = request;
|
|
97
|
+
this.error = error;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
166
100
|
}
|
|
167
101
|
|
|
168
|
-
class Claim {
|
|
169
|
-
constructor(name, values) {
|
|
170
|
-
this.name = name;
|
|
171
|
-
this.values = values;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
class Identity {
|
|
175
|
-
constructor() {
|
|
176
|
-
this.claims = [];
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
for (const key in token) {
|
|
184
|
-
if ({}.hasOwnProperty.call(token, key)) {
|
|
185
|
-
let vals = token[key];
|
|
186
|
-
if (!Array.isArray(vals)) {
|
|
187
|
-
vals = [vals];
|
|
188
|
-
}
|
|
189
|
-
const claim = new Claim(key, vals);
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
if (!jwt) {
|
|
197
|
-
throw new Error('NucleusIdentity: There was no identity token in the response!');
|
|
198
|
-
}
|
|
199
|
-
try {
|
|
200
|
-
const arr = jwt.split('.');
|
|
201
|
-
// var header = arr[0];
|
|
202
|
-
const payload = this.b64DecodeUnicode(arr[1]);
|
|
203
|
-
// var signature = arr[2];
|
|
204
|
-
return JSON.parse(payload);
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
console.error('Error while decoding identity token', error);
|
|
208
|
-
console.error('Error while decoding identity token JWT', jwt);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
str = str.replace(/-/g, '+').replace(/_/g, '/'); // Qlector fix :)
|
|
213
|
-
return decodeURIComponent(atob(str)
|
|
214
|
-
|
|
102
|
+
class Claim {
|
|
103
|
+
constructor(name, values) {
|
|
104
|
+
this.name = name;
|
|
105
|
+
this.values = values;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
class Identity {
|
|
109
|
+
constructor(res) {
|
|
110
|
+
this.claims = [];
|
|
111
|
+
if (!res.idToken) {
|
|
112
|
+
throw Error("There is no id token in the token response!");
|
|
113
|
+
}
|
|
114
|
+
const token = this.decodeToken(res.idToken);
|
|
115
|
+
this.name = token.name;
|
|
116
|
+
this.subject = token.sub;
|
|
117
|
+
for (const key in token) {
|
|
118
|
+
if ({}.hasOwnProperty.call(token, key)) {
|
|
119
|
+
let vals = token[key];
|
|
120
|
+
if (!Array.isArray(vals)) {
|
|
121
|
+
vals = [vals];
|
|
122
|
+
}
|
|
123
|
+
const claim = new Claim(key, vals);
|
|
124
|
+
this.claims.push(claim);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
129
|
+
decodeToken(jwt) {
|
|
130
|
+
if (!jwt) {
|
|
131
|
+
throw new Error('NucleusIdentity: There was no identity token in the response!');
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const arr = jwt.split('.');
|
|
135
|
+
// var header = arr[0];
|
|
136
|
+
const payload = this.b64DecodeUnicode(arr[1]);
|
|
137
|
+
// var signature = arr[2];
|
|
138
|
+
return JSON.parse(payload);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
console.error('Error while decoding identity token', error);
|
|
142
|
+
console.error('Error while decoding identity token JWT', jwt);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
b64DecodeUnicode(str) {
|
|
146
|
+
str = str.replace(/-/g, '+').replace(/_/g, '/'); // Qlector fix :)
|
|
147
|
+
return decodeURIComponent(atob(str)
|
|
148
|
+
.split('')
|
|
149
|
+
.map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
|
|
150
|
+
.join(''));
|
|
151
|
+
}
|
|
215
152
|
}
|
|
216
153
|
|
|
217
|
-
class SecretsStore {
|
|
218
|
-
constructor(clientId) {
|
|
219
|
-
this._tokens = {};
|
|
220
|
-
this._identities = {};
|
|
221
|
-
|
|
222
|
-
this.
|
|
223
|
-
this.
|
|
224
|
-
this.
|
|
225
|
-
this.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
clear(key) {
|
|
312
|
-
return SecureStoragePlugin.remove({ key });
|
|
313
|
-
}
|
|
314
|
-
save(key, value) {
|
|
315
|
-
return SecureStoragePlugin.set({ key, value: JSON.stringify(value) });
|
|
316
|
-
}
|
|
317
|
-
async load(key) {
|
|
318
|
-
try {
|
|
319
|
-
const x = await SecureStoragePlugin.get({ key });
|
|
320
|
-
if (x?.value) {
|
|
321
|
-
return JSON.parse(x.value);
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
return null;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
catch {
|
|
328
|
-
return null;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
154
|
+
class SecretsStore {
|
|
155
|
+
constructor(clientId) {
|
|
156
|
+
this._tokens = {};
|
|
157
|
+
this._identities = {};
|
|
158
|
+
this._servicePrincipal = null;
|
|
159
|
+
this._tokenStorageKeyPrefix = `Nucleus.Identity.${clientId}`; // do not change this or login with existing tokens will fail
|
|
160
|
+
this._servicePrincipalKey = `${this._tokenStorageKeyPrefix}.SvcP`;
|
|
161
|
+
this._defaultIdentityIdStorageKey = `${this._tokenStorageKeyPrefix}.IdId`;
|
|
162
|
+
this._defaultIdentityId = localStorage.getItem(this._defaultIdentityIdStorageKey);
|
|
163
|
+
}
|
|
164
|
+
get defaultIdentityId() {
|
|
165
|
+
return this._defaultIdentityId;
|
|
166
|
+
}
|
|
167
|
+
removeServicePrincipal() {
|
|
168
|
+
this._servicePrincipal = null;
|
|
169
|
+
return this.clear(this._servicePrincipalKey);
|
|
170
|
+
}
|
|
171
|
+
async setServicePrincipal(servicePrincipal) {
|
|
172
|
+
this._servicePrincipal = servicePrincipal;
|
|
173
|
+
await this.save(this._servicePrincipalKey, servicePrincipal);
|
|
174
|
+
}
|
|
175
|
+
async getServicePrincipal() {
|
|
176
|
+
if (!this._servicePrincipal) {
|
|
177
|
+
this._servicePrincipal = await this.load(this._servicePrincipalKey);
|
|
178
|
+
}
|
|
179
|
+
return this._servicePrincipal;
|
|
180
|
+
}
|
|
181
|
+
setToken(token, id = null) {
|
|
182
|
+
return this.setTokenInternal(token, true, id);
|
|
183
|
+
}
|
|
184
|
+
getIdentity(id = null) {
|
|
185
|
+
const key = this.getTokenKey(id);
|
|
186
|
+
return this._identities[key];
|
|
187
|
+
}
|
|
188
|
+
setDefaultIdentityId(id) {
|
|
189
|
+
this._defaultIdentityId = id;
|
|
190
|
+
if (this._defaultIdentityId) {
|
|
191
|
+
localStorage.setItem(this._defaultIdentityIdStorageKey, this._defaultIdentityId);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
localStorage.removeItem(this._defaultIdentityIdStorageKey);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async getToken(id = null) {
|
|
198
|
+
const key = this.getTokenKey(id);
|
|
199
|
+
// if token is not there or it is invalid we check storage again before returning
|
|
200
|
+
if (!this._tokens[key] || !this._tokens[key]?.isValid()) {
|
|
201
|
+
await this.reloadTokenFromStorage(id);
|
|
202
|
+
}
|
|
203
|
+
return this._tokens[key];
|
|
204
|
+
}
|
|
205
|
+
removeToken(id = null) {
|
|
206
|
+
const key = this.getTokenKey(id);
|
|
207
|
+
delete this._tokens[key];
|
|
208
|
+
delete this._identities[key];
|
|
209
|
+
return this.clear(key);
|
|
210
|
+
}
|
|
211
|
+
async reloadTokenFromStorage(id) {
|
|
212
|
+
const key = this.getTokenKey(id);
|
|
213
|
+
const storedToken = await this.load(key);
|
|
214
|
+
if (storedToken) {
|
|
215
|
+
const res = new TokenResponse(storedToken);
|
|
216
|
+
if (res?.accessToken || res?.idToken) {
|
|
217
|
+
await this.setTokenInternal(res, false, id);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
async setTokenInternal(token, save, id) {
|
|
223
|
+
const key = this.getTokenKey(id);
|
|
224
|
+
if (token == null) {
|
|
225
|
+
await this.removeToken(id);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
this._tokens[key] = token;
|
|
229
|
+
this._identities[key] = new Identity(token);
|
|
230
|
+
if (save) {
|
|
231
|
+
try {
|
|
232
|
+
await this.save(key, token.toJson());
|
|
233
|
+
}
|
|
234
|
+
catch (e) {
|
|
235
|
+
console.warn('Nucleus.Identity: Could not save to SecureStorage.');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
getTokenKey(id) {
|
|
241
|
+
if (!id) {
|
|
242
|
+
id = this._defaultIdentityId;
|
|
243
|
+
}
|
|
244
|
+
return id
|
|
245
|
+
? `${this._tokenStorageKeyPrefix}.${id}`
|
|
246
|
+
: this._tokenStorageKeyPrefix;
|
|
247
|
+
}
|
|
248
|
+
clear(key) {
|
|
249
|
+
return SecureStoragePlugin.remove({ key });
|
|
250
|
+
}
|
|
251
|
+
save(key, value) {
|
|
252
|
+
return SecureStoragePlugin.set({ key, value: JSON.stringify(value) });
|
|
253
|
+
}
|
|
254
|
+
async load(key) {
|
|
255
|
+
try {
|
|
256
|
+
const x = await SecureStoragePlugin.get({ key });
|
|
257
|
+
if (x?.value) {
|
|
258
|
+
return JSON.parse(x.value);
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
331
268
|
}
|
|
332
269
|
|
|
333
|
-
class AngularRequestor extends Requestor {
|
|
334
|
-
constructor(http) {
|
|
335
|
-
super();
|
|
336
|
-
this.http = http;
|
|
337
|
-
}
|
|
338
|
-
// eslint-disable-next-line no-undef
|
|
339
|
-
xhr(settings) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
270
|
+
class AngularRequestor extends Requestor {
|
|
271
|
+
constructor(http) {
|
|
272
|
+
super();
|
|
273
|
+
this.http = http;
|
|
274
|
+
}
|
|
275
|
+
// eslint-disable-next-line no-undef
|
|
276
|
+
xhr(settings) {
|
|
277
|
+
let method = 'GET';
|
|
278
|
+
if (settings.method) {
|
|
279
|
+
method = settings.method;
|
|
280
|
+
}
|
|
281
|
+
return new Promise((resolve, reject) => {
|
|
282
|
+
this.http
|
|
283
|
+
.request(method, settings.url, {
|
|
284
|
+
body: settings.data,
|
|
285
|
+
headers: settings.headers,
|
|
286
|
+
}).
|
|
287
|
+
subscribe({
|
|
288
|
+
next: res => resolve(res),
|
|
289
|
+
error: err => {
|
|
290
|
+
let e = new AppAuthError(err);
|
|
291
|
+
if (err instanceof HttpErrorResponse) {
|
|
292
|
+
e = new AppAuthError(err.error?.error || err.statusText);
|
|
293
|
+
}
|
|
294
|
+
reject(e);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AngularRequestor, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
300
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AngularRequestor, providedIn: 'root' }); }
|
|
301
|
+
}
|
|
302
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AngularRequestor, decorators: [{
|
|
303
|
+
type: Injectable,
|
|
304
|
+
args: [{
|
|
305
|
+
providedIn: 'root',
|
|
306
|
+
}]
|
|
364
307
|
}], ctorParameters: function () { return [{ type: i1$1.HttpClient }]; } });
|
|
365
308
|
|
|
366
|
-
const WELL_KNOWN_PATH = '.well-known';
|
|
367
|
-
const OPENID_CONFIGURATION = 'openid-configuration';
|
|
368
|
-
class NucleusAuthorizationServiceConfiguration extends AuthorizationServiceConfiguration {
|
|
369
|
-
constructor(request) {
|
|
370
|
-
super(request);
|
|
371
|
-
this.deviceAuthorizationEndpoint = request.device_authorization_endpoint;
|
|
372
|
-
this.registrationEndpoint = request.registration_endpoint;
|
|
373
|
-
}
|
|
374
|
-
static fetchFromIssuer(openIdIssuerUrl, requestor) {
|
|
375
|
-
const fullUrl = `${openIdIssuerUrl}/${WELL_KNOWN_PATH}/${OPENID_CONFIGURATION}`;
|
|
376
|
-
const requestorToUse = requestor || new JQueryRequestor();
|
|
377
|
-
|
|
378
|
-
.xhr({
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
309
|
+
const WELL_KNOWN_PATH = '.well-known';
|
|
310
|
+
const OPENID_CONFIGURATION = 'openid-configuration';
|
|
311
|
+
class NucleusAuthorizationServiceConfiguration extends AuthorizationServiceConfiguration {
|
|
312
|
+
constructor(request) {
|
|
313
|
+
super(request);
|
|
314
|
+
this.deviceAuthorizationEndpoint = request.device_authorization_endpoint;
|
|
315
|
+
this.registrationEndpoint = request.registration_endpoint;
|
|
316
|
+
}
|
|
317
|
+
static async fetchFromIssuer(openIdIssuerUrl, requestor) {
|
|
318
|
+
const fullUrl = `${openIdIssuerUrl}/${WELL_KNOWN_PATH}/${OPENID_CONFIGURATION}`;
|
|
319
|
+
const requestorToUse = requestor || new JQueryRequestor();
|
|
320
|
+
const json = await requestorToUse
|
|
321
|
+
.xhr({
|
|
322
|
+
url: fullUrl,
|
|
323
|
+
dataType: 'json',
|
|
324
|
+
method: 'GET',
|
|
325
|
+
});
|
|
326
|
+
return new NucleusAuthorizationServiceConfiguration(json);
|
|
327
|
+
}
|
|
328
|
+
toJson() {
|
|
329
|
+
const res = super.toJson();
|
|
330
|
+
res.device_authorization_endpoint = this.deviceAuthorizationEndpoint;
|
|
331
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
332
|
+
return res;
|
|
333
|
+
}
|
|
386
334
|
}
|
|
387
335
|
|
|
388
|
-
class OidcConfigurationService {
|
|
389
|
-
constructor(requestor, config, appService) {
|
|
390
|
-
this.requestor = requestor;
|
|
391
|
-
this.config = config;
|
|
392
|
-
this.appService = appService;
|
|
393
|
-
this._configuration = null;
|
|
394
|
-
}
|
|
395
|
-
async getConfiguration() {
|
|
396
|
-
await this.assureConfiguration();
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
return this.
|
|
401
|
-
}
|
|
402
|
-
get
|
|
403
|
-
return this.config.
|
|
404
|
-
}
|
|
405
|
-
get
|
|
406
|
-
return this.config.
|
|
407
|
-
}
|
|
408
|
-
get
|
|
409
|
-
return this.config.
|
|
410
|
-
}
|
|
411
|
-
get
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
uri = this.config.
|
|
419
|
-
}
|
|
420
|
-
else if (this.config.
|
|
421
|
-
uri = this.config.
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
336
|
+
class OidcConfigurationService {
|
|
337
|
+
constructor(requestor, config, appService) {
|
|
338
|
+
this.requestor = requestor;
|
|
339
|
+
this.config = config;
|
|
340
|
+
this.appService = appService;
|
|
341
|
+
this._configuration = null;
|
|
342
|
+
}
|
|
343
|
+
async getConfiguration() {
|
|
344
|
+
await this.assureConfiguration();
|
|
345
|
+
if (!this._configuration) {
|
|
346
|
+
throw Error('Failed to get OIDC configuration!');
|
|
347
|
+
}
|
|
348
|
+
return this._configuration;
|
|
349
|
+
}
|
|
350
|
+
get clientId() {
|
|
351
|
+
return this.config.clientId;
|
|
352
|
+
}
|
|
353
|
+
get requestedScopes() {
|
|
354
|
+
return this.config.requestedScopes;
|
|
355
|
+
}
|
|
356
|
+
get servicePrincipalRequestedScopes() {
|
|
357
|
+
return this.config.servicePrincipalRequestedScopes;
|
|
358
|
+
}
|
|
359
|
+
get authProviderHint() {
|
|
360
|
+
return this.config.authProviderHint;
|
|
361
|
+
}
|
|
362
|
+
get redirectUrl() {
|
|
363
|
+
let uri = window.location.href;
|
|
364
|
+
const platform = this.appService.platform;
|
|
365
|
+
if (platform === 'android' && this.config.androidRedirectUri) {
|
|
366
|
+
uri = this.config.androidRedirectUri;
|
|
367
|
+
}
|
|
368
|
+
else if (platform === 'ios' && this.config.iOSRedirectUri) {
|
|
369
|
+
uri = this.config.iOSRedirectUri;
|
|
370
|
+
}
|
|
371
|
+
else if (this.config.redirectUri) {
|
|
372
|
+
uri = this.config.redirectUri;
|
|
373
|
+
}
|
|
374
|
+
return this.NormalizeRedirectUri(uri);
|
|
375
|
+
}
|
|
376
|
+
getServerUrl(relativeUri = null) {
|
|
377
|
+
let authority = this.config.authority;
|
|
378
|
+
if (!authority || authority === 'origin') {
|
|
379
|
+
authority = window.origin;
|
|
380
|
+
}
|
|
381
|
+
let url = new URL(authority);
|
|
382
|
+
if (relativeUri) {
|
|
383
|
+
url = new URL(relativeUri, url);
|
|
384
|
+
}
|
|
385
|
+
return url.href;
|
|
386
|
+
}
|
|
387
|
+
NormalizeRedirectUri(uri) {
|
|
388
|
+
const i = uri.indexOf('#');
|
|
389
|
+
if (i > 0) {
|
|
390
|
+
uri = uri.substring(0, i);
|
|
391
|
+
}
|
|
392
|
+
return uri;
|
|
393
|
+
}
|
|
394
|
+
async assureConfiguration() {
|
|
395
|
+
if (this._configuration != null) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
let authority = this.getServerUrl();
|
|
399
|
+
if (authority[authority.length - 1] === '/') {
|
|
400
|
+
authority = authority.slice(0, -1);
|
|
401
|
+
}
|
|
402
|
+
try {
|
|
403
|
+
this._configuration =
|
|
404
|
+
await NucleusAuthorizationServiceConfiguration.fetchFromIssuer(authority, this.requestor);
|
|
405
|
+
}
|
|
406
|
+
catch (e) {
|
|
407
|
+
console.error('Nucleus.Identity: Cannot load OIDC configuration: ' +
|
|
408
|
+
e.message);
|
|
409
|
+
throw e;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OidcConfigurationService, deps: [{ token: AngularRequestor }, { token: NucleusIdentityConfig }, { token: i1.NucleusAppService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
413
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OidcConfigurationService, providedIn: 'root' }); }
|
|
414
|
+
}
|
|
415
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OidcConfigurationService, decorators: [{
|
|
416
|
+
type: Injectable,
|
|
417
|
+
args: [{
|
|
418
|
+
providedIn: 'root',
|
|
419
|
+
}]
|
|
467
420
|
}], ctorParameters: function () { return [{ type: AngularRequestor }, { type: NucleusIdentityConfig }, { type: i1.NucleusAppService }]; } });
|
|
468
421
|
|
|
469
|
-
class DeviceCode {
|
|
470
|
-
constructor(response) {
|
|
471
|
-
this.deviceCode = response.device_code;
|
|
472
|
-
this.userCode = response.user_code;
|
|
473
|
-
this.verificationUrl = response.verification_uri;
|
|
474
|
-
this.verificationUrlComplete = response.verification_uri_complete;
|
|
475
|
-
this.expiresIn = parseInt(response.expires_in, 10);
|
|
476
|
-
this.issuedAt = nowInSeconds();
|
|
477
|
-
}
|
|
478
|
-
isExpired(buffer = 60) {
|
|
479
|
-
return this.secondsLeft(buffer) <= 0;
|
|
480
|
-
}
|
|
481
|
-
secondsLeft(buffer = 60) {
|
|
482
|
-
const now = nowInSeconds();
|
|
483
|
-
return
|
|
484
|
-
}
|
|
422
|
+
class DeviceCode {
|
|
423
|
+
constructor(response) {
|
|
424
|
+
this.deviceCode = response.device_code;
|
|
425
|
+
this.userCode = response.user_code;
|
|
426
|
+
this.verificationUrl = response.verification_uri;
|
|
427
|
+
this.verificationUrlComplete = response.verification_uri_complete;
|
|
428
|
+
this.expiresIn = parseInt(response.expires_in, 10);
|
|
429
|
+
this.issuedAt = nowInSeconds();
|
|
430
|
+
}
|
|
431
|
+
isExpired(buffer = 60) {
|
|
432
|
+
return this.secondsLeft(buffer) <= 0;
|
|
433
|
+
}
|
|
434
|
+
secondsLeft(buffer = 60) {
|
|
435
|
+
const now = nowInSeconds();
|
|
436
|
+
return this.issuedAt + this.expiresIn - buffer - now;
|
|
437
|
+
}
|
|
485
438
|
}
|
|
486
439
|
|
|
487
|
-
class ClientRegistrationResponse {
|
|
488
|
-
constructor(response) {
|
|
489
|
-
this.clientId = response.client_id;
|
|
490
|
-
this.clientSecret = response.client_secret;
|
|
491
|
-
this.secretExpirationDate = new Date(response.client_secret_expires_at * 1000);
|
|
492
|
-
}
|
|
440
|
+
class ClientRegistrationResponse {
|
|
441
|
+
constructor(response) {
|
|
442
|
+
this.clientId = response.client_id;
|
|
443
|
+
this.clientSecret = response.client_secret;
|
|
444
|
+
this.secretExpirationDate = new Date(response.client_secret_expires_at * 1000);
|
|
445
|
+
}
|
|
493
446
|
}
|
|
494
447
|
|
|
495
|
-
class TokenClient {
|
|
496
|
-
constructor(requestor, config) {
|
|
497
|
-
this.requestor = requestor;
|
|
498
|
-
this.config = config;
|
|
499
|
-
this._tokenHandler = new BaseTokenRequestHandler(requestor);
|
|
500
|
-
this._utils = new BasicQueryStringUtils();
|
|
501
|
-
}
|
|
502
|
-
async getByAuthorizationCode(redirectUrl, code, codeVerifier) {
|
|
503
|
-
const config = await this.config.getConfiguration();
|
|
504
|
-
const redirectUri = redirectUrl;
|
|
505
|
-
const req = new TokenRequest({
|
|
506
|
-
client_id: this.config.clientId,
|
|
507
|
-
redirect_uri: redirectUri,
|
|
508
|
-
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
|
|
509
|
-
code,
|
|
510
|
-
extras: { code_verifier: codeVerifier }
|
|
511
|
-
});
|
|
512
|
-
return await this._tokenHandler.performTokenRequest(config, req);
|
|
513
|
-
}
|
|
514
|
-
async getByRefreshToken(refreshToken) {
|
|
515
|
-
const config = await this.config.getConfiguration();
|
|
516
|
-
const redirectUri = this.config.redirectUrl;
|
|
517
|
-
const req = new TokenRequest({
|
|
518
|
-
client_id: this.config.clientId,
|
|
519
|
-
redirect_uri: redirectUri,
|
|
520
|
-
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
521
|
-
refresh_token: refreshToken
|
|
522
|
-
});
|
|
523
|
-
return await this._tokenHandler.performTokenRequest(config, req);
|
|
524
|
-
}
|
|
525
|
-
async getByClientCredentials(clientId, clientSecret, scope) {
|
|
526
|
-
const config = await this.config.getConfiguration();
|
|
527
|
-
const req = new TokenRequest({
|
|
528
|
-
client_id: clientId,
|
|
529
|
-
redirect_uri:
|
|
530
|
-
grant_type: 'client_credentials',
|
|
531
|
-
extras: {
|
|
532
|
-
client_secret: clientSecret,
|
|
533
|
-
scope,
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
return await this._tokenHandler.performTokenRequest(config, req);
|
|
537
|
-
}
|
|
538
|
-
async getBySecret(provider, secret, assertionToken, scope) {
|
|
539
|
-
const config = await this.config.getConfiguration();
|
|
540
|
-
const req = new TokenRequest({
|
|
541
|
-
client_id: this.config.clientId,
|
|
542
|
-
redirect_uri:
|
|
543
|
-
grant_type: 'urn:kolektor:nucleus:secret',
|
|
544
|
-
extras: {
|
|
545
|
-
secret_provider: provider,
|
|
546
|
-
secret_value: secret,
|
|
547
|
-
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
|
548
|
-
client_assertion: assertionToken,
|
|
549
|
-
scope,
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
return await this._tokenHandler.performTokenRequest(config, req);
|
|
553
|
-
}
|
|
554
|
-
async getByDeviceCode(deviceCode) {
|
|
555
|
-
const config = await this.config.getConfiguration();
|
|
556
|
-
const req = new TokenRequest({
|
|
557
|
-
client_id: this.config.clientId,
|
|
558
|
-
redirect_uri:
|
|
559
|
-
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
560
|
-
extras: {
|
|
561
|
-
device_code: deviceCode
|
|
562
|
-
}
|
|
563
|
-
});
|
|
564
|
-
return await this._tokenHandler.performTokenRequest(config, req);
|
|
565
|
-
}
|
|
566
|
-
async registerServicePrincipal(token) {
|
|
567
|
-
const config = await this.config.getConfiguration();
|
|
568
|
-
const response = await this.requestor.xhr({
|
|
569
|
-
url: config.registrationEndpoint,
|
|
570
|
-
method: 'POST',
|
|
571
|
-
dataType: 'json',
|
|
572
|
-
headers: {
|
|
573
|
-
'Content-Type': 'application/json',
|
|
574
|
-
Authorization: `Bearer ${token}
|
|
575
|
-
}
|
|
576
|
-
// data: this._utils.stringify(map)
|
|
577
|
-
});
|
|
578
|
-
if (response.error === undefined) {
|
|
579
|
-
return new ClientRegistrationResponse(response);
|
|
580
|
-
}
|
|
581
|
-
else {
|
|
582
|
-
throw new AppAuthError(response.error);
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
async getRegistrationCode(existingServicePrincipalId = null) {
|
|
586
|
-
const params = {
|
|
587
|
-
custom_action: 'sp_register',
|
|
588
|
-
service_principal_id: existingServicePrincipalId
|
|
589
|
-
};
|
|
590
|
-
return this.getDeviceCodeInternal(params);
|
|
591
|
-
}
|
|
592
|
-
async getDeviceCode(scope) {
|
|
593
|
-
const params = {
|
|
594
|
-
scope,
|
|
595
|
-
};
|
|
596
|
-
return this.getDeviceCodeInternal(params);
|
|
597
|
-
}
|
|
598
|
-
async getDeviceCodeInternal(params) {
|
|
599
|
-
const config = await this.config.getConfiguration();
|
|
600
|
-
params['client_id'] = this.config.clientId;
|
|
601
|
-
const map = params;
|
|
602
|
-
const response = await this.requestor.xhr({
|
|
603
|
-
url: config.deviceAuthorizationEndpoint,
|
|
604
|
-
method: 'POST',
|
|
605
|
-
dataType: 'json',
|
|
606
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
607
|
-
data: this._utils.stringify(map)
|
|
608
|
-
});
|
|
609
|
-
if (response.error === undefined) {
|
|
610
|
-
return new DeviceCode(response);
|
|
611
|
-
}
|
|
612
|
-
else {
|
|
613
|
-
throw new AppAuthError(response.error);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
620
|
-
type: Injectable,
|
|
621
|
-
args: [{
|
|
622
|
-
providedIn: 'root'
|
|
623
|
-
}]
|
|
448
|
+
class TokenClient {
|
|
449
|
+
constructor(requestor, config) {
|
|
450
|
+
this.requestor = requestor;
|
|
451
|
+
this.config = config;
|
|
452
|
+
this._tokenHandler = new BaseTokenRequestHandler(requestor);
|
|
453
|
+
this._utils = new BasicQueryStringUtils();
|
|
454
|
+
}
|
|
455
|
+
async getByAuthorizationCode(redirectUrl, code, codeVerifier) {
|
|
456
|
+
const config = await this.config.getConfiguration();
|
|
457
|
+
const redirectUri = redirectUrl;
|
|
458
|
+
const req = new TokenRequest({
|
|
459
|
+
client_id: this.config.clientId,
|
|
460
|
+
redirect_uri: redirectUri,
|
|
461
|
+
grant_type: GRANT_TYPE_AUTHORIZATION_CODE,
|
|
462
|
+
code,
|
|
463
|
+
extras: codeVerifier ? { code_verifier: codeVerifier } : undefined,
|
|
464
|
+
});
|
|
465
|
+
return await this._tokenHandler.performTokenRequest(config, req);
|
|
466
|
+
}
|
|
467
|
+
async getByRefreshToken(refreshToken) {
|
|
468
|
+
const config = await this.config.getConfiguration();
|
|
469
|
+
const redirectUri = this.config.redirectUrl;
|
|
470
|
+
const req = new TokenRequest({
|
|
471
|
+
client_id: this.config.clientId,
|
|
472
|
+
redirect_uri: redirectUri,
|
|
473
|
+
grant_type: GRANT_TYPE_REFRESH_TOKEN,
|
|
474
|
+
refresh_token: refreshToken,
|
|
475
|
+
});
|
|
476
|
+
return await this._tokenHandler.performTokenRequest(config, req);
|
|
477
|
+
}
|
|
478
|
+
async getByClientCredentials(clientId, clientSecret, scope) {
|
|
479
|
+
const config = await this.config.getConfiguration();
|
|
480
|
+
const req = new TokenRequest({
|
|
481
|
+
client_id: clientId,
|
|
482
|
+
redirect_uri: '',
|
|
483
|
+
grant_type: 'client_credentials',
|
|
484
|
+
extras: {
|
|
485
|
+
client_secret: clientSecret,
|
|
486
|
+
scope,
|
|
487
|
+
},
|
|
488
|
+
});
|
|
489
|
+
return await this._tokenHandler.performTokenRequest(config, req);
|
|
490
|
+
}
|
|
491
|
+
async getBySecret(provider, secret, assertionToken, scope) {
|
|
492
|
+
const config = await this.config.getConfiguration();
|
|
493
|
+
const req = new TokenRequest({
|
|
494
|
+
client_id: this.config.clientId,
|
|
495
|
+
redirect_uri: '',
|
|
496
|
+
grant_type: 'urn:kolektor:nucleus:secret',
|
|
497
|
+
extras: {
|
|
498
|
+
secret_provider: provider,
|
|
499
|
+
secret_value: secret,
|
|
500
|
+
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
|
501
|
+
client_assertion: assertionToken,
|
|
502
|
+
scope,
|
|
503
|
+
},
|
|
504
|
+
});
|
|
505
|
+
return await this._tokenHandler.performTokenRequest(config, req);
|
|
506
|
+
}
|
|
507
|
+
async getByDeviceCode(deviceCode) {
|
|
508
|
+
const config = await this.config.getConfiguration();
|
|
509
|
+
const req = new TokenRequest({
|
|
510
|
+
client_id: this.config.clientId,
|
|
511
|
+
redirect_uri: '',
|
|
512
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
513
|
+
extras: {
|
|
514
|
+
device_code: deviceCode,
|
|
515
|
+
},
|
|
516
|
+
});
|
|
517
|
+
return await this._tokenHandler.performTokenRequest(config, req);
|
|
518
|
+
}
|
|
519
|
+
async registerServicePrincipal(token) {
|
|
520
|
+
const config = await this.config.getConfiguration();
|
|
521
|
+
const response = await this.requestor.xhr({
|
|
522
|
+
url: config.registrationEndpoint,
|
|
523
|
+
method: 'POST',
|
|
524
|
+
dataType: 'json',
|
|
525
|
+
headers: {
|
|
526
|
+
'Content-Type': 'application/json',
|
|
527
|
+
Authorization: `Bearer ${token}`,
|
|
528
|
+
},
|
|
529
|
+
// data: this._utils.stringify(map)
|
|
530
|
+
});
|
|
531
|
+
if (response.error === undefined) {
|
|
532
|
+
return new ClientRegistrationResponse(response);
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
throw new AppAuthError(response.error);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
async getRegistrationCode(existingServicePrincipalId = null) {
|
|
539
|
+
const params = {
|
|
540
|
+
custom_action: 'sp_register',
|
|
541
|
+
service_principal_id: existingServicePrincipalId,
|
|
542
|
+
};
|
|
543
|
+
return this.getDeviceCodeInternal(params);
|
|
544
|
+
}
|
|
545
|
+
async getDeviceCode(scope) {
|
|
546
|
+
const params = {
|
|
547
|
+
scope,
|
|
548
|
+
};
|
|
549
|
+
return this.getDeviceCodeInternal(params);
|
|
550
|
+
}
|
|
551
|
+
async getDeviceCodeInternal(params) {
|
|
552
|
+
const config = await this.config.getConfiguration();
|
|
553
|
+
params['client_id'] = this.config.clientId;
|
|
554
|
+
const map = params;
|
|
555
|
+
const response = await this.requestor.xhr({
|
|
556
|
+
url: config.deviceAuthorizationEndpoint,
|
|
557
|
+
method: 'POST',
|
|
558
|
+
dataType: 'json',
|
|
559
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
560
|
+
data: this._utils.stringify(map),
|
|
561
|
+
});
|
|
562
|
+
if (response.error === undefined) {
|
|
563
|
+
return new DeviceCode(response);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
throw new AppAuthError(response.error);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TokenClient, deps: [{ token: AngularRequestor }, { token: OidcConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
570
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TokenClient, providedIn: 'root' }); }
|
|
571
|
+
}
|
|
572
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TokenClient, decorators: [{
|
|
573
|
+
type: Injectable,
|
|
574
|
+
args: [{
|
|
575
|
+
providedIn: 'root',
|
|
576
|
+
}]
|
|
624
577
|
}], ctorParameters: function () { return [{ type: AngularRequestor }, { type: OidcConfigurationService }]; } });
|
|
625
578
|
|
|
626
|
-
class ServicePrincipal {
|
|
627
|
-
}
|
|
628
|
-
class ServicePrincipalRegistrationStatus {
|
|
629
|
-
constructor(servicePrincipal) {
|
|
630
|
-
this.isRegistered = false;
|
|
631
|
-
if (servicePrincipal) {
|
|
632
|
-
this.isRegistered = true;
|
|
633
|
-
this.id = servicePrincipal.id;
|
|
634
|
-
this.expiresAt = servicePrincipal.expiresAt;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
get isExpired() {
|
|
638
|
-
return false;
|
|
639
|
-
}
|
|
579
|
+
class ServicePrincipal {
|
|
580
|
+
}
|
|
581
|
+
class ServicePrincipalRegistrationStatus {
|
|
582
|
+
constructor(servicePrincipal) {
|
|
583
|
+
this.isRegistered = false;
|
|
584
|
+
if (servicePrincipal) {
|
|
585
|
+
this.isRegistered = true;
|
|
586
|
+
this.id = servicePrincipal.id;
|
|
587
|
+
this.expiresAt = servicePrincipal.expiresAt;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
get isExpired() {
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
640
593
|
}
|
|
641
594
|
|
|
642
|
-
class NucleusIdentityService {
|
|
643
|
-
constructor(appService, location, http, config, tokenClient) {
|
|
644
|
-
this.appService = appService;
|
|
645
|
-
this.http = http;
|
|
646
|
-
this.config = config;
|
|
647
|
-
this.tokenClient = tokenClient;
|
|
648
|
-
this._authorizationNotifier = new NucleusAuthorizationNotifier();
|
|
649
|
-
this._initStarted = false;
|
|
650
|
-
this._initialized = false;
|
|
651
|
-
this.
|
|
652
|
-
|
|
653
|
-
this.
|
|
654
|
-
this.
|
|
655
|
-
|
|
656
|
-
this.
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
}
|
|
661
|
-
get
|
|
662
|
-
return this.
|
|
663
|
-
}
|
|
664
|
-
get
|
|
665
|
-
return this.
|
|
666
|
-
}
|
|
667
|
-
get
|
|
668
|
-
return this.
|
|
669
|
-
}
|
|
670
|
-
get
|
|
671
|
-
return this.
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
this.
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
this._store.
|
|
707
|
-
await this.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
this._store.
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
this._getTokenPromise =
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
this._getServicePrincipalTokenPromise =
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
}
|
|
793
|
-
async
|
|
794
|
-
|
|
795
|
-
if (
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
|
|
799
|
-
}
|
|
800
|
-
async
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
}
|
|
924
|
-
return null;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
if (
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
595
|
+
class NucleusIdentityService {
|
|
596
|
+
constructor(appService, location, http, config, tokenClient) {
|
|
597
|
+
this.appService = appService;
|
|
598
|
+
this.http = http;
|
|
599
|
+
this.config = config;
|
|
600
|
+
this.tokenClient = tokenClient;
|
|
601
|
+
this._authorizationNotifier = new NucleusAuthorizationNotifier();
|
|
602
|
+
this._initStarted = false;
|
|
603
|
+
this._initialized = false;
|
|
604
|
+
this._refreshTokenPromise = null;
|
|
605
|
+
this._getTokenPromise = null;
|
|
606
|
+
this._getServicePrincipalTokenPromise = null;
|
|
607
|
+
this._servicePrincipalTokenId = '_svcp';
|
|
608
|
+
const storage = new LocalStorageBackend();
|
|
609
|
+
this._crypto = new DefaultCrypto();
|
|
610
|
+
this._authorizationHandler = new RedirectRequestHandler(storage, new BasicQueryStringUtils(), location, this._crypto);
|
|
611
|
+
this._authorizationHandler.setAuthorizationNotifier(this._authorizationNotifier);
|
|
612
|
+
this._store = new SecretsStore(config.clientId);
|
|
613
|
+
}
|
|
614
|
+
get identity() {
|
|
615
|
+
return this._store.getIdentity();
|
|
616
|
+
}
|
|
617
|
+
get isAuthenticated() {
|
|
618
|
+
return this.identity != null;
|
|
619
|
+
}
|
|
620
|
+
get servicePrincipalIdentity() {
|
|
621
|
+
return this._store.getIdentity(this._servicePrincipalTokenId);
|
|
622
|
+
}
|
|
623
|
+
get isServicePrincipalAuthenticated() {
|
|
624
|
+
return this.servicePrincipalIdentity != null;
|
|
625
|
+
}
|
|
626
|
+
get isIdentityServicePrincipal() {
|
|
627
|
+
return this._store.defaultIdentityId === this._servicePrincipalTokenId;
|
|
628
|
+
}
|
|
629
|
+
async init(startLogin = false) {
|
|
630
|
+
if (this._initStarted || this._initialized) {
|
|
631
|
+
console.warn("Nucleus.Identity: Auth initialization was already started. Don't call init() multiple times!");
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
this._initStarted = true;
|
|
635
|
+
this.handleLaunchCodeHash();
|
|
636
|
+
await this._authorizationHandler.completeAuthorizationRequestIfPossible();
|
|
637
|
+
const authErr = this._authorizationNotifier.error;
|
|
638
|
+
if (authErr) {
|
|
639
|
+
throw new Error('Authorization err: ' + authErr.error + ': ' + authErr.errorDescription);
|
|
640
|
+
}
|
|
641
|
+
else if (this._authorizationNotifier.response) {
|
|
642
|
+
window.location.hash = '';
|
|
643
|
+
const request = this._authorizationNotifier.request;
|
|
644
|
+
const response = this._authorizationNotifier.response;
|
|
645
|
+
const codeVerifier = (request.internal) ? request.internal['code_verifier'] : undefined;
|
|
646
|
+
const res = await this.tokenClient.getByAuthorizationCode(request.redirectUri, response.code, codeVerifier);
|
|
647
|
+
this._store.setDefaultIdentityId(null);
|
|
648
|
+
await this._store.setToken(res);
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
const res = await this._store.getToken();
|
|
652
|
+
if (!res && startLogin) {
|
|
653
|
+
await this.login();
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
this._initialized = true;
|
|
657
|
+
}
|
|
658
|
+
async loginWithSecret(provider, secret) {
|
|
659
|
+
this._store.removeToken();
|
|
660
|
+
const assertionToken = await this.getServicePrincipalAccessToken();
|
|
661
|
+
const scope = this.prepareScope(true, this.config?.requestedScopes);
|
|
662
|
+
const res = await this.tokenClient.getBySecret(provider, secret, assertionToken, scope);
|
|
663
|
+
this._store.setDefaultIdentityId(null);
|
|
664
|
+
await this._store.setToken(res);
|
|
665
|
+
}
|
|
666
|
+
async login() {
|
|
667
|
+
this._store.removeToken();
|
|
668
|
+
const config = await this.config.getConfiguration();
|
|
669
|
+
const request = this.prepareAuthorizationRequest();
|
|
670
|
+
if (this.appService.isNative) {
|
|
671
|
+
const listener = App.addListener('appUrlOpen', (data) => {
|
|
672
|
+
if (this.appService.platform === 'ios') {
|
|
673
|
+
Browser.close();
|
|
674
|
+
}
|
|
675
|
+
listener.remove();
|
|
676
|
+
const hash = this.getCodeHash(data.url);
|
|
677
|
+
if (hash) {
|
|
678
|
+
const targetUrl = window.location.origin + window.location.pathname + '#' + hash;
|
|
679
|
+
window.location.assign(targetUrl);
|
|
680
|
+
window.location.reload();
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
console.warn('Nucleus.Identity: Redirect url did not contain authorization code!', data);
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
this._authorizationHandler.performAuthorizationRequest(config, request);
|
|
688
|
+
}
|
|
689
|
+
async logout() {
|
|
690
|
+
this._store.removeToken();
|
|
691
|
+
const config = await this.config.getConfiguration();
|
|
692
|
+
const redirectUrl = this.config.redirectUrl;
|
|
693
|
+
const logoutUrl = config.endSessionEndpoint +
|
|
694
|
+
'?post_logout_redirect_uri=' +
|
|
695
|
+
encodeURI(redirectUrl);
|
|
696
|
+
if (this.appService.isNative) {
|
|
697
|
+
const listener = App.addListener('appUrlOpen', () => {
|
|
698
|
+
Device.getInfo().then((info) => {
|
|
699
|
+
if (info.platform === 'ios') {
|
|
700
|
+
Browser.close();
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
listener.remove();
|
|
704
|
+
});
|
|
705
|
+
Browser.open({ url: logoutUrl });
|
|
706
|
+
}
|
|
707
|
+
else {
|
|
708
|
+
window.location.assign(logoutUrl);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
async getAccessToken() {
|
|
712
|
+
if (!this._getTokenPromise) {
|
|
713
|
+
this._getTokenPromise = this.getAccessTokenInternal();
|
|
714
|
+
}
|
|
715
|
+
try {
|
|
716
|
+
return await this._getTokenPromise;
|
|
717
|
+
}
|
|
718
|
+
finally {
|
|
719
|
+
this._getTokenPromise = null;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
async getServicePrincipalAccessToken() {
|
|
723
|
+
if (!this._getServicePrincipalTokenPromise) {
|
|
724
|
+
this._getServicePrincipalTokenPromise =
|
|
725
|
+
this.getServicePrincipalAccessTokenInternal();
|
|
726
|
+
}
|
|
727
|
+
try {
|
|
728
|
+
return await this._getServicePrincipalTokenPromise;
|
|
729
|
+
}
|
|
730
|
+
finally {
|
|
731
|
+
this._getServicePrincipalTokenPromise = null;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
async loginServicePrincipal() {
|
|
735
|
+
const sp = await this._store.getServicePrincipal();
|
|
736
|
+
if (sp) {
|
|
737
|
+
const scope = this.prepareScope(false, this.config.servicePrincipalRequestedScopes);
|
|
738
|
+
const res = await this.tokenClient.getByClientCredentials(sp.id, sp.secret, scope);
|
|
739
|
+
await this._store.setToken(res, this._servicePrincipalTokenId);
|
|
740
|
+
return res;
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
throw Error('Service principal is not registered!');
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
async loginAsServicePrincipal() {
|
|
747
|
+
const token = await this._store.getToken(this._servicePrincipalTokenId);
|
|
748
|
+
if (!token) {
|
|
749
|
+
await this.loginServicePrincipal();
|
|
750
|
+
}
|
|
751
|
+
this._store.setDefaultIdentityId(this._servicePrincipalTokenId);
|
|
752
|
+
}
|
|
753
|
+
async getOtp(type, expiresIn = -1) {
|
|
754
|
+
let url = this.config.getServerUrl(`/otp/create?type=${type}`);
|
|
755
|
+
if (expiresIn > 0) {
|
|
756
|
+
url += `&expiresIn=${expiresIn}`;
|
|
757
|
+
}
|
|
758
|
+
return lastValueFrom(this.http.get(url));
|
|
759
|
+
}
|
|
760
|
+
async getOtpStatus(id) {
|
|
761
|
+
const url = this.config.getServerUrl(`/otp/status/${id}`);
|
|
762
|
+
return lastValueFrom(this.http.get(url));
|
|
763
|
+
}
|
|
764
|
+
getOtpUrl(redirectUrl, password) {
|
|
765
|
+
const encoded = encodeURIComponent(redirectUrl);
|
|
766
|
+
const url = `/otp/auth?otpValue=${password}&returnUrl=${encoded}`;
|
|
767
|
+
return this.config.getServerUrl(url);
|
|
768
|
+
}
|
|
769
|
+
async startServicePrincipalRegistration() {
|
|
770
|
+
const sp = await this._store.getServicePrincipal();
|
|
771
|
+
return await this.tokenClient.getRegistrationCode(sp?.id);
|
|
772
|
+
}
|
|
773
|
+
async completeServicePrincipalRegistration(deviceCode) {
|
|
774
|
+
const tokenRes = await this.waitForDeviceToken(deviceCode);
|
|
775
|
+
const regRes = await this.tokenClient.registerServicePrincipal(tokenRes.accessToken);
|
|
776
|
+
await this._store.setServicePrincipal({
|
|
777
|
+
id: regRes.clientId,
|
|
778
|
+
secret: regRes.clientSecret,
|
|
779
|
+
expiresAt: regRes.secretExpirationDate,
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
removeServicePrincipalRegistration() {
|
|
783
|
+
return this._store.removeServicePrincipal();
|
|
784
|
+
}
|
|
785
|
+
async getServicePrincipalRegistrationStatus() {
|
|
786
|
+
const sp = await this._store.getServicePrincipal();
|
|
787
|
+
return new ServicePrincipalRegistrationStatus(sp);
|
|
788
|
+
}
|
|
789
|
+
async startDeviceCodeLogin() {
|
|
790
|
+
const scope = this.prepareScope(true, this.config.requestedScopes);
|
|
791
|
+
return await this.tokenClient.getDeviceCode(scope);
|
|
792
|
+
}
|
|
793
|
+
async completeDeviceCodeLogin(deviceCode) {
|
|
794
|
+
const res = await this.waitForDeviceToken(deviceCode);
|
|
795
|
+
await this._store.setToken(res);
|
|
796
|
+
}
|
|
797
|
+
async waitForDeviceToken(deviceCode) {
|
|
798
|
+
let res = null;
|
|
799
|
+
do {
|
|
800
|
+
if (deviceCode.isExpired()) {
|
|
801
|
+
throw Error('Device code is expired!');
|
|
802
|
+
}
|
|
803
|
+
try {
|
|
804
|
+
res = await this.tokenClient.getByDeviceCode(deviceCode.deviceCode);
|
|
805
|
+
}
|
|
806
|
+
catch (error) {
|
|
807
|
+
if (error instanceof AppAuthError &&
|
|
808
|
+
error.message === 'authorization_pending') {
|
|
809
|
+
await this.delay(2000);
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
throw error;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
} while (!res);
|
|
816
|
+
return res;
|
|
817
|
+
}
|
|
818
|
+
prepareAuthorizationRequest() {
|
|
819
|
+
const redirectUri = this.config.redirectUrl;
|
|
820
|
+
const params = {
|
|
821
|
+
response_mode: 'fragment',
|
|
822
|
+
prompt: 'consent',
|
|
823
|
+
access_type: 'offline',
|
|
824
|
+
auth_provider_hint: this.config.authProviderHint,
|
|
825
|
+
};
|
|
826
|
+
return new AuthorizationRequest({
|
|
827
|
+
client_id: this.config.clientId,
|
|
828
|
+
redirect_uri: redirectUri,
|
|
829
|
+
response_type: AuthorizationRequest.RESPONSE_TYPE_CODE,
|
|
830
|
+
scope: this.prepareScope(true, this.config.requestedScopes),
|
|
831
|
+
extras: params,
|
|
832
|
+
}, this._crypto, true);
|
|
833
|
+
}
|
|
834
|
+
async getServicePrincipalAccessTokenInternal() {
|
|
835
|
+
let token = await this._store.getToken(this._servicePrincipalTokenId);
|
|
836
|
+
if (!token?.isValid()) {
|
|
837
|
+
token = await this.loginServicePrincipal();
|
|
838
|
+
}
|
|
839
|
+
return token?.accessToken;
|
|
840
|
+
}
|
|
841
|
+
async getAccessTokenInternal() {
|
|
842
|
+
let token = await this._store.getToken();
|
|
843
|
+
if (token && !token.isValid()) {
|
|
844
|
+
token = await this.loginWithRefreshToken(token);
|
|
845
|
+
}
|
|
846
|
+
return token?.accessToken ?? null;
|
|
847
|
+
}
|
|
848
|
+
async loginWithRefreshToken(token) {
|
|
849
|
+
if (!this._refreshTokenPromise) {
|
|
850
|
+
this._refreshTokenPromise = this.loginWithRefreshTokenInternal(token);
|
|
851
|
+
}
|
|
852
|
+
try {
|
|
853
|
+
return await this._refreshTokenPromise;
|
|
854
|
+
}
|
|
855
|
+
finally {
|
|
856
|
+
this._refreshTokenPromise = null;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
async loginWithRefreshTokenInternal(token) {
|
|
860
|
+
if (token?.refreshToken) {
|
|
861
|
+
try {
|
|
862
|
+
const res = await this.tokenClient.getByRefreshToken(token.refreshToken);
|
|
863
|
+
await this._store.setToken(res);
|
|
864
|
+
return res;
|
|
865
|
+
}
|
|
866
|
+
catch (err) {
|
|
867
|
+
console.warn('Nucleus.Identity: Failed to login with refresh token.', err);
|
|
868
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
869
|
+
if (err.message === 'invalid_grant') {
|
|
870
|
+
await this.logout();
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
else {
|
|
875
|
+
console.warn('Nucleus.Identity: There is no refresh token available.');
|
|
876
|
+
}
|
|
877
|
+
return null;
|
|
878
|
+
}
|
|
879
|
+
getCodeHash(url) {
|
|
880
|
+
const arr = url.split('#');
|
|
881
|
+
if (arr.length > 1) {
|
|
882
|
+
const hash = arr[1];
|
|
883
|
+
if (hash.startsWith('code=')) {
|
|
884
|
+
return hash;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return null;
|
|
888
|
+
}
|
|
889
|
+
handleLaunchCodeHash() {
|
|
890
|
+
if (this.appService.isNative && this.appService.launchUrl) {
|
|
891
|
+
const hash = this.getCodeHash(this.appService.launchUrl);
|
|
892
|
+
if (hash) {
|
|
893
|
+
console.log('Nucleus.Identity: Got authorization code from launchUrl, will assign it to hash.');
|
|
894
|
+
window.location.hash = '#' + hash;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
prepareScope(offlineAccess, aditionalScope) {
|
|
899
|
+
let scope = 'openid';
|
|
900
|
+
if (offlineAccess) {
|
|
901
|
+
scope += ' offline_access';
|
|
902
|
+
}
|
|
903
|
+
if (aditionalScope) {
|
|
904
|
+
scope += ' ' + aditionalScope;
|
|
905
|
+
}
|
|
906
|
+
return scope;
|
|
907
|
+
}
|
|
908
|
+
delay(miliseconds) {
|
|
909
|
+
return new Promise((resolve) => {
|
|
910
|
+
setTimeout(() => {
|
|
911
|
+
resolve();
|
|
912
|
+
}, miliseconds);
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityService, deps: [{ token: i1.NucleusAppService }, { token: LocationService }, { token: i1$1.HttpClient }, { token: OidcConfigurationService }, { token: TokenClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
916
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityService, providedIn: 'root' }); }
|
|
917
|
+
}
|
|
918
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityService, decorators: [{
|
|
919
|
+
type: Injectable,
|
|
920
|
+
args: [{
|
|
921
|
+
providedIn: 'root',
|
|
922
|
+
}]
|
|
960
923
|
}], ctorParameters: function () { return [{ type: i1.NucleusAppService }, { type: LocationService }, { type: i1$1.HttpClient }, { type: OidcConfigurationService }, { type: TokenClient }]; } });
|
|
961
924
|
|
|
962
|
-
class NucleusTokenInterceptor {
|
|
963
|
-
constructor(auth, config) {
|
|
964
|
-
this.auth = auth;
|
|
965
|
-
this.config = config;
|
|
966
|
-
this._authorityInterceptPaths = [
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
925
|
+
class NucleusTokenInterceptor {
|
|
926
|
+
constructor(auth, config) {
|
|
927
|
+
this.auth = auth;
|
|
928
|
+
this.config = config;
|
|
929
|
+
this._authorityInterceptPaths = [
|
|
930
|
+
'/api',
|
|
931
|
+
'/manage',
|
|
932
|
+
'/otp/create',
|
|
933
|
+
'/otp/status',
|
|
934
|
+
];
|
|
935
|
+
this._authority = config.authority.toLowerCase();
|
|
936
|
+
this._interceptUrls = config.httpInterceptorUrls?.map((x) => x.toLowerCase());
|
|
937
|
+
}
|
|
938
|
+
intercept(req, next) {
|
|
939
|
+
if (this.shouldIntercept(req.url)) {
|
|
940
|
+
const res = this.authorizeRequest(this.auth.getAccessToken(), req, next);
|
|
941
|
+
return this.checkUnauthorized(res);
|
|
942
|
+
}
|
|
943
|
+
return next.handle(req);
|
|
944
|
+
}
|
|
945
|
+
shouldIntercept(url) {
|
|
946
|
+
url = url.toLowerCase();
|
|
947
|
+
if (url.startsWith(this._authority)) {
|
|
948
|
+
const pathname = new URL(url).pathname;
|
|
949
|
+
return this._authorityInterceptPaths.some((x) => pathname.startsWith(x));
|
|
950
|
+
}
|
|
951
|
+
if (this._interceptUrls && this._interceptUrls.length > 0) {
|
|
952
|
+
return this.config.httpInterceptorUrls?.some((x) => url.startsWith(x)) ?? false;
|
|
953
|
+
}
|
|
954
|
+
return false;
|
|
955
|
+
}
|
|
956
|
+
authorizeRequest(getToken, req, next) {
|
|
957
|
+
return from(getToken).pipe(mergeMap((token) => {
|
|
958
|
+
if (token) {
|
|
959
|
+
const headers = req.headers.set('Authorization', `Bearer ${token}`);
|
|
960
|
+
req = req.clone({ headers });
|
|
961
|
+
}
|
|
962
|
+
return next.handle(req);
|
|
963
|
+
}));
|
|
964
|
+
}
|
|
965
|
+
checkUnauthorized(response) {
|
|
966
|
+
return response.pipe(catchError((err) => {
|
|
967
|
+
if (err instanceof HttpErrorResponse && err.status === 401) {
|
|
968
|
+
if (this.config.automaticLoginOnHttp401) {
|
|
969
|
+
this.auth.login();
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return throwError(err);
|
|
973
|
+
}));
|
|
974
|
+
}
|
|
975
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusTokenInterceptor, deps: [{ token: NucleusIdentityService }, { token: NucleusIdentityConfig }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
976
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusTokenInterceptor, providedIn: 'root' }); }
|
|
977
|
+
}
|
|
978
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusTokenInterceptor, decorators: [{
|
|
979
|
+
type: Injectable,
|
|
980
|
+
args: [{
|
|
981
|
+
providedIn: 'root',
|
|
982
|
+
}]
|
|
1015
983
|
}], ctorParameters: function () { return [{ type: NucleusIdentityService }, { type: NucleusIdentityConfig }]; } });
|
|
1016
984
|
|
|
1017
|
-
class NucleusIdentityModule {
|
|
1018
|
-
static forRoot(config) {
|
|
1019
|
-
return {
|
|
1020
|
-
ngModule: NucleusIdentityModule,
|
|
1021
|
-
providers: [
|
|
1022
|
-
{ provide: NucleusIdentityConfig, useValue: config },
|
|
1023
|
-
{
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
i0.ɵɵ
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
985
|
+
class NucleusIdentityModule {
|
|
986
|
+
static forRoot(config) {
|
|
987
|
+
return {
|
|
988
|
+
ngModule: NucleusIdentityModule,
|
|
989
|
+
providers: [
|
|
990
|
+
{ provide: NucleusIdentityConfig, useValue: config },
|
|
991
|
+
{
|
|
992
|
+
provide: HTTP_INTERCEPTORS,
|
|
993
|
+
useClass: NucleusTokenInterceptor,
|
|
994
|
+
multi: true,
|
|
995
|
+
},
|
|
996
|
+
],
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
1000
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityModule }); }
|
|
1001
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityModule }); }
|
|
1002
|
+
}
|
|
1003
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NucleusIdentityModule, decorators: [{
|
|
1004
|
+
type: NgModule,
|
|
1005
|
+
args: [{
|
|
1006
|
+
imports: [],
|
|
1007
|
+
declarations: [],
|
|
1008
|
+
exports: [],
|
|
1009
|
+
}]
|
|
1038
1010
|
}] });
|
|
1039
1011
|
|
|
1040
|
-
class OtpResponse {
|
|
1041
|
-
}
|
|
1042
|
-
class OtpStatus {
|
|
1043
|
-
}
|
|
1044
|
-
var OtpType;
|
|
1045
|
-
(function (OtpType) {
|
|
1046
|
-
OtpType[OtpType["SimpleNumbers"] = 0] = "SimpleNumbers";
|
|
1047
|
-
OtpType[OtpType["SimpleAlfanumeric"] = 1] = "SimpleAlfanumeric";
|
|
1048
|
-
OtpType[OtpType["Complex"] = 2] = "Complex";
|
|
1012
|
+
class OtpResponse {
|
|
1013
|
+
}
|
|
1014
|
+
class OtpStatus {
|
|
1015
|
+
}
|
|
1016
|
+
var OtpType;
|
|
1017
|
+
(function (OtpType) {
|
|
1018
|
+
OtpType[OtpType["SimpleNumbers"] = 0] = "SimpleNumbers";
|
|
1019
|
+
OtpType[OtpType["SimpleAlfanumeric"] = 1] = "SimpleAlfanumeric";
|
|
1020
|
+
OtpType[OtpType["Complex"] = 2] = "Complex";
|
|
1049
1021
|
})(OtpType || (OtpType = {}));
|
|
1050
1022
|
|
|
1051
|
-
|
|
1052
|
-
*
|
|
1053
|
-
*/
|
|
1054
|
-
|
|
1055
|
-
/**
|
|
1056
|
-
* Generated bundle index. Do not edit.
|
|
1023
|
+
/**
|
|
1024
|
+
* Generated bundle index. Do not edit.
|
|
1057
1025
|
*/
|
|
1058
1026
|
|
|
1059
|
-
export { DeviceCode,
|
|
1027
|
+
export { DeviceCode, NucleusIdentityConfig, NucleusIdentityModule, NucleusIdentityService, OtpResponse, OtpStatus, OtpType, ServicePrincipalRegistrationStatus };
|
|
1060
1028
|
//# sourceMappingURL=kolektor-nucleus-identity.mjs.map
|