oidc-spa 7.2.5 → 7.3.1
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/core/Oidc.d.ts +4 -1
- package/core/createOidc.js +65 -18
- package/core/createOidc.js.map +1 -1
- package/core/oidcClientTsUserToTokens.js +7 -2
- package/core/oidcClientTsUserToTokens.js.map +1 -1
- package/esm/core/Oidc.d.ts +4 -1
- package/esm/core/createOidc.js +65 -18
- package/esm/core/createOidc.js.map +1 -1
- package/esm/core/oidcClientTsUserToTokens.js +7 -2
- package/esm/core/oidcClientTsUserToTokens.js.map +1 -1
- package/esm/keycloak/keycloak-js/Keycloak.d.ts +5 -3
- package/esm/keycloak/keycloak-js/Keycloak.js +175 -184
- package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
- package/esm/keycloak/keycloak-js/types.d.ts +1 -3
- package/esm/mock/oidc.js +2 -1
- package/esm/mock/oidc.js.map +1 -1
- package/esm/tools/workerTimers.js +2 -5
- package/esm/tools/workerTimers.js.map +1 -1
- package/esm/vendor/frontend/oidc-client-ts.js +46 -8
- package/keycloak/keycloak-js/Keycloak.d.ts +5 -3
- package/keycloak/keycloak-js/Keycloak.js +175 -184
- package/keycloak/keycloak-js/Keycloak.js.map +1 -1
- package/keycloak/keycloak-js/types.d.ts +1 -3
- package/mock/oidc.js +2 -1
- package/mock/oidc.js.map +1 -1
- package/package.json +1 -1
- package/src/core/Oidc.ts +5 -1
- package/src/core/createOidc.ts +81 -16
- package/src/core/oidcClientTsUserToTokens.ts +7 -2
- package/src/keycloak/keycloak-js/Keycloak.ts +198 -232
- package/src/keycloak/keycloak-js/types.ts +1 -4
- package/src/mock/oidc.ts +2 -1
- package/src/tools/workerTimers.ts +2 -6
- package/tools/workerTimers.js +2 -5
- package/tools/workerTimers.js.map +1 -1
- package/vendor/frontend/oidc-client-ts.js +46 -8
|
@@ -25,21 +25,6 @@ type ConstructorParams = KeycloakServerConfig & {
|
|
|
25
25
|
homeUrl: string;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
type InternalState = {
|
|
29
|
-
constructorParams: ConstructorParams;
|
|
30
|
-
keycloakUtils: KeycloakUtils;
|
|
31
|
-
issuerUri: string;
|
|
32
|
-
dInitialized: Deferred<void>;
|
|
33
|
-
initOptions: KeycloakInitOptions | undefined;
|
|
34
|
-
oidc: Oidc<Record<string, unknown>> | undefined;
|
|
35
|
-
tokens: Oidc.Tokens<Record<string, unknown>> | undefined;
|
|
36
|
-
profile: KeycloakProfile | undefined;
|
|
37
|
-
userInfo: KeycloakUserInfo | undefined;
|
|
38
|
-
$onTokenExpired: StatefulEvt<(() => void) | undefined>;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const internalStateByInstance = new WeakMap<Keycloak, InternalState>();
|
|
42
|
-
|
|
43
28
|
/**
|
|
44
29
|
* This module provides a drop-in replacement for `keycloak-js`,
|
|
45
30
|
* designed for teams migrating to `oidc-spa` with minimal changes.
|
|
@@ -48,6 +33,19 @@ const internalStateByInstance = new WeakMap<Keycloak, InternalState>();
|
|
|
48
33
|
* it is a full alternative implementation aligned with the `keycloak-js` API.
|
|
49
34
|
*/
|
|
50
35
|
export class Keycloak {
|
|
36
|
+
readonly #state: {
|
|
37
|
+
constructorParams: ConstructorParams;
|
|
38
|
+
keycloakUtils: KeycloakUtils;
|
|
39
|
+
issuerUri: string;
|
|
40
|
+
dInitialized: Deferred<void>;
|
|
41
|
+
initOptions: KeycloakInitOptions | undefined;
|
|
42
|
+
oidc: Oidc<Record<string, unknown>> | undefined;
|
|
43
|
+
tokens: Oidc.Tokens<Record<string, unknown>> | undefined;
|
|
44
|
+
profile: KeycloakProfile | undefined;
|
|
45
|
+
userInfo: KeycloakUserInfo | undefined;
|
|
46
|
+
$onTokenExpired: StatefulEvt<(() => void) | undefined>;
|
|
47
|
+
};
|
|
48
|
+
|
|
51
49
|
/**
|
|
52
50
|
* Creates a new Keycloak client instance.
|
|
53
51
|
* @param config A configuration object or path to a JSON config file.
|
|
@@ -59,7 +57,7 @@ export class Keycloak {
|
|
|
59
57
|
constructor(params: ConstructorParams) {
|
|
60
58
|
const issuerUri = `${params.url.replace(/\/$/, "")}/realms/${params.realm}`;
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
this.#state = {
|
|
63
61
|
constructorParams: params,
|
|
64
62
|
dInitialized: new Deferred(),
|
|
65
63
|
initOptions: undefined,
|
|
@@ -70,7 +68,7 @@ export class Keycloak {
|
|
|
70
68
|
profile: undefined,
|
|
71
69
|
userInfo: undefined,
|
|
72
70
|
$onTokenExpired: createStatefulEvt(() => undefined)
|
|
73
|
-
}
|
|
71
|
+
};
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
/**
|
|
@@ -81,23 +79,19 @@ export class Keycloak {
|
|
|
81
79
|
async init(initOptions: KeycloakInitOptions = {}): Promise<boolean> {
|
|
82
80
|
const { onLoad = "check-sso", redirectUri, enableLogging, scope, locale } = initOptions;
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
assert(internalState !== undefined);
|
|
87
|
-
|
|
88
|
-
if (internalState.initOptions !== undefined) {
|
|
89
|
-
if (JSON.stringify(internalState.initOptions) !== JSON.stringify(initOptions)) {
|
|
82
|
+
if (this.#state.initOptions !== undefined) {
|
|
83
|
+
if (JSON.stringify(this.#state.initOptions) !== JSON.stringify(initOptions)) {
|
|
90
84
|
throw new Error("Can't call init() multiple time with different params");
|
|
91
85
|
}
|
|
92
|
-
await
|
|
93
|
-
const { oidc } =
|
|
86
|
+
await this.#state.dInitialized.pr;
|
|
87
|
+
const { oidc } = this.#state;
|
|
94
88
|
assert(oidc !== undefined);
|
|
95
89
|
return oidc.isUserLoggedIn;
|
|
96
90
|
}
|
|
97
91
|
|
|
98
|
-
|
|
92
|
+
this.#state.initOptions = initOptions;
|
|
99
93
|
|
|
100
|
-
const { constructorParams, issuerUri } =
|
|
94
|
+
const { constructorParams, issuerUri } = this.#state;
|
|
101
95
|
|
|
102
96
|
const autoLogin = onLoad === "login-required";
|
|
103
97
|
|
|
@@ -106,7 +100,7 @@ export class Keycloak {
|
|
|
106
100
|
const oidcOrError = await createOidc({
|
|
107
101
|
homeUrl: constructorParams.homeUrl,
|
|
108
102
|
issuerUri,
|
|
109
|
-
clientId:
|
|
103
|
+
clientId: this.#state.constructorParams.clientId,
|
|
110
104
|
autoLogin,
|
|
111
105
|
postLoginRedirectUrl: redirectUri,
|
|
112
106
|
debugLogs: enableLogging,
|
|
@@ -142,101 +136,123 @@ export class Keycloak {
|
|
|
142
136
|
|
|
143
137
|
const oidc = oidcOrError;
|
|
144
138
|
|
|
145
|
-
internalState.oidc = oidc;
|
|
146
|
-
|
|
147
139
|
if (oidc.isUserLoggedIn) {
|
|
148
|
-
|
|
149
|
-
const tokens = await oidc.getTokens();
|
|
140
|
+
const tokens = await oidc.getTokens();
|
|
150
141
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
142
|
+
const onNewToken = (tokens_new: Oidc.Tokens<Record<string, unknown>>) => {
|
|
143
|
+
this.#state.tokens = tokens_new;
|
|
144
|
+
this.onAuthRefreshSuccess?.();
|
|
145
|
+
};
|
|
155
146
|
|
|
156
|
-
|
|
147
|
+
onNewToken(tokens);
|
|
157
148
|
|
|
158
|
-
|
|
149
|
+
oidc.subscribeToTokensChange(onNewToken);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.#state.oidc = oidc;
|
|
153
|
+
this.#state.dInitialized.resolve();
|
|
154
|
+
|
|
155
|
+
this.onReady?.(oidc.isUserLoggedIn);
|
|
156
|
+
|
|
157
|
+
onAuthSuccess_call: {
|
|
158
|
+
if (!oidc.isUserLoggedIn) {
|
|
159
|
+
break onAuthSuccess_call;
|
|
159
160
|
}
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
this.onAuthSuccess?.();
|
|
163
|
+
}
|
|
163
164
|
|
|
164
|
-
|
|
165
|
+
onAuthError_call: {
|
|
166
|
+
if (oidc.isUserLoggedIn) {
|
|
167
|
+
break onAuthError_call;
|
|
168
|
+
}
|
|
165
169
|
|
|
166
|
-
|
|
167
|
-
|
|
170
|
+
if (oidc.initializationError === undefined) {
|
|
171
|
+
break onAuthError_call;
|
|
172
|
+
}
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
174
|
+
this.onAuthError?.({
|
|
175
|
+
error: oidc.initializationError.name,
|
|
176
|
+
error_description: oidc.initializationError.message
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
onActionUpdate_call: {
|
|
181
|
+
if (!oidc.isUserLoggedIn) {
|
|
182
|
+
break onActionUpdate_call;
|
|
183
|
+
}
|
|
172
184
|
|
|
173
|
-
|
|
185
|
+
if (this.onActionUpdate === undefined) {
|
|
186
|
+
break onActionUpdate_call;
|
|
187
|
+
}
|
|
174
188
|
|
|
175
|
-
|
|
176
|
-
if (timer !== undefined) {
|
|
177
|
-
workerTimers.clearTimeout(timer);
|
|
178
|
-
}
|
|
189
|
+
const { backFromAuthServer } = oidc;
|
|
179
190
|
|
|
180
|
-
|
|
181
|
-
|
|
191
|
+
if (backFromAuthServer === undefined) {
|
|
192
|
+
break onActionUpdate_call;
|
|
193
|
+
}
|
|
182
194
|
|
|
183
|
-
|
|
184
|
-
onTokenExpired.call(this);
|
|
185
|
-
}, Math.max(tokens.accessTokenExpirationTime - Date.now() - 3_000, 0));
|
|
186
|
-
};
|
|
195
|
+
const status = backFromAuthServer.result.kc_action_status;
|
|
187
196
|
|
|
188
|
-
|
|
197
|
+
if (!isAmong(["success", "cancelled", "error"], status)) {
|
|
198
|
+
break onActionUpdate_call;
|
|
199
|
+
}
|
|
189
200
|
|
|
190
|
-
|
|
201
|
+
const action = backFromAuthServer.extraQueryParams.kc_action;
|
|
191
202
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
workerTimers.clearTimeout(timer);
|
|
195
|
-
}
|
|
196
|
-
unsubscribe();
|
|
197
|
-
};
|
|
198
|
-
});
|
|
203
|
+
if (action === undefined) {
|
|
204
|
+
break onActionUpdate_call;
|
|
199
205
|
}
|
|
200
206
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
break onActionUpdate_call;
|
|
204
|
-
}
|
|
207
|
+
this.onActionUpdate(status, action);
|
|
208
|
+
}
|
|
205
209
|
|
|
206
|
-
|
|
210
|
+
schedule_onTokenExpired_call: {
|
|
211
|
+
if (!oidc.isUserLoggedIn) {
|
|
212
|
+
break schedule_onTokenExpired_call;
|
|
213
|
+
}
|
|
207
214
|
|
|
208
|
-
|
|
209
|
-
break onActionUpdate_call;
|
|
210
|
-
}
|
|
215
|
+
const { $onTokenExpired } = this.#state;
|
|
211
216
|
|
|
212
|
-
|
|
217
|
+
let clear: (() => void) | undefined = undefined;
|
|
213
218
|
|
|
214
|
-
|
|
215
|
-
|
|
219
|
+
const next = (onTokenExpired: (() => void) | undefined) => {
|
|
220
|
+
clear?.();
|
|
221
|
+
|
|
222
|
+
if (onTokenExpired === undefined) {
|
|
223
|
+
return;
|
|
216
224
|
}
|
|
217
225
|
|
|
218
|
-
|
|
226
|
+
let timer: ReturnType<typeof workerTimers.setTimeout> | undefined = undefined;
|
|
219
227
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
const onNewToken = () => {
|
|
229
|
+
if (timer !== undefined) {
|
|
230
|
+
workerTimers.clearTimeout(timer);
|
|
231
|
+
}
|
|
223
232
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
233
|
+
const { tokens } = this.#state;
|
|
234
|
+
assert(tokens !== undefined);
|
|
227
235
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
});
|
|
233
|
-
}
|
|
236
|
+
timer = workerTimers.setTimeout(() => {
|
|
237
|
+
onTokenExpired.call(this);
|
|
238
|
+
}, Math.max(tokens.accessTokenExpirationTime - tokens.getServerDateNow() - 3_000, 0));
|
|
239
|
+
};
|
|
234
240
|
|
|
235
|
-
|
|
241
|
+
onNewToken();
|
|
236
242
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
243
|
+
const { unsubscribe } = oidc.subscribeToTokensChange(onNewToken);
|
|
244
|
+
|
|
245
|
+
clear = () => {
|
|
246
|
+
if (timer !== undefined) {
|
|
247
|
+
workerTimers.clearTimeout(timer);
|
|
248
|
+
}
|
|
249
|
+
unsubscribe();
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
next($onTokenExpired.current);
|
|
254
|
+
|
|
255
|
+
$onTokenExpired.subscribe(next);
|
|
240
256
|
}
|
|
241
257
|
|
|
242
258
|
return oidc.isUserLoggedIn;
|
|
@@ -250,11 +266,7 @@ export class Keycloak {
|
|
|
250
266
|
return false;
|
|
251
267
|
}
|
|
252
268
|
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
assert(internalState !== undefined);
|
|
256
|
-
|
|
257
|
-
const { oidc } = internalState;
|
|
269
|
+
const { oidc } = this.#state;
|
|
258
270
|
|
|
259
271
|
assert(oidc !== undefined);
|
|
260
272
|
|
|
@@ -269,11 +281,7 @@ export class Keycloak {
|
|
|
269
281
|
return undefined;
|
|
270
282
|
}
|
|
271
283
|
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
assert(internalState !== undefined);
|
|
275
|
-
|
|
276
|
-
const { oidc, tokens } = internalState;
|
|
284
|
+
const { oidc, tokens } = this.#state;
|
|
277
285
|
|
|
278
286
|
assert(oidc !== undefined);
|
|
279
287
|
|
|
@@ -320,17 +328,13 @@ export class Keycloak {
|
|
|
320
328
|
return undefined;
|
|
321
329
|
}
|
|
322
330
|
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
assert(internalState !== undefined);
|
|
326
|
-
|
|
327
|
-
const { oidc, tokens } = internalState;
|
|
331
|
+
const { oidc, tokens } = this.#state;
|
|
328
332
|
|
|
329
333
|
assert(oidc !== undefined);
|
|
330
334
|
|
|
331
335
|
if (!oidc.isUserLoggedIn) {
|
|
332
336
|
console.warn(
|
|
333
|
-
"Trying to read keycloak.realAccess when keycloak.
|
|
337
|
+
"Trying to read keycloak.realAccess when keycloak.authenticated is false is a logical error in your application"
|
|
334
338
|
);
|
|
335
339
|
return undefined;
|
|
336
340
|
}
|
|
@@ -349,11 +353,7 @@ export class Keycloak {
|
|
|
349
353
|
return undefined;
|
|
350
354
|
}
|
|
351
355
|
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
assert(internalState !== undefined);
|
|
355
|
-
|
|
356
|
-
const { oidc, tokens } = internalState;
|
|
356
|
+
const { oidc, tokens } = this.#state;
|
|
357
357
|
|
|
358
358
|
assert(oidc !== undefined);
|
|
359
359
|
|
|
@@ -375,21 +375,17 @@ export class Keycloak {
|
|
|
375
375
|
* requests to services.
|
|
376
376
|
*/
|
|
377
377
|
get token(): string | undefined {
|
|
378
|
-
const internalState = internalStateByInstance.get(this);
|
|
379
|
-
|
|
380
|
-
assert(internalState !== undefined);
|
|
381
|
-
|
|
382
378
|
if (!this.didInitialize) {
|
|
383
|
-
return
|
|
379
|
+
return this.#state.initOptions?.token;
|
|
384
380
|
}
|
|
385
381
|
|
|
386
|
-
const { oidc, tokens } =
|
|
382
|
+
const { oidc, tokens } = this.#state;
|
|
387
383
|
|
|
388
384
|
assert(oidc !== undefined);
|
|
389
385
|
|
|
390
386
|
if (!oidc.isUserLoggedIn) {
|
|
391
387
|
console.warn(
|
|
392
|
-
"Trying to read keycloak.token when keycloak.
|
|
388
|
+
"Trying to read keycloak.token when keycloak.authenticated is false is a logical error in your application"
|
|
393
389
|
);
|
|
394
390
|
return undefined;
|
|
395
391
|
}
|
|
@@ -403,12 +399,8 @@ export class Keycloak {
|
|
|
403
399
|
* The parsed token as a JavaScript object.
|
|
404
400
|
*/
|
|
405
401
|
get tokenParsed(): KeycloakTokenParsed | undefined {
|
|
406
|
-
const internalState = internalStateByInstance.get(this);
|
|
407
|
-
|
|
408
|
-
assert(internalState !== undefined);
|
|
409
|
-
|
|
410
402
|
if (!this.didInitialize) {
|
|
411
|
-
const { token } =
|
|
403
|
+
const { token } = this.#state.initOptions ?? {};
|
|
412
404
|
|
|
413
405
|
if (token === undefined) {
|
|
414
406
|
return undefined;
|
|
@@ -417,13 +409,13 @@ export class Keycloak {
|
|
|
417
409
|
return decodeJwt(token) as KeycloakTokenParsed;
|
|
418
410
|
}
|
|
419
411
|
|
|
420
|
-
const { oidc, tokens } =
|
|
412
|
+
const { oidc, tokens } = this.#state;
|
|
421
413
|
|
|
422
414
|
assert(oidc !== undefined);
|
|
423
415
|
|
|
424
416
|
if (!oidc.isUserLoggedIn) {
|
|
425
417
|
console.warn(
|
|
426
|
-
"Trying to read keycloak.
|
|
418
|
+
"Trying to read keycloak.tokenParsed when keycloak.authenticated is false is a logical error in your application"
|
|
427
419
|
);
|
|
428
420
|
return undefined;
|
|
429
421
|
}
|
|
@@ -437,21 +429,17 @@ export class Keycloak {
|
|
|
437
429
|
* The base64 encoded refresh token that can be used to retrieve a new token.
|
|
438
430
|
*/
|
|
439
431
|
get refreshToken(): string | undefined {
|
|
440
|
-
const internalState = internalStateByInstance.get(this);
|
|
441
|
-
|
|
442
|
-
assert(internalState !== undefined);
|
|
443
|
-
|
|
444
432
|
if (!this.didInitialize) {
|
|
445
|
-
return
|
|
433
|
+
return this.#state.initOptions?.refreshToken;
|
|
446
434
|
}
|
|
447
435
|
|
|
448
|
-
const { oidc, tokens } =
|
|
436
|
+
const { oidc, tokens } = this.#state;
|
|
449
437
|
|
|
450
438
|
assert(oidc !== undefined);
|
|
451
439
|
|
|
452
440
|
if (!oidc.isUserLoggedIn) {
|
|
453
441
|
console.warn(
|
|
454
|
-
"Trying to read keycloak.
|
|
442
|
+
"Trying to read keycloak.refreshToken when keycloak.authenticated is false is a logical error in your application"
|
|
455
443
|
);
|
|
456
444
|
return undefined;
|
|
457
445
|
}
|
|
@@ -465,12 +453,8 @@ export class Keycloak {
|
|
|
465
453
|
* The parsed refresh token as a JavaScript object.
|
|
466
454
|
*/
|
|
467
455
|
get refreshTokenParsed(): KeycloakTokenParsed | undefined {
|
|
468
|
-
const internalState = internalStateByInstance.get(this);
|
|
469
|
-
|
|
470
|
-
assert(internalState !== undefined);
|
|
471
|
-
|
|
472
456
|
if (!this.didInitialize) {
|
|
473
|
-
const { refreshToken } =
|
|
457
|
+
const { refreshToken } = this.#state.initOptions ?? {};
|
|
474
458
|
|
|
475
459
|
if (refreshToken === undefined) {
|
|
476
460
|
return undefined;
|
|
@@ -479,13 +463,13 @@ export class Keycloak {
|
|
|
479
463
|
return decodeJwt(refreshToken) as KeycloakTokenParsed;
|
|
480
464
|
}
|
|
481
465
|
|
|
482
|
-
const { oidc, tokens } =
|
|
466
|
+
const { oidc, tokens } = this.#state;
|
|
483
467
|
|
|
484
468
|
assert(oidc !== undefined);
|
|
485
469
|
|
|
486
470
|
if (!oidc.isUserLoggedIn) {
|
|
487
471
|
console.warn(
|
|
488
|
-
"Trying to read keycloak.
|
|
472
|
+
"Trying to read keycloak.refreshTokenParsed when keycloak.authenticated is false is a logical error in your application"
|
|
489
473
|
);
|
|
490
474
|
return undefined;
|
|
491
475
|
}
|
|
@@ -503,21 +487,17 @@ export class Keycloak {
|
|
|
503
487
|
* The base64 encoded ID token.
|
|
504
488
|
*/
|
|
505
489
|
get idToken(): string | undefined {
|
|
506
|
-
const internalState = internalStateByInstance.get(this);
|
|
507
|
-
|
|
508
|
-
assert(internalState !== undefined);
|
|
509
|
-
|
|
510
490
|
if (!this.didInitialize) {
|
|
511
|
-
return
|
|
491
|
+
return this.#state.initOptions?.idToken;
|
|
512
492
|
}
|
|
513
493
|
|
|
514
|
-
const { oidc, tokens } =
|
|
494
|
+
const { oidc, tokens } = this.#state;
|
|
515
495
|
|
|
516
496
|
assert(oidc !== undefined);
|
|
517
497
|
|
|
518
498
|
if (!oidc.isUserLoggedIn) {
|
|
519
499
|
console.warn(
|
|
520
|
-
"Trying to read keycloak.
|
|
500
|
+
"Trying to read keycloak.idToken when keycloak.authenticated is false is a logical error in your application"
|
|
521
501
|
);
|
|
522
502
|
return undefined;
|
|
523
503
|
}
|
|
@@ -531,12 +511,8 @@ export class Keycloak {
|
|
|
531
511
|
* The parsed id token as a JavaScript object.
|
|
532
512
|
*/
|
|
533
513
|
get idTokenParsed(): KeycloakTokenParsed | undefined {
|
|
534
|
-
const internalState = internalStateByInstance.get(this);
|
|
535
|
-
|
|
536
|
-
assert(internalState !== undefined);
|
|
537
|
-
|
|
538
514
|
if (!this.didInitialize) {
|
|
539
|
-
const { idToken } =
|
|
515
|
+
const { idToken } = this.#state.initOptions ?? {};
|
|
540
516
|
|
|
541
517
|
if (idToken === undefined) {
|
|
542
518
|
return undefined;
|
|
@@ -545,13 +521,13 @@ export class Keycloak {
|
|
|
545
521
|
return decodeJwt(idToken) as KeycloakTokenParsed;
|
|
546
522
|
}
|
|
547
523
|
|
|
548
|
-
const { oidc, tokens } =
|
|
524
|
+
const { oidc, tokens } = this.#state;
|
|
549
525
|
|
|
550
526
|
assert(oidc !== undefined);
|
|
551
527
|
|
|
552
528
|
if (!oidc.isUserLoggedIn) {
|
|
553
529
|
console.warn(
|
|
554
|
-
"Trying to read keycloak.
|
|
530
|
+
"Trying to read keycloak.idTokenParsed when keycloak.authenticated is false is a logical error in your application"
|
|
555
531
|
);
|
|
556
532
|
return undefined;
|
|
557
533
|
}
|
|
@@ -566,28 +542,46 @@ export class Keycloak {
|
|
|
566
542
|
* The estimated time difference between the browser time and the Keycloak
|
|
567
543
|
* server in seconds. This value is just an estimation, but is accurate
|
|
568
544
|
* enough when determining if a token is expired or not.
|
|
569
|
-
*
|
|
570
|
-
* NOTE oidc-spa: Not supported.
|
|
571
545
|
*/
|
|
572
|
-
timeSkew
|
|
546
|
+
get timeSkew(): number | null {
|
|
547
|
+
if (!this.didInitialize) {
|
|
548
|
+
const { timeSkew } = this.#state.initOptions ?? {};
|
|
549
|
+
|
|
550
|
+
if (timeSkew === undefined) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return timeSkew;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
const { oidc, tokens } = this.#state;
|
|
558
|
+
|
|
559
|
+
assert(oidc !== undefined);
|
|
560
|
+
|
|
561
|
+
if (!oidc.isUserLoggedIn) {
|
|
562
|
+
console.warn(
|
|
563
|
+
"Trying to read keycloak.timeSkew when keycloak.authenticated is false is a logical error in your application"
|
|
564
|
+
);
|
|
565
|
+
return null;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
assert(tokens !== undefined);
|
|
569
|
+
|
|
570
|
+
return Math.ceil((tokens.getServerDateNow() - Date.now()) / 1000);
|
|
571
|
+
}
|
|
573
572
|
|
|
574
573
|
/**
|
|
575
574
|
* Whether the instance has been initialized by calling `.init()`.
|
|
576
575
|
*/
|
|
577
576
|
get didInitialize(): boolean {
|
|
578
|
-
|
|
579
|
-
assert(internalState !== undefined);
|
|
580
|
-
return internalState.oidc !== undefined;
|
|
577
|
+
return this.#state.oidc !== undefined;
|
|
581
578
|
}
|
|
582
579
|
|
|
583
580
|
/**
|
|
584
581
|
* @private Undocumented.
|
|
585
582
|
*/
|
|
586
583
|
get loginRequired(): boolean {
|
|
587
|
-
const
|
|
588
|
-
assert(internalState !== undefined);
|
|
589
|
-
|
|
590
|
-
const { initOptions } = internalState;
|
|
584
|
+
const { initOptions } = this.#state;
|
|
591
585
|
|
|
592
586
|
if (initOptions === undefined) {
|
|
593
587
|
return false;
|
|
@@ -600,11 +594,9 @@ export class Keycloak {
|
|
|
600
594
|
* @private Undocumented.
|
|
601
595
|
*/
|
|
602
596
|
get authServerUrl(): string {
|
|
603
|
-
const internalState = internalStateByInstance.get(this);
|
|
604
|
-
assert(internalState !== undefined);
|
|
605
597
|
const {
|
|
606
598
|
keycloakUtils: { issuerUriParsed }
|
|
607
|
-
} =
|
|
599
|
+
} = this.#state;
|
|
608
600
|
|
|
609
601
|
return `${issuerUriParsed.origin}${issuerUriParsed.kcHttpRelativePath}`;
|
|
610
602
|
}
|
|
@@ -613,11 +605,9 @@ export class Keycloak {
|
|
|
613
605
|
* @private Undocumented.
|
|
614
606
|
*/
|
|
615
607
|
get realm(): string {
|
|
616
|
-
const internalState = internalStateByInstance.get(this);
|
|
617
|
-
assert(internalState !== undefined);
|
|
618
608
|
const {
|
|
619
609
|
keycloakUtils: { issuerUriParsed }
|
|
620
|
-
} =
|
|
610
|
+
} = this.#state;
|
|
621
611
|
|
|
622
612
|
return issuerUriParsed.realm;
|
|
623
613
|
}
|
|
@@ -626,9 +616,7 @@ export class Keycloak {
|
|
|
626
616
|
* @private Undocumented.
|
|
627
617
|
*/
|
|
628
618
|
get clientId(): string {
|
|
629
|
-
const
|
|
630
|
-
assert(internalState !== undefined);
|
|
631
|
-
const { constructorParams } = internalState;
|
|
619
|
+
const { constructorParams } = this.#state;
|
|
632
620
|
return constructorParams.clientId;
|
|
633
621
|
}
|
|
634
622
|
|
|
@@ -636,9 +624,7 @@ export class Keycloak {
|
|
|
636
624
|
* @private Undocumented.
|
|
637
625
|
*/
|
|
638
626
|
get redirectUri(): string | undefined {
|
|
639
|
-
const
|
|
640
|
-
assert(internalState !== undefined);
|
|
641
|
-
const { initOptions } = internalState;
|
|
627
|
+
const { initOptions } = this.#state;
|
|
642
628
|
if (initOptions === undefined) {
|
|
643
629
|
return undefined;
|
|
644
630
|
}
|
|
@@ -653,9 +639,7 @@ export class Keycloak {
|
|
|
653
639
|
return undefined;
|
|
654
640
|
}
|
|
655
641
|
|
|
656
|
-
const
|
|
657
|
-
assert(internalState !== undefined);
|
|
658
|
-
const { oidc, tokens } = internalState;
|
|
642
|
+
const { oidc, tokens } = this.#state;
|
|
659
643
|
|
|
660
644
|
assert(oidc !== undefined);
|
|
661
645
|
|
|
@@ -679,9 +663,7 @@ export class Keycloak {
|
|
|
679
663
|
* @private Undocumented.
|
|
680
664
|
*/
|
|
681
665
|
get profile(): KeycloakProfile | undefined {
|
|
682
|
-
const
|
|
683
|
-
assert(internalState !== undefined);
|
|
684
|
-
const { profile } = internalState;
|
|
666
|
+
const { profile } = this.#state;
|
|
685
667
|
return profile;
|
|
686
668
|
}
|
|
687
669
|
|
|
@@ -689,9 +671,7 @@ export class Keycloak {
|
|
|
689
671
|
* @private Undocumented.
|
|
690
672
|
*/
|
|
691
673
|
get userInfo(): KeycloakUserInfo | undefined {
|
|
692
|
-
const
|
|
693
|
-
assert(internalState !== undefined);
|
|
694
|
-
const { userInfo } = internalState;
|
|
674
|
+
const { userInfo } = this.#state;
|
|
695
675
|
return userInfo;
|
|
696
676
|
}
|
|
697
677
|
|
|
@@ -737,15 +717,11 @@ export class Keycloak {
|
|
|
737
717
|
* obtain a new access token.
|
|
738
718
|
*/
|
|
739
719
|
set onTokenExpired(value: (() => void) | undefined) {
|
|
740
|
-
const
|
|
741
|
-
assert(internalState !== undefined);
|
|
742
|
-
const { $onTokenExpired } = internalState;
|
|
720
|
+
const { $onTokenExpired } = this.#state;
|
|
743
721
|
$onTokenExpired.current = value;
|
|
744
722
|
}
|
|
745
723
|
get onTokenExpired() {
|
|
746
|
-
const
|
|
747
|
-
assert(internalState !== undefined);
|
|
748
|
-
const { $onTokenExpired } = internalState;
|
|
724
|
+
const { $onTokenExpired } = this.#state;
|
|
749
725
|
return $onTokenExpired.current;
|
|
750
726
|
}
|
|
751
727
|
|
|
@@ -774,14 +750,11 @@ export class Keycloak {
|
|
|
774
750
|
doesCurrentHrefRequiresAuth
|
|
775
751
|
} = options ?? {};
|
|
776
752
|
|
|
777
|
-
const internalState = internalStateByInstance.get(this);
|
|
778
|
-
assert(internalState !== undefined);
|
|
779
|
-
|
|
780
753
|
if (!this.didInitialize) {
|
|
781
|
-
await
|
|
754
|
+
await this.#state.dInitialized.pr;
|
|
782
755
|
}
|
|
783
756
|
|
|
784
|
-
const { oidc, keycloakUtils } =
|
|
757
|
+
const { oidc, keycloakUtils } = this.#state;
|
|
785
758
|
|
|
786
759
|
assert(oidc !== undefined);
|
|
787
760
|
|
|
@@ -836,15 +809,11 @@ export class Keycloak {
|
|
|
836
809
|
* @param options Logout options.
|
|
837
810
|
*/
|
|
838
811
|
async logout(options?: KeycloakLogoutOptions): Promise<never> {
|
|
839
|
-
const internalState = internalStateByInstance.get(this);
|
|
840
|
-
|
|
841
|
-
assert(internalState !== undefined);
|
|
842
|
-
|
|
843
812
|
if (!this.didInitialize) {
|
|
844
|
-
await
|
|
813
|
+
await this.#state.dInitialized.pr;
|
|
845
814
|
}
|
|
846
815
|
|
|
847
|
-
const { oidc, initOptions } =
|
|
816
|
+
const { oidc, initOptions } = this.#state;
|
|
848
817
|
|
|
849
818
|
assert(oidc !== undefined);
|
|
850
819
|
assert(initOptions !== undefined);
|
|
@@ -922,11 +891,7 @@ export class Keycloak {
|
|
|
922
891
|
createAccountUrl(options?: KeycloakAccountOptions & { locale?: string }): string {
|
|
923
892
|
const { locale, redirectUri } = options ?? {};
|
|
924
893
|
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
assert(internalState !== undefined);
|
|
928
|
-
|
|
929
|
-
const { keycloakUtils } = internalState;
|
|
894
|
+
const { keycloakUtils } = this.#state;
|
|
930
895
|
|
|
931
896
|
return keycloakUtils.getAccountUrl({
|
|
932
897
|
clientId: this.clientId,
|
|
@@ -941,9 +906,6 @@ export class Keycloak {
|
|
|
941
906
|
* @param minValidity If not specified, `0` is used.
|
|
942
907
|
*/
|
|
943
908
|
isTokenExpired(minValidity: number = 0): boolean {
|
|
944
|
-
const internalState = internalStateByInstance.get(this);
|
|
945
|
-
assert(internalState !== undefined);
|
|
946
|
-
|
|
947
909
|
let accessTokenExpirationTime: number;
|
|
948
910
|
|
|
949
911
|
if (!this.didInitialize) {
|
|
@@ -958,7 +920,7 @@ export class Keycloak {
|
|
|
958
920
|
|
|
959
921
|
accessTokenExpirationTime = time;
|
|
960
922
|
} else {
|
|
961
|
-
const { tokens } =
|
|
923
|
+
const { tokens } = this.#state;
|
|
962
924
|
assert(tokens !== undefined);
|
|
963
925
|
|
|
964
926
|
accessTokenExpirationTime = tokens.accessTokenExpirationTime;
|
|
@@ -991,15 +953,11 @@ export class Keycloak {
|
|
|
991
953
|
* });
|
|
992
954
|
*/
|
|
993
955
|
async updateToken(minValidity: number = 5): Promise<boolean> {
|
|
994
|
-
const internalState = internalStateByInstance.get(this);
|
|
995
|
-
|
|
996
|
-
assert(internalState !== undefined);
|
|
997
|
-
|
|
998
956
|
if (!this.didInitialize) {
|
|
999
|
-
await
|
|
957
|
+
await this.#state.dInitialized.pr;
|
|
1000
958
|
}
|
|
1001
959
|
|
|
1002
|
-
const { oidc } =
|
|
960
|
+
const { oidc } = this.#state;
|
|
1003
961
|
|
|
1004
962
|
assert(oidc !== undefined);
|
|
1005
963
|
|
|
@@ -1055,14 +1013,11 @@ export class Keycloak {
|
|
|
1055
1013
|
* @returns A promise to set functions to be invoked on success or error.
|
|
1056
1014
|
*/
|
|
1057
1015
|
async loadUserProfile(): Promise<KeycloakProfile> {
|
|
1058
|
-
const internalState = internalStateByInstance.get(this);
|
|
1059
|
-
assert(internalState !== undefined);
|
|
1060
|
-
|
|
1061
1016
|
if (!this.didInitialize) {
|
|
1062
|
-
await
|
|
1017
|
+
await this.#state.dInitialized.pr;
|
|
1063
1018
|
}
|
|
1064
1019
|
|
|
1065
|
-
const { oidc, keycloakUtils } =
|
|
1020
|
+
const { oidc, keycloakUtils } = this.#state;
|
|
1066
1021
|
|
|
1067
1022
|
assert(oidc !== undefined);
|
|
1068
1023
|
|
|
@@ -1070,21 +1025,18 @@ export class Keycloak {
|
|
|
1070
1025
|
|
|
1071
1026
|
const { accessToken } = await oidc.getTokens();
|
|
1072
1027
|
|
|
1073
|
-
return (
|
|
1028
|
+
return (this.#state.profile = await keycloakUtils.fetchUserProfile({ accessToken }));
|
|
1074
1029
|
}
|
|
1075
1030
|
|
|
1076
1031
|
/**
|
|
1077
1032
|
* @private Undocumented.
|
|
1078
1033
|
*/
|
|
1079
1034
|
async loadUserInfo(): Promise<KeycloakUserInfo> {
|
|
1080
|
-
const internalState = internalStateByInstance.get(this);
|
|
1081
|
-
assert(internalState !== undefined);
|
|
1082
|
-
|
|
1083
1035
|
if (!this.didInitialize) {
|
|
1084
|
-
await
|
|
1036
|
+
await this.#state.dInitialized.pr;
|
|
1085
1037
|
}
|
|
1086
1038
|
|
|
1087
|
-
const { oidc, keycloakUtils } =
|
|
1039
|
+
const { oidc, keycloakUtils } = this.#state;
|
|
1088
1040
|
|
|
1089
1041
|
assert(oidc !== undefined);
|
|
1090
1042
|
|
|
@@ -1092,6 +1044,20 @@ export class Keycloak {
|
|
|
1092
1044
|
|
|
1093
1045
|
const { accessToken } = await oidc.getTokens();
|
|
1094
1046
|
|
|
1095
|
-
return (
|
|
1047
|
+
return (this.#state.userInfo = await keycloakUtils.fetchUserInfo({ accessToken }));
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
/** Get the underlying oidc-spa instance */
|
|
1051
|
+
get oidc(): Oidc<Record<string, unknown>> {
|
|
1052
|
+
assert(
|
|
1053
|
+
this.didInitialize,
|
|
1054
|
+
"Cannot get keycloak.oidc before the init() method was called and have resolved."
|
|
1055
|
+
);
|
|
1056
|
+
|
|
1057
|
+
const { oidc } = this.#state;
|
|
1058
|
+
|
|
1059
|
+
assert(oidc !== undefined);
|
|
1060
|
+
|
|
1061
|
+
return oidc;
|
|
1096
1062
|
}
|
|
1097
1063
|
}
|