oidc-spa 8.2.0 → 8.2.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.
Files changed (48) hide show
  1. package/core/OidcMetadata.d.ts +5 -0
  2. package/core/OidcMetadata.js +56 -0
  3. package/core/OidcMetadata.js.map +1 -1
  4. package/core/createOidc.d.ts +1 -1
  5. package/core/createOidc.js +170 -102
  6. package/core/createOidc.js.map +1 -1
  7. package/core/diagnostic.d.ts +0 -1
  8. package/core/diagnostic.js +18 -5
  9. package/core/diagnostic.js.map +1 -1
  10. package/core/loginOrGoToAuthServer.d.ts +0 -1
  11. package/core/loginOrGoToAuthServer.js +1 -16
  12. package/core/loginOrGoToAuthServer.js.map +1 -1
  13. package/core/loginSilent.d.ts +1 -2
  14. package/core/loginSilent.js +3 -21
  15. package/core/loginSilent.js.map +1 -1
  16. package/esm/core/OidcMetadata.d.ts +5 -0
  17. package/esm/core/OidcMetadata.js +54 -0
  18. package/esm/core/OidcMetadata.js.map +1 -1
  19. package/esm/core/createOidc.d.ts +1 -1
  20. package/esm/core/createOidc.js +170 -102
  21. package/esm/core/createOidc.js.map +1 -1
  22. package/esm/core/diagnostic.d.ts +0 -1
  23. package/esm/core/diagnostic.js +15 -1
  24. package/esm/core/diagnostic.js.map +1 -1
  25. package/esm/core/loginOrGoToAuthServer.d.ts +0 -1
  26. package/esm/core/loginOrGoToAuthServer.js +1 -16
  27. package/esm/core/loginOrGoToAuthServer.js.map +1 -1
  28. package/esm/core/loginSilent.d.ts +1 -2
  29. package/esm/core/loginSilent.js +3 -21
  30. package/esm/core/loginSilent.js.map +1 -1
  31. package/esm/keycloak/keycloakIssuerUriParsed.js +8 -1
  32. package/esm/keycloak/keycloakIssuerUriParsed.js.map +1 -1
  33. package/esm/tools/isLikelyDevServer.d.ts +1 -0
  34. package/esm/tools/isLikelyDevServer.js +14 -0
  35. package/esm/tools/isLikelyDevServer.js.map +1 -0
  36. package/keycloak/keycloakIssuerUriParsed.js +8 -1
  37. package/keycloak/keycloakIssuerUriParsed.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/core/OidcMetadata.ts +75 -0
  40. package/src/core/createOidc.ts +209 -137
  41. package/src/core/diagnostic.ts +21 -2
  42. package/src/core/loginOrGoToAuthServer.ts +0 -22
  43. package/src/core/loginSilent.ts +4 -27
  44. package/src/keycloak/keycloakIssuerUriParsed.ts +10 -1
  45. package/src/tools/isLikelyDevServer.ts +17 -0
  46. package/tools/isLikelyDevServer.d.ts +1 -0
  47. package/tools/isLikelyDevServer.js +17 -0
  48. package/tools/isLikelyDevServer.js.map +1 -0
@@ -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 { OidcMetadata } from "./OidcMetadata";
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";
@@ -49,10 +49,10 @@ import { createGetIsNewBrowserSession } from "./isNewBrowserSession";
49
49
  import { getIsOnline } from "../tools/getIsOnline";
50
50
  import { isKeycloak } from "../keycloak/isKeycloak";
51
51
  import { INFINITY_TIME } from "../tools/INFINITY_TIME";
52
- import type { WELL_KNOWN_PATH } from "./diagnostic";
53
- import { getIsValidRemoteJson } from "../tools/getIsValidRemoteJson";
54
52
  import { prShouldLoadApp } from "./prShouldLoadApp";
55
53
  import { getBASE_URL } from "./BASE_URL";
54
+ import { getIsLikelyDevServer } from "../tools/isLikelyDevServer";
55
+ import { createObjectThatThrowsIfAccessed } from "../tools/createObjectThatThrowsIfAccessed";
56
56
 
