oidc-spa 8.2.0 → 8.2.2
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/AuthResponse.d.ts +0 -5
- package/core/AuthResponse.js +0 -25
- package/core/AuthResponse.js.map +1 -1
- package/core/OidcMetadata.d.ts +5 -0
- package/core/OidcMetadata.js +56 -0
- package/core/OidcMetadata.js.map +1 -1
- package/core/createOidc.d.ts +4 -3
- package/core/createOidc.js +229 -197
- package/core/createOidc.js.map +1 -1
- package/core/diagnostic.d.ts +0 -1
- package/core/diagnostic.js +18 -5
- package/core/diagnostic.js.map +1 -1
- package/core/instancesThatCantUseIframes.d.ts +2 -0
- package/core/instancesThatCantUseIframes.js +20 -0
- package/core/instancesThatCantUseIframes.js.map +1 -0
- package/core/loginOrGoToAuthServer.d.ts +1 -1
- package/core/loginOrGoToAuthServer.js +4 -16
- package/core/loginOrGoToAuthServer.js.map +1 -1
- package/core/loginSilent.d.ts +1 -2
- package/core/loginSilent.js +3 -21
- package/core/loginSilent.js.map +1 -1
- package/core/persistedAuthState.d.ts +1 -0
- package/core/persistedAuthState.js +14 -4
- package/core/persistedAuthState.js.map +1 -1
- package/esm/core/AuthResponse.d.ts +0 -5
- package/esm/core/AuthResponse.js +0 -23
- package/esm/core/AuthResponse.js.map +1 -1
- package/esm/core/OidcMetadata.d.ts +5 -0
- package/esm/core/OidcMetadata.js +54 -0
- package/esm/core/OidcMetadata.js.map +1 -1
- package/esm/core/createOidc.d.ts +4 -3
- package/esm/core/createOidc.js +230 -198
- package/esm/core/createOidc.js.map +1 -1
- package/esm/core/diagnostic.d.ts +0 -1
- package/esm/core/diagnostic.js +15 -1
- package/esm/core/diagnostic.js.map +1 -1
- package/esm/core/instancesThatCantUseIframes.d.ts +2 -0
- package/esm/core/instancesThatCantUseIframes.js +16 -0
- package/esm/core/instancesThatCantUseIframes.js.map +1 -0
- package/esm/core/loginOrGoToAuthServer.d.ts +1 -1
- package/esm/core/loginOrGoToAuthServer.js +4 -16
- package/esm/core/loginOrGoToAuthServer.js.map +1 -1
- package/esm/core/loginSilent.d.ts +1 -2
- package/esm/core/loginSilent.js +3 -21
- package/esm/core/loginSilent.js.map +1 -1
- package/esm/core/persistedAuthState.d.ts +1 -0
- package/esm/core/persistedAuthState.js +14 -4
- package/esm/core/persistedAuthState.js.map +1 -1
- package/esm/keycloak/keycloakIssuerUriParsed.js +8 -1
- package/esm/keycloak/keycloakIssuerUriParsed.js.map +1 -1
- package/esm/tools/isLikelyDevServer.d.ts +1 -0
- package/esm/tools/isLikelyDevServer.js +14 -0
- package/esm/tools/isLikelyDevServer.js.map +1 -0
- package/esm/tools/{EphemeralSessionStorage.d.ts → lazySessionStorage.d.ts} +2 -4
- package/esm/tools/lazySessionStorage.js +81 -0
- package/esm/tools/lazySessionStorage.js.map +1 -0
- package/keycloak/keycloakIssuerUriParsed.js +8 -1
- package/keycloak/keycloakIssuerUriParsed.js.map +1 -1
- package/package.json +1 -1
- package/src/core/AuthResponse.ts +0 -36
- package/src/core/OidcMetadata.ts +75 -0
- package/src/core/createOidc.ts +277 -264
- package/src/core/diagnostic.ts +21 -2
- package/src/core/instancesThatCantUseIframes.ts +24 -0
- package/src/core/loginOrGoToAuthServer.ts +5 -22
- package/src/core/loginSilent.ts +4 -27
- package/src/core/persistedAuthState.ts +27 -5
- package/src/keycloak/keycloakIssuerUriParsed.ts +10 -1
- package/src/tools/isLikelyDevServer.ts +17 -0
- package/src/tools/lazySessionStorage.ts +119 -0
- package/src/vite-plugin/manageOptimizedDeps.ts +2 -0
- package/tools/isLikelyDevServer.d.ts +1 -0
- package/tools/isLikelyDevServer.js +17 -0
- package/tools/isLikelyDevServer.js.map +1 -0
- package/tools/{EphemeralSessionStorage.d.ts → lazySessionStorage.d.ts} +2 -4
- package/tools/lazySessionStorage.js +84 -0
- package/tools/lazySessionStorage.js.map +1 -0
- package/vite-plugin/manageOptimizedDeps.js +1 -0
- package/vite-plugin/manageOptimizedDeps.js.map +1 -1
- package/esm/tools/EphemeralSessionStorage.js +0 -143
- package/esm/tools/EphemeralSessionStorage.js.map +0 -1
- package/src/tools/EphemeralSessionStorage.ts +0 -225
- package/tools/EphemeralSessionStorage.js +0 -146
- package/tools/EphemeralSessionStorage.js.map +0 -1
package/src/core/createOidc.ts
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
type User as OidcClientTsUser,
|
|
5
5
|
InMemoryWebStorage
|
|
6
6
|
} from "../vendor/frontend/oidc-client-ts";
|
|
7
|
-
import type
|
|
7
|
+
import { type OidcMetadata, fetchOidcMetadata } from "./OidcMetadata";
|
|
8
8
|
import { assert, is, type Equals } from "../tools/tsafe/assert";
|
|
9
9
|
import { id } from "../tools/tsafe/id";
|
|
10
10
|
import { setTimeout, clearTimeout } from "../tools/workerTimers";
|
|
@@ -25,12 +25,7 @@ import { notifyOtherTabsOfLogin, getPrOtherTabLogin } from "./loginPropagationTo
|
|
|
25
25
|
import { getConfigId } from "./configId";
|
|
26
26
|
import { oidcClientTsUserToTokens } from "./oidcClientTsUserToTokens";
|
|
27
27
|
import { loginSilent } from "./loginSilent";
|
|
28
|
-
import {
|
|
29
|
-
authResponseToUrl,
|
|
30
|
-
getPersistedRedirectAuthResponses,
|
|
31
|
-
setPersistedRedirectAuthResponses,
|
|
32
|
-
type AuthResponse
|
|
33
|
-
} from "./AuthResponse";
|
|
28
|
+
import { authResponseToUrl, type AuthResponse } from "./AuthResponse";
|
|
34
29
|
import { getRootRelativeOriginalLocationHref, getRedirectAuthResponse } from "./earlyInit";
|
|
35
30
|
import { getPersistedAuthState, persistAuthState } from "./persistedAuthState";
|
|
36
31
|
import type { Oidc } from "./Oidc";
|
|
@@ -40,7 +35,7 @@ import {
|
|
|
40
35
|
createLoginOrGoToAuthServer,
|
|
41
36
|
getPrSafelyRestoredFromBfCacheAfterLoginBackNavigationOrInitializationError
|
|
42
37
|
} from "./loginOrGoToAuthServer";
|
|
43
|
-
import {
|
|
38
|
+
import { createLazySessionStorage } from "../tools/lazySessionStorage";
|
|
44
39
|
import {
|
|
45
40
|
startLoginOrRefreshProcess,
|
|
46
41
|
waitForAllOtherOngoingLoginOrRefreshProcessesToComplete
|
|
@@ -49,10 +44,14 @@ import { createGetIsNewBrowserSession } from "./isNewBrowserSession";
|
|
|
49
44
|
import { getIsOnline } from "../tools/getIsOnline";
|
|
50
45
|
import { isKeycloak } from "../keycloak/isKeycloak";
|
|
51
46
|
import { INFINITY_TIME } from "../tools/INFINITY_TIME";
|
|
52
|
-
import type { WELL_KNOWN_PATH } from "./diagnostic";
|
|
53
|
-
import { getIsValidRemoteJson } from "../tools/getIsValidRemoteJson";
|
|
54
47
|
import { prShouldLoadApp } from "./prShouldLoadApp";
|
|
55
48
|
import { getBASE_URL } from "./BASE_URL";
|
|
49
|
+
import { getIsLikelyDevServer } from "../tools/isLikelyDevServer";
|
|
50
|
+
import { createObjectThatThrowsIfAccessed } from "../tools/createObjectThatThrowsIfAccessed";
|
|
51
|
+
import {
|
|
52
|
+
evtIsThereMoreThanOneInstanceThatCantUserIframes,
|
|
53
|
+
notifyNewInstanceThatCantUseIframes
|
|
54
|
+
} from "./instancesThatCantUseIframes";
|
|
56
55
|
|
|
57
56
|
// NOTE: Replaced at build time
|
|
58
57
|
const VERSION = "{{OIDC_SPA_VERSION}}";
|
|
@@ -108,6 +107,8 @@ export type ParamsOfCreateOidc<
|
|
|
108
107
|
*/
|
|
109
108
|
extraTokenParams?: Record<string, string | undefined> | (() => Record<string, string | undefined>);
|
|
110
109
|
/**
|
|
110
|
+
* @deprecated: Use login({ redirectUrl: "..." }) instead.
|
|
111
|
+
*
|
|
111
112
|
* Usage discouraged, it's here because we don't want to assume too much on your
|
|
112
113
|
* usecase but I can't think of a scenario where you would want anything
|
|
113
114
|
* other than the current page.
|
|
@@ -208,24 +209,9 @@ export type ParamsOfCreateOidc<
|
|
|
208
209
|
|
|
209
210
|
const globalContext = {
|
|
210
211
|
prOidcByConfigId: new Map<string, Promise<Oidc<any>>>(),
|
|
211
|
-
hasLogoutBeenCalled: id<boolean>(false)
|
|
212
|
-
evtRequestToPersistTokens: createEvt<{ configIdOfInstancePostingTheRequest: string }>()
|
|
212
|
+
hasLogoutBeenCalled: id<boolean>(false)
|
|
213
213
|
};
|
|
214
214
|
|
|
215
|
-
globalContext.evtRequestToPersistTokens.subscribe(() => {
|
|
216
|
-
const { authResponse } = getRedirectAuthResponse();
|
|
217
|
-
|
|
218
|
-
if (authResponse === undefined) {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const { authResponses } = getPersistedRedirectAuthResponses();
|
|
223
|
-
|
|
224
|
-
setPersistedRedirectAuthResponses({
|
|
225
|
-
authResponses: [...authResponses, authResponse]
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
215
|
/** @see: https://docs.oidc-spa.dev/v/v8/usage */
|
|
230
216
|
export async function createOidc<
|
|
231
217
|
DecodedIdToken extends Record<string, unknown> = Oidc.Tokens.DecodedIdToken_OidcCoreSpec,
|
|
@@ -242,7 +228,7 @@ export async function createOidc<
|
|
|
242
228
|
}
|
|
243
229
|
}
|
|
244
230
|
|
|
245
|
-
const { issuerUri: issuerUri_params, clientId,
|
|
231
|
+
const { issuerUri: issuerUri_params, clientId, debugLogs, ...rest } = params;
|
|
246
232
|
|
|
247
233
|
const issuerUri = toFullyQualifiedUrl({
|
|
248
234
|
urlish: issuerUri_params,
|
|
@@ -298,7 +284,6 @@ export async function createOidc<
|
|
|
298
284
|
const oidc = await createOidc_nonMemoized(rest, {
|
|
299
285
|
issuerUri,
|
|
300
286
|
clientId,
|
|
301
|
-
scopes,
|
|
302
287
|
configId,
|
|
303
288
|
log
|
|
304
289
|
});
|
|
@@ -312,14 +297,10 @@ export async function createOidc_nonMemoized<
|
|
|
312
297
|
DecodedIdToken extends Record<string, unknown>,
|
|
313
298
|
AutoLogin extends boolean
|
|
314
299
|
>(
|
|
315
|
-
params: Omit<
|
|
316
|
-
ParamsOfCreateOidc<DecodedIdToken, AutoLogin>,
|
|
317
|
-
"issuerUri" | "clientId" | "scopes" | "debugLogs"
|
|
318
|
-
>,
|
|
300
|
+
params: Omit<ParamsOfCreateOidc<DecodedIdToken, AutoLogin>, "issuerUri" | "clientId" | "debugLogs">,
|
|
319
301
|
preProcessedParams: {
|
|
320
302
|
issuerUri: string;
|
|
321
303
|
clientId: string;
|
|
322
|
-
scopes: string[];
|
|
323
304
|
configId: string;
|
|
324
305
|
log: typeof console.log | undefined;
|
|
325
306
|
}
|
|
@@ -357,12 +338,13 @@ export async function createOidc_nonMemoized<
|
|
|
357
338
|
__unsafe_clientSecret,
|
|
358
339
|
__unsafe_useIdTokenAsAccessToken = false,
|
|
359
340
|
__metadata,
|
|
360
|
-
noIframe = false
|
|
341
|
+
noIframe = false,
|
|
342
|
+
scopes = ["openid", "profile"]
|
|
361
343
|
} = params;
|
|
362
344
|
|
|
363
345
|
const BASE_URL_params = params.BASE_URL ?? params.homeUrl;
|
|
364
346
|
|
|
365
|
-
const { issuerUri, clientId,
|
|
347
|
+
const { issuerUri, clientId, configId, log } = preProcessedParams;
|
|
366
348
|
|
|
367
349
|
const getExtraQueryParams = (() => {
|
|
368
350
|
if (extraQueryParamsOrGetter === undefined) {
|
|
@@ -422,8 +404,7 @@ export async function createOidc_nonMemoized<
|
|
|
422
404
|
issuerUri,
|
|
423
405
|
clientId,
|
|
424
406
|
scopes,
|
|
425
|
-
|
|
426
|
-
homeUrlAndRedirectUri
|
|
407
|
+
oidcRedirectUri: homeUrlAndRedirectUri
|
|
427
408
|
},
|
|
428
409
|
null,
|
|
429
410
|
2
|
|
@@ -432,92 +413,212 @@ export async function createOidc_nonMemoized<
|
|
|
432
413
|
|
|
433
414
|
const stateUrlParamValue_instance = generateStateUrlParamValue();
|
|
434
415
|
|
|
416
|
+
const oidcMetadata = __metadata ?? (await fetchOidcMetadata({ issuerUri }));
|
|
417
|
+
|
|
435
418
|
const canUseIframe = (() => {
|
|
436
419
|
if (noIframe) {
|
|
437
420
|
return false;
|
|
438
421
|
}
|
|
439
422
|
|
|
440
423
|
third_party_cookies: {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
url1: window.location.origin,
|
|
444
|
-
url2: issuerUri
|
|
445
|
-
}) === false;
|
|
446
|
-
|
|
447
|
-
if (!isOidcServerThirdPartyRelativeToApp) {
|
|
448
|
-
break third_party_cookies;
|
|
424
|
+
if (oidcMetadata === undefined) {
|
|
425
|
+
return false;
|
|
449
426
|
}
|
|
450
427
|
|
|
451
|
-
const
|
|
452
|
-
const ua = navigator.userAgent;
|
|
453
|
-
const vendor = navigator.vendor;
|
|
428
|
+
const { authorization_endpoint } = oidcMetadata;
|
|
454
429
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
430
|
+
assert(
|
|
431
|
+
authorization_endpoint !== undefined,
|
|
432
|
+
"Missing authorization_endpoint on the provided __metadata"
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
const isOidcServerThirdPartyRelativeToApp = !getHaveSharedParentDomain({
|
|
436
|
+
url1: window.location.origin,
|
|
437
|
+
// TODO: No, here we should test against the authorization endpoint!
|
|
438
|
+
url2: authorization_endpoint
|
|
439
|
+
});
|
|
459
440
|
|
|
460
|
-
if (
|
|
441
|
+
if (!isOidcServerThirdPartyRelativeToApp) {
|
|
461
442
|
break third_party_cookies;
|
|
462
443
|
}
|
|
463
444
|
|
|
464
|
-
|
|
465
|
-
[
|
|
466
|
-
"Can't use iframe because your auth server is on a third party domain relative",
|
|
467
|
-
"to the domain of your app and third party cookies are blocked by navigators."
|
|
468
|
-
].join(" ")
|
|
469
|
-
);
|
|
445
|
+
const isLikelyDevServer = getIsLikelyDevServer();
|
|
470
446
|
|
|
471
|
-
|
|
472
|
-
}
|
|
447
|
+
const domain_auth = new URL(authorization_endpoint).origin.split("//")[1];
|
|
473
448
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
449
|
+
assert(domain_auth !== undefined, "33921384");
|
|
450
|
+
|
|
451
|
+
const domain_here = window.location.origin.split("//")[1];
|
|
452
|
+
|
|
453
|
+
let isWellKnownProviderDomain = false;
|
|
454
|
+
let isIp = false;
|
|
477
455
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
authority: issuerUri,
|
|
483
|
-
client_id: clientId,
|
|
484
|
-
redirect_uri: homeUrlAndRedirectUri,
|
|
485
|
-
silent_redirect_uri: homeUrlAndRedirectUri,
|
|
486
|
-
post_logout_redirect_uri: homeUrlAndRedirectUri,
|
|
487
|
-
response_mode: isKeycloak({ issuerUri }) ? "fragment" : "query",
|
|
488
|
-
response_type: "code",
|
|
489
|
-
scope: Array.from(new Set(["openid", ...scopes])).join(" "),
|
|
490
|
-
automaticSilentRenew: false,
|
|
491
|
-
userStore: new WebStorageStateStore({
|
|
492
|
-
store: (() => {
|
|
493
|
-
if (canUseIframe) {
|
|
494
|
-
isUserStoreInMemoryOnly = true;
|
|
495
|
-
return new InMemoryWebStorage();
|
|
456
|
+
const suggestedDeployments = (() => {
|
|
457
|
+
if (/^(?:\d{1,3}\.){3}\d{1,3}$|^\[?[A-Fa-f0-9:]+\]?$/.test(domain_auth)) {
|
|
458
|
+
isIp = true;
|
|
459
|
+
return [];
|
|
496
460
|
}
|
|
497
461
|
|
|
498
|
-
|
|
462
|
+
const baseDomain = (() => {
|
|
463
|
+
const segments = domain_auth.split(".");
|
|
499
464
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
465
|
+
if (segments.length >= 3) {
|
|
466
|
+
segments.shift();
|
|
467
|
+
}
|
|
468
|
+
return segments.join(".");
|
|
469
|
+
})();
|
|
503
470
|
|
|
504
|
-
|
|
471
|
+
{
|
|
472
|
+
const baseDomain_low = baseDomain.toLowerCase();
|
|
505
473
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
474
|
+
if (
|
|
475
|
+
baseDomain_low.includes("auth0") ||
|
|
476
|
+
baseDomain_low.includes("clerk") ||
|
|
477
|
+
baseDomain_low.includes("microsoft") ||
|
|
478
|
+
baseDomain_low.includes("okta") ||
|
|
479
|
+
baseDomain_low.includes("aws")
|
|
480
|
+
) {
|
|
481
|
+
isWellKnownProviderDomain = true;
|
|
482
|
+
return [];
|
|
509
483
|
}
|
|
484
|
+
}
|
|
510
485
|
|
|
511
|
-
|
|
512
|
-
});
|
|
486
|
+
const baseUrl = new URL(homeUrlAndRedirectUri).pathname;
|
|
513
487
|
|
|
514
|
-
return
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
488
|
+
return [
|
|
489
|
+
`myapp.${baseDomain}`,
|
|
490
|
+
baseDomain === domain_auth ? undefined : baseDomain,
|
|
491
|
+
`${baseDomain}/${baseUrl === "/" ? "dashboard" : baseUrl}`
|
|
492
|
+
].filter(x => x !== undefined);
|
|
493
|
+
})();
|
|
494
|
+
|
|
495
|
+
if (isLikelyDevServer) {
|
|
496
|
+
log?.(
|
|
497
|
+
[
|
|
498
|
+
"Detected localhost environment.",
|
|
499
|
+
"\nWhen reloading while logged in, you will briefly see",
|
|
500
|
+
"some URL params appear in the address bar.",
|
|
501
|
+
"\nThis happens because session restore via iframe is disabled,",
|
|
502
|
+
"the browser treats your auth server as a third party.",
|
|
503
|
+
`\nAuth server: ${domain_auth}`,
|
|
504
|
+
`\nApp domain: ${domain_here}`,
|
|
505
|
+
...(() => {
|
|
506
|
+
if (isIp) {
|
|
507
|
+
return [];
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (isWellKnownProviderDomain) {
|
|
511
|
+
return [
|
|
512
|
+
"\nYou seem to be using a well-known auth provider.",
|
|
513
|
+
"Check your provider's docs, some allow configuring",
|
|
514
|
+
`a your custom domain at least for the authorization endpoint.`,
|
|
515
|
+
"\nIf configured, oidc-spa will restore sessions silently",
|
|
516
|
+
"and improve the user experience."
|
|
517
|
+
];
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return [
|
|
521
|
+
"\nOnce deployed under the same root domain as your auth server,",
|
|
522
|
+
"oidc-spa will use iframes to restore sessions silently.",
|
|
523
|
+
"\nSuggested deployments:",
|
|
524
|
+
...suggestedDeployments.map(d => `\n • ${d}`)
|
|
525
|
+
];
|
|
526
|
+
})(),
|
|
527
|
+
"\n\nMore info:",
|
|
528
|
+
"https://docs.oidc-spa.dev/v/v8/resources/end-of-third-party-cookies#when-are-cookies-considered-third-party"
|
|
529
|
+
].join(" ")
|
|
530
|
+
);
|
|
531
|
+
} else {
|
|
532
|
+
log?.(
|
|
533
|
+
[
|
|
534
|
+
"Silent session restore via iframe is disabled.",
|
|
535
|
+
`\nAuth server: ${domain_auth}`,
|
|
536
|
+
`App domain: ${domain_here}`,
|
|
537
|
+
"\nThey do not share a common root domain.",
|
|
538
|
+
...(() => {
|
|
539
|
+
if (isIp) {
|
|
540
|
+
return [];
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (isWellKnownProviderDomain) {
|
|
544
|
+
return [
|
|
545
|
+
"\nYou seem to be using a well-known auth provider.",
|
|
546
|
+
"Check if you can configure a custom auth domain.",
|
|
547
|
+
"\nIf so, oidc-spa can restore sessions silently",
|
|
548
|
+
"and improve the user experience."
|
|
549
|
+
];
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return [
|
|
553
|
+
"\nTo improve the experience, here are some examples of deployment for your app:",
|
|
554
|
+
...suggestedDeployments.map(d => `\n • ${d}`)
|
|
555
|
+
];
|
|
556
|
+
})(),
|
|
557
|
+
"\nMore info:",
|
|
558
|
+
"https://docs.oidc-spa.dev/v/v8/resources/end-of-third-party-cookies#when-are-cookies-considered-third-party"
|
|
559
|
+
].join(" ")
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return true;
|
|
567
|
+
})();
|
|
568
|
+
|
|
569
|
+
notifyNewInstanceThatCantUseIframes();
|
|
570
|
+
|
|
571
|
+
if (evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
|
|
572
|
+
log?.(
|
|
573
|
+
[
|
|
574
|
+
"More than one oidc instance can't use iframe",
|
|
575
|
+
"falling back to persisting tokens in session storage"
|
|
576
|
+
].join(" ")
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const oidcClientTsUserManager =
|
|
581
|
+
oidcMetadata === undefined
|
|
582
|
+
? createObjectThatThrowsIfAccessed<OidcClientTsUserManager>({
|
|
583
|
+
debugMessage: "oidc-spa: Wrong assertion 43943"
|
|
584
|
+
})
|
|
585
|
+
: new OidcClientTsUserManager({
|
|
586
|
+
stateUrlParamValue: stateUrlParamValue_instance,
|
|
587
|
+
authority: issuerUri,
|
|
588
|
+
client_id: clientId,
|
|
589
|
+
redirect_uri: homeUrlAndRedirectUri,
|
|
590
|
+
silent_redirect_uri: homeUrlAndRedirectUri,
|
|
591
|
+
post_logout_redirect_uri: homeUrlAndRedirectUri,
|
|
592
|
+
response_mode: isKeycloak({ issuerUri }) ? "fragment" : "query",
|
|
593
|
+
response_type: "code",
|
|
594
|
+
scope: Array.from(new Set(["openid", ...scopes])).join(" "),
|
|
595
|
+
automaticSilentRenew: false,
|
|
596
|
+
userStore: new WebStorageStateStore({
|
|
597
|
+
store: (() => {
|
|
598
|
+
if (canUseIframe) {
|
|
599
|
+
return new InMemoryWebStorage();
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const storage = createLazySessionStorage();
|
|
603
|
+
|
|
604
|
+
if (evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
|
|
605
|
+
storage.persistCurrentStateAndSubsequentChanges();
|
|
606
|
+
} else {
|
|
607
|
+
evtIsThereMoreThanOneInstanceThatCantUserIframes.subscribe(() => {
|
|
608
|
+
storage.persistCurrentStateAndSubsequentChanges();
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
return storage;
|
|
613
|
+
})()
|
|
614
|
+
}),
|
|
615
|
+
stateStore: new WebStorageStateStore({
|
|
616
|
+
store: localStorage,
|
|
617
|
+
prefix: STATE_STORE_KEY_PREFIX
|
|
618
|
+
}),
|
|
619
|
+
client_secret: __unsafe_clientSecret,
|
|
620
|
+
metadata: oidcMetadata
|
|
621
|
+
});
|
|
521
622
|
|
|
522
623
|
const evtInitializationOutcomeUserNotLoggedIn = createEvt<void>();
|
|
523
624
|
|
|
@@ -547,75 +648,75 @@ export async function createOidc_nonMemoized<
|
|
|
547
648
|
backFromAuthServer: Oidc.LoggedIn["backFromAuthServer"]; // Undefined is silent signin
|
|
548
649
|
}
|
|
549
650
|
> => {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
const { authResponse, clearAuthResponse } = getRedirectAuthResponse();
|
|
651
|
+
if (oidcMetadata === undefined) {
|
|
652
|
+
return (
|
|
653
|
+
await import("./diagnostic")
|
|
654
|
+
).createWellKnownOidcConfigurationEndpointUnreachableInitializationError({
|
|
655
|
+
issuerUri
|
|
656
|
+
});
|
|
657
|
+
}
|
|
558
658
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
659
|
+
restore_from_session_storage: {
|
|
660
|
+
if (canUseIframe) {
|
|
661
|
+
break restore_from_session_storage;
|
|
662
|
+
}
|
|
562
663
|
|
|
563
|
-
|
|
664
|
+
if (!evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
|
|
665
|
+
break restore_from_session_storage;
|
|
666
|
+
}
|
|
564
667
|
|
|
565
|
-
|
|
566
|
-
clearAuthResponse();
|
|
567
|
-
break from_memory;
|
|
568
|
-
}
|
|
668
|
+
let oidcClientTsUser: OidcClientTsUser | null;
|
|
569
669
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
670
|
+
try {
|
|
671
|
+
oidcClientTsUser = await oidcClientTsUserManager.getUser();
|
|
672
|
+
} catch {
|
|
673
|
+
// NOTE: Not sure if it can throw, but let's be safe.
|
|
674
|
+
oidcClientTsUser = null;
|
|
675
|
+
try {
|
|
676
|
+
await oidcClientTsUserManager.removeUser();
|
|
677
|
+
} catch {}
|
|
678
|
+
}
|
|
573
679
|
|
|
574
|
-
|
|
680
|
+
if (oidcClientTsUser === null) {
|
|
681
|
+
break restore_from_session_storage;
|
|
682
|
+
}
|
|
575
683
|
|
|
576
|
-
|
|
684
|
+
log?.("Session was restored from session storage");
|
|
577
685
|
|
|
578
|
-
|
|
686
|
+
return {
|
|
687
|
+
oidcClientTsUser,
|
|
688
|
+
backFromAuthServer: undefined
|
|
689
|
+
};
|
|
690
|
+
}
|
|
579
691
|
|
|
580
|
-
|
|
581
|
-
|
|
692
|
+
handle_redirect_auth_response: {
|
|
693
|
+
let stateDataAndAuthResponse:
|
|
694
|
+
| { stateData: StateData.Redirect; authResponse: AuthResponse }
|
|
695
|
+
| undefined = undefined;
|
|
582
696
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
// the authResponse in memory had the chance to be processed.
|
|
586
|
-
// This can only happen if:
|
|
587
|
-
// 1) There are multiple oidc instances in the App.
|
|
588
|
-
// 2) They are instantiated in a non deterministic order.
|
|
589
|
-
// 3) We can't use iframe
|
|
590
|
-
// We practically never persist the auth response and do it only in session
|
|
591
|
-
// an ephemeral session storage, when we know it's gonna be required.
|
|
592
|
-
{
|
|
593
|
-
const { authResponses } = getPersistedRedirectAuthResponses();
|
|
697
|
+
{
|
|
698
|
+
const { authResponse, clearAuthResponse } = getRedirectAuthResponse();
|
|
594
699
|
|
|
595
|
-
|
|
596
|
-
|
|
700
|
+
if (authResponse === undefined) {
|
|
701
|
+
break handle_redirect_auth_response;
|
|
702
|
+
}
|
|
597
703
|
|
|
598
|
-
|
|
599
|
-
continue;
|
|
600
|
-
}
|
|
704
|
+
const stateData = getStateData({ stateUrlParamValue: authResponse.state });
|
|
601
705
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
706
|
+
if (stateData === undefined) {
|
|
707
|
+
clearAuthResponse();
|
|
708
|
+
break handle_redirect_auth_response;
|
|
709
|
+
}
|
|
605
710
|
|
|
606
|
-
|
|
711
|
+
if (stateData.configId !== configId) {
|
|
712
|
+
break handle_redirect_auth_response;
|
|
713
|
+
}
|
|
607
714
|
|
|
608
|
-
|
|
609
|
-
authResponses: authResponses.filter(
|
|
610
|
-
authResponse_i => authResponse_i !== authResponse
|
|
611
|
-
)
|
|
612
|
-
});
|
|
715
|
+
assert(stateData.context === "redirect", "3229492");
|
|
613
716
|
|
|
614
|
-
|
|
717
|
+
clearAuthResponse();
|
|
615
718
|
|
|
616
|
-
|
|
617
|
-
}
|
|
618
|
-
}
|
|
719
|
+
stateDataAndAuthResponse = { stateData, authResponse };
|
|
619
720
|
}
|
|
620
721
|
|
|
621
722
|
if (stateDataAndAuthResponse === undefined) {
|
|
@@ -728,37 +829,6 @@ export async function createOidc_nonMemoized<
|
|
|
728
829
|
}
|
|
729
830
|
}
|
|
730
831
|
|
|
731
|
-
// NOTE: We almost never persist tokens, we have to only to support edge case
|
|
732
|
-
// of multiple oidc instance in a single App with no iframe support.
|
|
733
|
-
restore_from_session_storage: {
|
|
734
|
-
if (isUserStoreInMemoryOnly) {
|
|
735
|
-
break restore_from_session_storage;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
let oidcClientTsUser: OidcClientTsUser | null;
|
|
739
|
-
|
|
740
|
-
try {
|
|
741
|
-
oidcClientTsUser = await oidcClientTsUserManager.getUser();
|
|
742
|
-
} catch {
|
|
743
|
-
// NOTE: Not sure if it can throw, but let's be safe.
|
|
744
|
-
oidcClientTsUser = null;
|
|
745
|
-
try {
|
|
746
|
-
await oidcClientTsUserManager.removeUser();
|
|
747
|
-
} catch {}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
if (oidcClientTsUser === null) {
|
|
751
|
-
break restore_from_session_storage;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
log?.("Restored the auth from ephemeral session storage");
|
|
755
|
-
|
|
756
|
-
return {
|
|
757
|
-
oidcClientTsUser,
|
|
758
|
-
backFromAuthServer: undefined
|
|
759
|
-
};
|
|
760
|
-
}
|
|
761
|
-
|
|
762
832
|
silent_login_if_possible_and_auto_login: {
|
|
763
833
|
const persistedAuthState = getPersistedAuthState({ configId });
|
|
764
834
|
|
|
@@ -801,20 +871,6 @@ export async function createOidc_nonMemoized<
|
|
|
801
871
|
}
|
|
802
872
|
|
|
803
873
|
if (!canUseIframe) {
|
|
804
|
-
if (
|
|
805
|
-
!(await getIsValidRemoteJson(
|
|
806
|
-
`${issuerUri}${id<typeof WELL_KNOWN_PATH>(
|
|
807
|
-
"/.well-known/openid-configuration"
|
|
808
|
-
)}`
|
|
809
|
-
))
|
|
810
|
-
) {
|
|
811
|
-
return (
|
|
812
|
-
await import("./diagnostic")
|
|
813
|
-
).createWellKnownOidcConfigurationEndpointUnreachableInitializationError({
|
|
814
|
-
issuerUri
|
|
815
|
-
});
|
|
816
|
-
}
|
|
817
|
-
|
|
818
874
|
break actual_silent_signin;
|
|
819
875
|
}
|
|
820
876
|
|
|
@@ -835,26 +891,13 @@ export async function createOidc_nonMemoized<
|
|
|
835
891
|
|
|
836
892
|
assert(result_loginSilent.outcome !== "token refreshed using refresh token", "876995");
|
|
837
893
|
|
|
838
|
-
if (result_loginSilent.outcome === "
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
});
|
|
846
|
-
case "timeout":
|
|
847
|
-
return (await import("./diagnostic")).createIframeTimeoutInitializationError(
|
|
848
|
-
{
|
|
849
|
-
redirectUri: homeUrlAndRedirectUri,
|
|
850
|
-
clientId,
|
|
851
|
-
issuerUri,
|
|
852
|
-
noIframe
|
|
853
|
-
}
|
|
854
|
-
);
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
assert<Equals<typeof result_loginSilent.cause, never>>(false);
|
|
894
|
+
if (result_loginSilent.outcome === "timeout") {
|
|
895
|
+
return (await import("./diagnostic")).createIframeTimeoutInitializationError({
|
|
896
|
+
redirectUri: homeUrlAndRedirectUri,
|
|
897
|
+
clientId,
|
|
898
|
+
issuerUri,
|
|
899
|
+
noIframe
|
|
900
|
+
});
|
|
858
901
|
}
|
|
859
902
|
|
|
860
903
|
assert<Equals<typeof result_loginSilent.outcome, "got auth response from iframe">>();
|
|
@@ -899,8 +942,6 @@ export async function createOidc_nonMemoized<
|
|
|
899
942
|
) {
|
|
900
943
|
log?.("Performing auto login with redirect");
|
|
901
944
|
|
|
902
|
-
persistAuthState({ configId, state: undefined });
|
|
903
|
-
|
|
904
945
|
completeLoginOrRefreshProcess();
|
|
905
946
|
|
|
906
947
|
if (autoLogin && persistedAuthState !== "logged in") {
|
|
@@ -912,18 +953,16 @@ export async function createOidc_nonMemoized<
|
|
|
912
953
|
getPrSafelyRestoredFromBfCacheAfterLoginBackNavigationOrInitializationError()
|
|
913
954
|
});
|
|
914
955
|
|
|
915
|
-
|
|
916
|
-
globalContext.evtRequestToPersistTokens.post({
|
|
917
|
-
configIdOfInstancePostingTheRequest: configId
|
|
918
|
-
});
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
const dCantFetchWellKnownEndpointOrNever = new Deferred<void | never>();
|
|
922
|
-
|
|
923
|
-
loginOrGoToAuthServer({
|
|
956
|
+
await loginOrGoToAuthServer({
|
|
924
957
|
action: "login",
|
|
925
958
|
doForceReloadOnBfCache: true,
|
|
926
|
-
redirectUrl:
|
|
959
|
+
redirectUrl: (() => {
|
|
960
|
+
if (evtIsThereMoreThanOneInstanceThatCantUserIframes.current) {
|
|
961
|
+
return window.location.href;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
return getRootRelativeOriginalLocationHref();
|
|
965
|
+
})(),
|
|
927
966
|
// NOTE: Wether or not it's the preferred behavior, pushing to history
|
|
928
967
|
// only works on user interaction so it have to be false
|
|
929
968
|
doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
|
|
@@ -940,19 +979,10 @@ export async function createOidc_nonMemoized<
|
|
|
940
979
|
|
|
941
980
|
return "ensure no interaction";
|
|
942
981
|
})(),
|
|
943
|
-
|
|
944
|
-
|
|
982
|
+
preRedirectHook: () => {
|
|
983
|
+
persistAuthState({ configId, state: undefined });
|
|
945
984
|
}
|
|
946
985
|
});
|
|
947
|
-
|
|
948
|
-
await dCantFetchWellKnownEndpointOrNever.pr;
|
|
949
|
-
|
|
950
|
-
return (
|
|
951
|
-
await import("./diagnostic")
|
|
952
|
-
).createFailedToFetchTokenEndpointInitializationError({
|
|
953
|
-
clientId,
|
|
954
|
-
issuerUri
|
|
955
|
-
});
|
|
956
986
|
}
|
|
957
987
|
|
|
958
988
|
if (authResponse_error !== undefined) {
|
|
@@ -1073,10 +1103,7 @@ export async function createOidc_nonMemoized<
|
|
|
1073
1103
|
getPersistedAuthState({ configId }) === "explicitly logged out"
|
|
1074
1104
|
? "ensure interaction"
|
|
1075
1105
|
: "directly redirect if active session show login otherwise",
|
|
1076
|
-
|
|
1077
|
-
log?.("Login called but the auth server seems to be down..");
|
|
1078
|
-
alert("Authentication unavailable please try again later.");
|
|
1079
|
-
}
|
|
1106
|
+
preRedirectHook: undefined
|
|
1080
1107
|
});
|
|
1081
1108
|
},
|
|
1082
1109
|
initializationError: undefined
|
|
@@ -1148,6 +1175,7 @@ export async function createOidc_nonMemoized<
|
|
|
1148
1175
|
state: {
|
|
1149
1176
|
stateDescription: "logged in",
|
|
1150
1177
|
refreshTokenExpirationTime: currentTokens.refreshTokenExpirationTime,
|
|
1178
|
+
serverDateNow: currentTokens.getServerDateNow(),
|
|
1151
1179
|
idleSessionLifetimeInSeconds
|
|
1152
1180
|
}
|
|
1153
1181
|
});
|
|
@@ -1297,10 +1325,6 @@ export async function createOidc_nonMemoized<
|
|
|
1297
1325
|
prUnlock: new Promise<never>(() => {})
|
|
1298
1326
|
});
|
|
1299
1327
|
|
|
1300
|
-
globalContext.evtRequestToPersistTokens.post({
|
|
1301
|
-
configIdOfInstancePostingTheRequest: configId
|
|
1302
|
-
});
|
|
1303
|
-
|
|
1304
1328
|
await loginOrGoToAuthServer({
|
|
1305
1329
|
action: "login",
|
|
1306
1330
|
redirectUrl: window.location.href,
|
|
@@ -1309,15 +1333,7 @@ export async function createOidc_nonMemoized<
|
|
|
1309
1333
|
transformUrlBeforeRedirect_local: undefined,
|
|
1310
1334
|
doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
|
|
1311
1335
|
interaction: "directly redirect if active session show login otherwise",
|
|
1312
|
-
|
|
1313
|
-
log?.(
|
|
1314
|
-
[
|
|
1315
|
-
"The auth server seems to be down while we needed to refresh the token",
|
|
1316
|
-
"with a full page redirect. Reloading the page"
|
|
1317
|
-
].join(" ")
|
|
1318
|
-
);
|
|
1319
|
-
window.location.reload();
|
|
1320
|
-
}
|
|
1336
|
+
preRedirectHook: undefined
|
|
1321
1337
|
});
|
|
1322
1338
|
assert(false, "136134");
|
|
1323
1339
|
};
|
|
@@ -1352,10 +1368,10 @@ export async function createOidc_nonMemoized<
|
|
|
1352
1368
|
log
|
|
1353
1369
|
});
|
|
1354
1370
|
|
|
1355
|
-
if (result_loginSilent.outcome === "
|
|
1371
|
+
if (result_loginSilent.outcome === "timeout") {
|
|
1356
1372
|
log?.(
|
|
1357
1373
|
[
|
|
1358
|
-
`Silent refresh of the token failed
|
|
1374
|
+
`Silent refresh of the token failed the iframe didn't post a response (timeout).`,
|
|
1359
1375
|
`This isn't recoverable, reloading the page.`
|
|
1360
1376
|
].join(" ")
|
|
1361
1377
|
);
|
|
@@ -1438,6 +1454,7 @@ export async function createOidc_nonMemoized<
|
|
|
1438
1454
|
state: {
|
|
1439
1455
|
stateDescription: "logged in",
|
|
1440
1456
|
refreshTokenExpirationTime: currentTokens.refreshTokenExpirationTime,
|
|
1457
|
+
serverDateNow: currentTokens.getServerDateNow(),
|
|
1441
1458
|
idleSessionLifetimeInSeconds
|
|
1442
1459
|
}
|
|
1443
1460
|
});
|
|
@@ -1545,11 +1562,7 @@ export async function createOidc_nonMemoized<
|
|
|
1545
1562
|
action: "go to auth server",
|
|
1546
1563
|
redirectUrl: redirectUrl ?? window.location.href,
|
|
1547
1564
|
extraQueryParams_local: extraQueryParams,
|
|
1548
|
-
transformUrlBeforeRedirect_local: transformUrlBeforeRedirect
|
|
1549
|
-
onCantFetchWellKnownEndpointError: () => {
|
|
1550
|
-
log?.("goToAuthServer called but the auth server seems to be down..");
|
|
1551
|
-
alert("Authentication unavailable please try again later.");
|
|
1552
|
-
}
|
|
1565
|
+
transformUrlBeforeRedirect_local: transformUrlBeforeRedirect
|
|
1553
1566
|
}),
|
|
1554
1567
|
backFromAuthServer: resultOfLoginProcess.backFromAuthServer,
|
|
1555
1568
|
isNewBrowserSession: (() => {
|