57
57
  // NOTE: Replaced at build time
58
58
  const VERSION = "{{OIDC_SPA_VERSION}}";
@@ -432,92 +432,212 @@ export async function createOidc_nonMemoized<
432
432
 
433
433
  const stateUrlParamValue_instance = generateStateUrlParamValue();
434
434
 
435
+ const oidcMetadata = __metadata ?? (await fetchOidcMetadata({ issuerUri }));
436
+
435
437
  const canUseIframe = (() => {
436
438
  if (noIframe) {
437
439
  return false;
438
440
  }
439
441
 
440
442
  third_party_cookies: {
441
- const isOidcServerThirdPartyRelativeToApp =
442
- getHaveSharedParentDomain({
443
- url1: window.location.origin,
444
- url2: issuerUri
445
- }) === false;
446
-
447
- if (!isOidcServerThirdPartyRelativeToApp) {
448
- break third_party_cookies;
443
+ if (oidcMetadata === undefined) {
444
+ return false;
449
445
  }
450
446
 
451
- const isGoogleChrome = (() => {
452
- const ua = navigator.userAgent;
453
- const vendor = navigator.vendor;
447
+ const { authorization_endpoint } = oidcMetadata;
454
448
 
455
- return (
456
- /Chrome/.test(ua) && /Google Inc/.test(vendor) && !/Edg/.test(ua) && !/OPR/.test(ua)
457
- );
458
- })();
449
+ assert(
450
+ authorization_endpoint !== undefined,
451
+ "Missing authorization_endpoint on the provided __metadata"
452
+ );
453
+
454
+ const isOidcServerThirdPartyRelativeToApp = !getHaveSharedParentDomain({
455
+ url1: window.location.origin,
456
+ // TODO: No, here we should test against the authorization endpoint!
457
+ url2: authorization_endpoint
458
+ });
459
459
 
460
- if (window.location.origin.startsWith("http://localhost") && isGoogleChrome) {
460
+ if (!isOidcServerThirdPartyRelativeToApp) {
461
461
  break third_party_cookies;
462
462
  }
463
463
 
464
- log?.(
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
- );
464
+ const isLikelyDevServer = getIsLikelyDevServer();
470
465
 
471
- return false;
472
- }
466
+ const domain_auth = new URL(authorization_endpoint).origin.split("//")[1];
473
467
 
474
- // NOTE: Maybe not, it depend if the app can iframe itself.
475
- return true;
476
- })();
468
+ assert(domain_auth !== undefined, "33921384");
477
469
 
478
- let isUserStoreInMemoryOnly: boolean;
479
-
480
- const oidcClientTsUserManager = new OidcClientTsUserManager({
481
- stateUrlParamValue: stateUrlParamValue_instance,
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();
470
+ const domain_here = window.location.origin.split("//")[1];
471
+
472
+ let isWellKnownProviderDomain = false;
473
+ let isIp = false;
474
+
475
+ const suggestedDeployments = (() => {
476
+ if (/^(?:\d{1,3}\.){3}\d{1,3}$|^\[?[A-Fa-f0-9:]+\]?$/.test(domain_auth)) {
477
+ isIp = true;
478
+ return [];
496
479
  }
497
480
 
498
- isUserStoreInMemoryOnly = false;
481
+ const baseDomain = (() => {
482
+ const segments = domain_auth.split(".");
499
483
 
500
- const storage = createEphemeralSessionStorage({
501
- sessionStorageTtlMs: 3 * 60_000
502
- });
484
+ if (segments.length >= 3) {
485
+ segments.shift();
486
+ }
487
+ return segments.join(".");
488
+ })();
503
489
 
504
- const { evtRequestToPersistTokens } = globalContext;
490
+ {
491
+ const baseDomain_low = baseDomain.toLowerCase();
505
492
 
506
- evtRequestToPersistTokens.subscribe(({ configIdOfInstancePostingTheRequest }) => {
507
- if (configIdOfInstancePostingTheRequest === configId) {
508
- return;
493
+ if (
494
+ baseDomain_low.includes("auth0") ||
495
+ baseDomain_low.includes("clerk") ||
496
+ baseDomain_low.includes("microsoft") ||
497
+ baseDomain_low.includes("okta") ||
498
+ baseDomain_low.includes("aws")
499
+ ) {
500
+ isWellKnownProviderDomain = true;
501
+ return [];
509
502
  }
503
+ }
510
504
 
511
- storage.persistCurrentStateAndSubsequentChanges();
512
- });
505
+ const baseUrl = new URL(homeUrlAndRedirectUri).pathname;
513
506
 
514
- return storage;
515
- })()
516
- }),
517
- stateStore: new WebStorageStateStore({ store: localStorage, prefix: STATE_STORE_KEY_PREFIX }),
518
- client_secret: __unsafe_clientSecret,
519
- metadata: __metadata
520
- });
507
+ return [
508
+ `myapp.${baseDomain}`,
509
+ baseDomain === domain_auth ? undefined : baseDomain,
510
+ `${baseDomain}/${baseUrl === "/" ? "dashboard" : baseUrl}`
511
+ ].filter(x => x !== undefined);
512
+ })();
513
+
514
+ if (isLikelyDevServer) {
515
+ log?.(
516
+ [
517
+ "Detected localhost environment.",
518
+ "\nWhen reloading while logged in, you may briefly see",
519
+ "some URL params appear in the address bar.",
520
+ "\nThis happens because session restore via iframe is disabled,",
521
+ "the browser treats your auth server as a third party.",
522
+ `\nAuth server: ${domain_auth}`,
523
+ `\nApp domain: ${domain_here}`,
524
+ ...(() => {
525
+ if (isIp) {
526
+ return [];
527
+ }
528
+
529
+ if (isWellKnownProviderDomain) {
530
+ return [
531
+ "\nYou seem to be using a well-known auth provider.",
532
+ "Check your provider's docs, some allow configuring",
533
+ `a your custom domain at least for the authorization endpoint.`,
534
+ "\nIf configured, oidc-spa will restore sessions silently",
535
+ "and improve the user experience."
536
+ ];
537
+ }
538
+
539
+ return [
540
+ "\nOnce deployed under the same root domain as your auth server,",
541
+ "oidc-spa will use iframes to restore sessions silently.",
542
+ "\nSuggested deployments:",
543
+ ...suggestedDeployments.map(d => `\n • ${d}`)
544
+ ];
545
+ })(),
546
+ "\n\nMore info:",
547
+ "https://docs.oidc-spa.dev/v/v8/resources/end-of-third-party-cookies#when-are-cookies-considered-third-party"
548
+ ].join(" ")
549
+ );
550
+ } else {
551
+ log?.(
552
+ [
553
+ "Silent session restore via iframe is disabled.",
554
+ `\nAuth server: ${domain_auth}`,
555
+ `App domain: ${domain_here}`,
556
+ "\nThey do not share a common root domain.",
557
+ ...(() => {
558
+ if (isIp) {
559
+ return [];
560
+ }
561
+
562
+ if (isWellKnownProviderDomain) {
563
+ return [
564
+ "\nYou seem to be using a well-known auth provider.",
565
+ "Check if you can configure a custom auth domain.",
566
+ "\nIf so, oidc-spa can restore sessions silently",
567
+ "and improve the user experience."
568
+ ];
569
+ }
570
+
571
+ return [
572
+ "\nTo improve the experience, here are some examples of deployment for your app:",
573
+ ...suggestedDeployments.map(d => `\n • ${d}`)
574
+ ];
575
+ })(),
576
+ "\nMore info:",
577
+ "https://docs.oidc-spa.dev/v/v8/resources/end-of-third-party-cookies#when-are-cookies-considered-third-party"
578
+ ].join(" ")
579
+ );
580
+ }
581
+
582
+ return false;
583
+ }
584
+
585
+ return true;
586
+ })();
587
+
588
+ let isUserStoreInMemoryOnly: boolean | undefined = undefined;
589
+
590
+ const oidcClientTsUserManager =
591
+ oidcMetadata === undefined
592
+ ? createObjectThatThrowsIfAccessed<OidcClientTsUserManager>({
593
+ debugMessage: "oidc-spa: Wrong assertion 43943"
594
+ })
595
+ : new OidcClientTsUserManager({
596
+ stateUrlParamValue: stateUrlParamValue_instance,
597
+ authority: issuerUri,
598
+ client_id: clientId,
599
+ redirect_uri: homeUrlAndRedirectUri,
600
+ silent_redirect_uri: homeUrlAndRedirectUri,
601
+ post_logout_redirect_uri: homeUrlAndRedirectUri,
602
+ response_mode: isKeycloak({ issuerUri }) ? "fragment" : "query",
603
+ response_type: "code",
604
+ scope: Array.from(new Set(["openid", ...scopes])).join(" "),
605
+ automaticSilentRenew: false,
606
+ userStore: new WebStorageStateStore({
607
+ store: (() => {
608
+ if (canUseIframe) {
609
+ isUserStoreInMemoryOnly = true;
610
+ return new InMemoryWebStorage();
611
+ }
612
+
613
+ isUserStoreInMemoryOnly = false;
614
+
615
+ const storage = createEphemeralSessionStorage({
616
+ sessionStorageTtlMs: 3 * 60_000
617
+ });
618
+
619
+ const { evtRequestToPersistTokens } = globalContext;
620
+
621
+ evtRequestToPersistTokens.subscribe(
622
+ ({ configIdOfInstancePostingTheRequest }) => {
623
+ if (configIdOfInstancePostingTheRequest === configId) {
624
+ return;
625
+ }
626
+
627
+ storage.persistCurrentStateAndSubsequentChanges();
628
+ }
629
+ );
630
+
631
+ return storage;
632
+ })()
633
+ }),
634
+ stateStore: new WebStorageStateStore({
635
+ store: localStorage,
636
+ prefix: STATE_STORE_KEY_PREFIX
637
+ }),
638
+ client_secret: __unsafe_clientSecret,
639
+ metadata: oidcMetadata
640
+ });
521
641
 
522
642
  const evtInitializationOutcomeUserNotLoggedIn = createEvt<void>();
523
643
 
@@ -547,6 +667,14 @@ export async function createOidc_nonMemoized<
547
667
  backFromAuthServer: Oidc.LoggedIn["backFromAuthServer"]; // Undefined is silent signin
548
668
  }
549
669
  > => {
670
+ if (oidcMetadata === undefined) {
671
+ return (
672
+ await import("./diagnostic")
673
+ ).createWellKnownOidcConfigurationEndpointUnreachableInitializationError({
674
+ issuerUri
675
+ });
676
+ }
677
+
550
678
  handle_redirect_auth_response: {
551
679
  let stateDataAndAuthResponse:
552
680
  | { stateData: StateData.Redirect; authResponse: AuthResponse }
@@ -731,6 +859,8 @@ export async function createOidc_nonMemoized<
731
859
  // NOTE: We almost never persist tokens, we have to only to support edge case
732
860
  // of multiple oidc instance in a single App with no iframe support.
733
861
  restore_from_session_storage: {
862
+ assert(isUserStoreInMemoryOnly !== undefined, "3392204");
863
+
734
864
  if (isUserStoreInMemoryOnly) {
735
865
  break restore_from_session_storage;
736
866
  }
@@ -801,20 +931,6 @@ export async function createOidc_nonMemoized<
801
931
  }
802
932
 
803
933
  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
934
  break actual_silent_signin;
819
935
  }
820
936
 
@@ -835,26 +951,13 @@ export async function createOidc_nonMemoized<
835
951
 
836
952
  assert(result_loginSilent.outcome !== "token refreshed using refresh token", "876995");
837
953
 
838
- if (result_loginSilent.outcome === "failure") {
839
- switch (result_loginSilent.cause) {
840
- case "can't reach well-known oidc endpoint":
841
- return (
842
- await import("./diagnostic")
843
- ).createWellKnownOidcConfigurationEndpointUnreachableInitializationError({
844
- issuerUri
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);
954
+ if (result_loginSilent.outcome === "timeout") {
955
+ return (await import("./diagnostic")).createIframeTimeoutInitializationError({
956
+ redirectUri: homeUrlAndRedirectUri,
957
+ clientId,
958
+ issuerUri,
959
+ noIframe
960
+ });
858
961
  }
859
962
 
860
963
  assert<Equals<typeof result_loginSilent.outcome, "got auth response from iframe">>();
@@ -918,9 +1021,7 @@ export async function createOidc_nonMemoized<
918
1021
  });
919
1022
  }
920
1023
 
921
- const dCantFetchWellKnownEndpointOrNever = new Deferred<void | never>();
922
-
923
- loginOrGoToAuthServer({
1024
+ await loginOrGoToAuthServer({
924
1025
  action: "login",
925
1026
  doForceReloadOnBfCache: true,
926
1027
  redirectUrl: getRootRelativeOriginalLocationHref(),
@@ -939,19 +1040,7 @@ export async function createOidc_nonMemoized<
939
1040
  }
940
1041
 
941
1042
  return "ensure no interaction";
942
- })(),
943
- onCantFetchWellKnownEndpointError: () => {
944
- dCantFetchWellKnownEndpointOrNever.resolve();
945
- }
946
- });
947
-
948
- await dCantFetchWellKnownEndpointOrNever.pr;
949
-
950
- return (
951
- await import("./diagnostic")
952
- ).createFailedToFetchTokenEndpointInitializationError({
953
- clientId,
954
- issuerUri
1043
+ })()
955
1044
  });
956
1045
  }
957
1046
 
@@ -1072,11 +1161,7 @@ export async function createOidc_nonMemoized<
1072
1161
  interaction:
1073
1162
  getPersistedAuthState({ configId }) === "explicitly logged out"
1074
1163
  ? "ensure interaction"
1075
- : "directly redirect if active session show login otherwise",
1076
- onCantFetchWellKnownEndpointError: () => {
1077
- log?.("Login called but the auth server seems to be down..");
1078
- alert("Authentication unavailable please try again later.");
1079
- }
1164
+ : "directly redirect if active session show login otherwise"
1080
1165
  });
1081
1166
  },
1082
1167
  initializationError: undefined
@@ -1308,16 +1393,7 @@ export async function createOidc_nonMemoized<
1308
1393
  extraQueryParams_local: undefined,
1309
1394
  transformUrlBeforeRedirect_local: undefined,
1310
1395
  doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
1311
- interaction: "directly redirect if active session show login otherwise",
1312
- onCantFetchWellKnownEndpointError: () => {
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
- }
1396
+ interaction: "directly redirect if active session show login otherwise"
1321
1397
  });
1322
1398
  assert(false, "136134");
1323
1399
  };
@@ -1352,10 +1428,10 @@ export async function createOidc_nonMemoized<
1352
1428
  log
1353
1429
  });
1354
1430
 
1355
- if (result_loginSilent.outcome === "failure") {
1431
+ if (result_loginSilent.outcome === "timeout") {
1356
1432
  log?.(
1357
1433
  [
1358
- `Silent refresh of the token failed with ${result_loginSilent.cause}.`,
1434
+ `Silent refresh of the token failed the iframe didn't post a response (timeout).`,
1359
1435
  `This isn't recoverable, reloading the page.`
1360
1436
  ].join(" ")
1361
1437
  );
@@ -1545,11 +1621,7 @@ export async function createOidc_nonMemoized<
1545
1621
  action: "go to auth server",
1546
1622
  redirectUrl: redirectUrl ?? window.location.href,
1547
1623
  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
- }
1624
+ transformUrlBeforeRedirect_local: transformUrlBeforeRedirect
1553
1625
  }),
1554
1626
  backFromAuthServer: resultOfLoginProcess.backFromAuthServer,
1555
1627
  isNewBrowserSession: (() => {
@@ -1,8 +1,7 @@
1
1
  import { OidcInitializationError } from "./OidcInitializationError";
2
2
  import { isKeycloak, createKeycloakUtils } from "../keycloak";
3
3
  import { getIsValidRemoteJson } from "../tools/getIsValidRemoteJson";
4
-
5
- export const WELL_KNOWN_PATH = "/.well-known/openid-configuration";
4
+ import { WELL_KNOWN_PATH } from "./OidcMetadata";
6
5
 
7
6
  export async function createWellKnownOidcConfigurationEndpointUnreachableInitializationError(params: {
8
7
  issuerUri: string;
@@ -95,6 +94,16 @@ export async function createIframeTimeoutInitializationError(params: {
95
94
  }): Promise<OidcInitializationError> {
96
95
  const { redirectUri, issuerUri, clientId, noIframe } = params;
97
96
 
97
+ check_if_well_known_endpoint_is_reachable: {
98
+ const isValid = await getIsValidRemoteJson(`${issuerUri}${WELL_KNOWN_PATH}`);
99
+
100
+ if (isValid) {
101
+ break check_if_well_known_endpoint_is_reachable;
102
+ }
103
+
104
+ return createWellKnownOidcConfigurationEndpointUnreachableInitializationError({ issuerUri });
105
+ }
106
+
98
107
  iframe_blocked: {
99
108
  if (noIframe) {
100
109
  break iframe_blocked;
@@ -233,6 +242,16 @@ export async function createFailedToFetchTokenEndpointInitializationError(params
233
242
  }) {
234
243
  const { issuerUri, clientId } = params;
235
244
 
245
+ check_if_well_known_endpoint_is_reachable: {
246
+ const isValid = await getIsValidRemoteJson(`${issuerUri}${WELL_KNOWN_PATH}`);
247
+
248
+ if (isValid) {
249
+ break check_if_well_known_endpoint_is_reachable;
250
+ }
251
+
252
+ return createWellKnownOidcConfigurationEndpointUnreachableInitializationError({ issuerUri });
253
+ }
254
+
236
255
  return new OidcInitializationError({
237
256
  isAuthServerLikelyDown: false,
238
257
  messageOrCause: [
@@ -20,7 +20,6 @@ namespace Params {
20
20
  redirectUrl: string;
21
21
  extraQueryParams_local: Record<string, string | undefined> | undefined;
22
22
  transformUrlBeforeRedirect_local: ((url: string) => string) | undefined;
23
- onCantFetchWellKnownEndpointError: () => void;
24
23
  };
25
24
 
26
25
  export type Login = Common & {
@@ -90,10 +89,8 @@ export function createLoginOrGoToAuthServer(params: {
90
89
  redirectUrl: redirectUrl_params,
91
90
  extraQueryParams_local,
92
91
  transformUrlBeforeRedirect_local,
93
- onCantFetchWellKnownEndpointError: onCantFetchWellKnownEndpointError_params,
94
92
  ...rest
95
93
  } = params;
96
- let onCantFetchWellKnownEndpointError = onCantFetchWellKnownEndpointError_params;
97
94
 
98
95
  log?.(`Calling loginOrGoToAuthServer ${JSON.stringify(params, null, 2)}`);
99
96
 
@@ -147,12 +144,6 @@ export function createLoginOrGoToAuthServer(params: {
147
144
  };
148
145
 
149
146
  window.addEventListener("pageshow", callback);
150
-
151
- onCantFetchWellKnownEndpointError = () => {
152
- window.removeEventListener("pageshow", callback);
153
- onCantFetchWellKnownEndpointError_params();
154
- };
155
-
156
147
  break bf_cache_handling;
157
148
  }
158
149
 
@@ -183,12 +174,6 @@ export function createLoginOrGoToAuthServer(params: {
183
174
  };
184
175
 
185
176
  window.addEventListener("pageshow", callback);
186
-
187
- onCantFetchWellKnownEndpointError = () => {
188
- window.removeEventListener("pageshow", callback);
189
- globalContext.evtHasLoginBeenCalled.current = false;
190
- onCantFetchWellKnownEndpointError_params();
191
- };
192
177
  }
193
178
  }
194
179
 
@@ -348,13 +333,6 @@ export function createLoginOrGoToAuthServer(params: {
348
333
  .then(
349
334
  () => new Promise<never>(() => {}),
350
335
  (error: Error) => {
351
- if (error.message === "Failed to fetch") {
352
- // NOTE: See ./loginSilent for explanation.
353
- onCantFetchWellKnownEndpointError();
354
-
355
- return new Promise<never>(() => {});
356
- }
357
-
358
336
  if (error.message.includes("Crypto.subtle is available only in secure contexts")) {
359
337
  throw new Error(
360
338
  [
@@ -20,8 +20,7 @@ type ResultOfLoginSilent =
20
20
  authResponse: AuthResponse;
21
21
  }
22
22
  | {
23
- outcome: "failure";
24
- cause: "timeout" | "can't reach well-known oidc endpoint";
23
+ outcome: "timeout";
25
24
  }
26
25
  | {
27
26
  outcome: "token refreshed using refresh token";
@@ -106,8 +105,7 @@ export async function loginSilent(params: {
106
105
  const timeouts = [
107
106
  setTimeout(() => {
108
107
  dResult.resolve({
109
- outcome: "failure",
110
- cause: "timeout"
108
+ outcome: "timeout"
111
109
  });
112
110
  }, timeoutDelayMs),
113
111
  setTimeout(() => {
@@ -259,28 +257,7 @@ export async function loginSilent(params: {
259
257
  oidcClientTsUser
260
258
  });
261
259
  },
262
- (error: Error) => {
263
- if (error.message === "Failed to fetch") {
264
- // NOTE: If we got an error here it means that the fetch to the
265
- // well-known oidc endpoint failed.
266
- // This usually means that the server is down or that the issuerUri
267
- // is not pointing to a valid oidc server.
268
- // It could be a CORS error on the well-known endpoint but it's unlikely.
269
-
270
- // NOTE: This error should happen well before we displayed
271
- // the warning notifying that something is probably misconfigured.
272
- // wasSuccess shouldn't really be a required parameter but we do it
273
- // for peace of mind.
274
- clearTimeouts({ wasSuccess: false });
275
-
276
- dResult.resolve({
277
- outcome: "failure",
278
- cause: "can't reach well-known oidc endpoint"
279
- });
280
-
281
- return;
282
- }
283
-
260
+ () => {
284
261
  // NOTE: Here, except error on our understanding there can't be any other
285
262
  // error than timeout so we fail silently and let the timeout expire.
286
263
  }
@@ -289,7 +266,7 @@ export async function loginSilent(params: {
289
266
  dResult.pr.then(result => {
290
267
  clearSessionStoragePublicKey();
291
268
 
292
- if (result.outcome === "failure") {
269
+ if (result.outcome === "timeout") {
293
270
  clearStateStore({ stateUrlParamValue: stateUrlParamValue_instance });
294
271
  }
295
272
  });
@@ -11,7 +11,16 @@ export type KeycloakIssuerUriParsed = {
11
11
  export function parseKeycloakIssuerUri(params: { issuerUri: string }): KeycloakIssuerUriParsed {
12
12
  const { issuerUri } = params;
13
13
 
14
- assert(isKeycloak({ issuerUri }));
14
+ if (!isKeycloak({ issuerUri })) {
15
+ throw new Error(
16
+ [
17
+ `oidc-spa: The issuer uri provided ${issuerUri}`,
18
+ "if you are in an environnement that should support multiple",
19
+ "auth provider, you should first test `isKeycloakUrl({ issuerUri })`",
20
+ "before calling parseKeycloakIssuerUri({ issuerUri })"
21
+ ].join(" ")
22
+ );
23
+ }
15
24
 
16
25
  const url = new URL(issuerUri.replace(/\/$/, ""));
17
26
 
@@ -0,0 +1,17 @@
1
+ export function getIsLikelyDevServer(): boolean {
2
+ const origin = window.location.origin;
3
+
4
+ if (/^https?:\/\/localhost/.test(origin)) {
5
+ return true;
6
+ }
7
+
8
+ if (/^https?:\/\/\[::\]/.test(origin)) {
9
+ return true;
10
+ }
11
+
12
+ if (/^https?:\/\/127.0.0.1/.test(origin)) {
13
+ return true;
14
+ }
15
+
16
+ return false;
17
+ }
@@ -0,0 +1 @@
1
+ export declare function getIsLikelyDevServer(): boolean;