oidc-spa 8.1.15 → 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.
- package/core/BASE_URL.d.ts +4 -0
- package/core/BASE_URL.js +12 -0
- package/core/BASE_URL.js.map +1 -0
- 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 +15 -8
- package/core/createOidc.js +207 -104
- 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/earlyInit.d.ts +1 -0
- package/core/earlyInit.js +8 -8
- package/core/earlyInit.js.map +1 -1
- package/core/loginOrGoToAuthServer.d.ts +0 -1
- package/core/loginOrGoToAuthServer.js +1 -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/prShouldLoadApp.d.ts +4 -0
- package/core/prShouldLoadApp.js +13 -0
- package/core/prShouldLoadApp.js.map +1 -0
- package/esm/core/BASE_URL.d.ts +4 -0
- package/esm/core/BASE_URL.js +8 -0
- package/esm/core/BASE_URL.js.map +1 -0
- 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 +15 -8
- package/esm/core/createOidc.js +207 -104
- 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/earlyInit.d.ts +1 -0
- package/esm/core/earlyInit.js +8 -8
- package/esm/core/earlyInit.js.map +1 -1
- package/esm/core/loginOrGoToAuthServer.d.ts +0 -1
- package/esm/core/loginOrGoToAuthServer.js +1 -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/prShouldLoadApp.d.ts +4 -0
- package/esm/core/prShouldLoadApp.js +9 -0
- package/esm/core/prShouldLoadApp.js.map +1 -0
- package/esm/keycloak/keycloak-js/Keycloak.d.ts +1 -1
- package/esm/keycloak/keycloak-js/Keycloak.js +1 -1
- package/esm/keycloak/keycloak-js/Keycloak.js.map +1 -1
- package/esm/keycloak/keycloakIssuerUriParsed.js +8 -1
- package/esm/keycloak/keycloakIssuerUriParsed.js.map +1 -1
- package/esm/mock/oidc.d.ts +3 -1
- package/esm/mock/oidc.js +4 -2
- package/esm/mock/oidc.js.map +1 -1
- package/esm/react-spa/apiBuilder.d.ts +12 -0
- package/esm/react-spa/apiBuilder.js +26 -0
- package/esm/react-spa/apiBuilder.js.map +1 -0
- package/esm/react-spa/createOidcSpaApi.d.ts +8 -0
- package/esm/react-spa/createOidcSpaApi.js +387 -0
- package/esm/react-spa/createOidcSpaApi.js.map +1 -0
- package/esm/react-spa/index.d.ts +2 -0
- package/esm/react-spa/index.js +3 -0
- package/esm/react-spa/index.js.map +1 -0
- package/esm/react-spa/types.d.ts +279 -0
- package/esm/react-spa/types.js +2 -0
- package/esm/react-spa/types.js.map +1 -0
- package/esm/tanstack-start/react/apiBuilder.js.map +1 -1
- package/esm/tanstack-start/react/createOidcSpaApi.js +13 -9
- package/esm/tanstack-start/react/createOidcSpaApi.js.map +1 -1
- package/esm/tanstack-start/react/types.d.ts +5 -4
- package/esm/tools/isLikelyDevServer.d.ts +1 -0
- package/esm/tools/isLikelyDevServer.js +14 -0
- package/esm/tools/isLikelyDevServer.js.map +1 -0
- package/keycloak/keycloak-js/Keycloak.d.ts +1 -1
- package/keycloak/keycloak-js/Keycloak.js +1 -1
- package/keycloak/keycloak-js/Keycloak.js.map +1 -1
- package/keycloak/keycloakIssuerUriParsed.js +8 -1
- package/keycloak/keycloakIssuerUriParsed.js.map +1 -1
- package/mock/oidc.d.ts +3 -1
- package/mock/oidc.js +4 -2
- package/mock/oidc.js.map +1 -1
- package/package.json +5 -1
- package/react-spa/apiBuilder.d.ts +12 -0
- package/react-spa/apiBuilder.js +29 -0
- package/react-spa/apiBuilder.js.map +1 -0
- package/react-spa/createOidcSpaApi.d.ts +8 -0
- package/react-spa/createOidcSpaApi.js +423 -0
- package/react-spa/createOidcSpaApi.js.map +1 -0
- package/react-spa/index.d.ts +2 -0
- package/react-spa/index.js +6 -0
- package/react-spa/index.js.map +1 -0
- package/react-spa/types.d.ts +279 -0
- package/react-spa/types.js +3 -0
- package/react-spa/types.js.map +1 -0
- package/src/angular.ts +1 -1
- package/src/core/BASE_URL.ts +9 -0
- package/src/core/OidcMetadata.ts +75 -0
- package/src/core/createOidc.ts +273 -147
- package/src/core/diagnostic.ts +21 -2
- package/src/core/earlyInit.ts +14 -11
- package/src/core/loginOrGoToAuthServer.ts +0 -22
- package/src/core/loginSilent.ts +4 -27
- package/src/core/prShouldLoadApp.ts +11 -0
- package/src/keycloak/keycloak-js/Keycloak.ts +2 -2
- package/src/keycloak/keycloakIssuerUriParsed.ts +10 -1
- package/src/mock/oidc.ts +9 -3
- package/src/react-spa/apiBuilder.ts +70 -0
- package/src/react-spa/createOidcSpaApi.tsx +527 -0
- package/src/react-spa/index.ts +4 -0
- package/src/react-spa/types.tsx +308 -0
- package/src/tanstack-start/react/apiBuilder.ts +0 -1
- package/src/tanstack-start/react/createOidcSpaApi.tsx +24 -20
- package/src/tanstack-start/react/types.tsx +3 -4
- package/src/tools/isLikelyDevServer.ts +17 -0
- package/src/vite-plugin/handleClientEntrypoint.ts +5 -5
- package/src/vite-plugin/manageOptimizedDeps.ts +64 -0
- package/src/vite-plugin/projectType.ts +18 -0
- package/src/vite-plugin/vite-plugin.ts +40 -10
- package/tools/isLikelyDevServer.d.ts +1 -0
- package/tools/isLikelyDevServer.js +17 -0
- package/tools/isLikelyDevServer.js.map +1 -0
- package/vite-plugin/handleClientEntrypoint.d.ts +2 -0
- package/vite-plugin/handleClientEntrypoint.js +3 -4
- package/vite-plugin/handleClientEntrypoint.js.map +1 -1
- package/vite-plugin/manageOptimizedDeps.d.ts +6 -0
- package/vite-plugin/{excludeModuleExportFromOptimizedDeps.js → manageOptimizedDeps.js} +42 -7
- package/vite-plugin/manageOptimizedDeps.js.map +1 -0
- package/vite-plugin/projectType.d.ts +4 -0
- package/vite-plugin/projectType.js +15 -0
- package/vite-plugin/projectType.js.map +1 -0
- package/vite-plugin/{transformCreateFileRoute.js → transformTanstackRouterCreateFileRoute.js} +1 -1
- package/vite-plugin/transformTanstackRouterCreateFileRoute.js.map +1 -0
- package/vite-plugin/vite-plugin.d.ts +1 -1
- package/vite-plugin/vite-plugin.js +28 -8
- package/vite-plugin/vite-plugin.js.map +1 -1
- package/esm/tools/infer_import_meta_env_BASE_URL.d.ts +0 -1
- package/esm/tools/infer_import_meta_env_BASE_URL.js +0 -15
- package/esm/tools/infer_import_meta_env_BASE_URL.js.map +0 -1
- package/src/tools/infer_import_meta_env_BASE_URL.ts +0 -19
- package/src/vite-plugin/detectProjectType.ts +0 -20
- package/src/vite-plugin/excludeModuleExportFromOptimizedDeps.ts +0 -20
- package/vite-plugin/detectProjectType.d.ts +0 -10
- package/vite-plugin/detectProjectType.js +0 -15
- package/vite-plugin/detectProjectType.js.map +0 -1
- package/vite-plugin/excludeModuleExportFromOptimizedDeps.d.ts +0 -4
- package/vite-plugin/excludeModuleExportFromOptimizedDeps.js.map +0 -1
- package/vite-plugin/transformCreateFileRoute.js.map +0 -1
- /package/src/vite-plugin/{transformCreateFileRoute.ts → transformTanstackRouterCreateFileRoute.ts} +0 -0
- /package/vite-plugin/{transformCreateFileRoute.d.ts → transformTanstackRouterCreateFileRoute.d.ts} +0 -0
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";
|
|
@@ -49,8 +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
|
|
53
|
-
import {
|
|
52
|
+
import { prShouldLoadApp } from "./prShouldLoadApp";
|
|
53
|
+
import { getBASE_URL } from "./BASE_URL";
|
|
54
|
+
import { getIsLikelyDevServer } from "../tools/isLikelyDevServer";
|
|
55
|
+
import { createObjectThatThrowsIfAccessed } from "../tools/createObjectThatThrowsIfAccessed";
|
|
54
56
|
|
|
55
57
|
// NOTE: Replaced at build time
|
|
56
58
|
const VERSION = "{{OIDC_SPA_VERSION}}";
|
|
@@ -59,14 +61,6 @@ export type ParamsOfCreateOidc<
|
|
|
59
61
|
DecodedIdToken extends Record<string, unknown> = Oidc.Tokens.DecodedIdToken_OidcCoreSpec,
|
|
60
62
|
AutoLogin extends boolean = false
|
|
61
63
|
> = {
|
|
62
|
-
/**
|
|
63
|
-
* What should you put in this parameter?
|
|
64
|
-
* - Vite project: `BASE_URL: import.meta.env.BASE_URL`
|
|
65
|
-
* - Create React App project: `BASE_URL: process.env.PUBLIC_URL`
|
|
66
|
-
* - Other: `BASE_URL: "/"` (Usually, or `/dashboard` if your app is not at the root of the domain)
|
|
67
|
-
*/
|
|
68
|
-
homeUrl: string;
|
|
69
|
-
|
|
70
64
|
/**
|
|
71
65
|
* See: https://docs.oidc-spa.dev/v/v8/providers-configuration/provider-configuration
|
|
72
66
|
*/
|
|
@@ -194,6 +188,22 @@ export type ParamsOfCreateOidc<
|
|
|
194
188
|
* or non-standard deployments), and you cannot fix the server-side configuration.
|
|
195
189
|
*/
|
|
196
190
|
__metadata?: Partial<OidcMetadata>;
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* NOTE: This parameter is optional if you use the Vite plugin.
|
|
194
|
+
*
|
|
195
|
+
* This parameter let's you overwrite the value provided in
|
|
196
|
+
* oidcEarlyInit({ BASE_URL: xxx });
|
|
197
|
+
*
|
|
198
|
+
* What should you put in this parameter?
|
|
199
|
+
* - Vite project: `BASE_URL: import.meta.env.BASE_URL`
|
|
200
|
+
* - Create React App project: `BASE_URL: process.env.PUBLIC_URL`
|
|
201
|
+
* - Other: `BASE_URL: "/"` (Usually, or `/dashboard` if your app is not at the root of the domain)
|
|
202
|
+
*/
|
|
203
|
+
BASE_URL?: string;
|
|
204
|
+
|
|
205
|
+
/** @deprecated: Use BASE_URL (same thing, just renamed). */
|
|
206
|
+
homeUrl?: string;
|
|
197
207
|
};
|
|
198
208
|
|
|
199
209
|
const globalContext = {
|
|
@@ -314,11 +324,31 @@ export async function createOidc_nonMemoized<
|
|
|
314
324
|
log: typeof console.log | undefined;
|
|
315
325
|
}
|
|
316
326
|
): Promise<AutoLogin extends true ? Oidc.LoggedIn<DecodedIdToken> : Oidc<DecodedIdToken>> {
|
|
327
|
+
{
|
|
328
|
+
const timer = window.setTimeout(() => {
|
|
329
|
+
console.warn(
|
|
330
|
+
[
|
|
331
|
+
"oidc-spa: Setup error.",
|
|
332
|
+
"oidcEarlyInit() wasn't called.",
|
|
333
|
+
"This is supposed to be handled by the oidc-spa Vite plugin",
|
|
334
|
+
"or manually in other environments."
|
|
335
|
+
].join(" ")
|
|
336
|
+
);
|
|
337
|
+
}, 3_000);
|
|
338
|
+
|
|
339
|
+
const shouldLoadApp = await prShouldLoadApp;
|
|
340
|
+
|
|
341
|
+
window.clearTimeout(timer);
|
|
342
|
+
|
|
343
|
+
if (!shouldLoadApp) {
|
|
344
|
+
return new Promise<never>(() => {});
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
317
348
|
const {
|
|
318
349
|
transformUrlBeforeRedirect,
|
|
319
350
|
extraQueryParams: extraQueryParamsOrGetter,
|
|
320
351
|
extraTokenParams: extraTokenParamsOrGetter,
|
|
321
|
-
homeUrl: homeUrl_params,
|
|
322
352
|
decodedIdTokenSchema,
|
|
323
353
|
idleSessionLifetimeInSeconds,
|
|
324
354
|
autoLogoutParams = { redirectTo: "current page" },
|
|
@@ -330,6 +360,8 @@ export async function createOidc_nonMemoized<
|
|
|
330
360
|
noIframe = false
|
|
331
361
|
} = params;
|
|
332
362
|
|
|
363
|
+
const BASE_URL_params = params.BASE_URL ?? params.homeUrl;
|
|
364
|
+
|
|
333
365
|
const { issuerUri, clientId, scopes, configId, log } = preProcessedParams;
|
|
334
366
|
|
|
335
367
|
const getExtraQueryParams = (() => {
|
|
@@ -357,7 +389,29 @@ export async function createOidc_nonMemoized<
|
|
|
357
389
|
})();
|
|
358
390
|
|
|
359
391
|
const homeUrlAndRedirectUri = toFullyQualifiedUrl({
|
|
360
|
-
urlish:
|
|
392
|
+
urlish: (() => {
|
|
393
|
+
if (BASE_URL_params !== undefined) {
|
|
394
|
+
return BASE_URL_params;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const BASE_URL = getBASE_URL();
|
|
398
|
+
|
|
399
|
+
if (BASE_URL === undefined) {
|
|
400
|
+
throw new Error(
|
|
401
|
+
[
|
|
402
|
+
"oidc-spa: If you do not use the oidc-spa Vite plugin",
|
|
403
|
+
"you must provide the BASE_URL to the earlyInit() examples:",
|
|
404
|
+
"oidcSpaEarlyInit({ BASE_URL: import.meta.env.BASE_URL })",
|
|
405
|
+
"oidcSpaEarlyInit({ BASE_URL: '/' })",
|
|
406
|
+
"",
|
|
407
|
+
"You can also pass this parameter to createOidc({ BASE_URL: '...' })",
|
|
408
|
+
"or bootstrapOidc({ BASE_URL: '...' })"
|
|
409
|
+
].join("\n")
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return BASE_URL;
|
|
414
|
+
})(),
|
|
361
415
|
doAssertNoQueryParams: true,
|
|
362
416
|
doOutputWithTrailingSlash: true
|
|
363
417
|
});
|
|
@@ -378,92 +432,212 @@ export async function createOidc_nonMemoized<
|
|
|
378
432
|
|
|
379
433
|
const stateUrlParamValue_instance = generateStateUrlParamValue();
|
|
380
434
|
|
|
435
|
+
const oidcMetadata = __metadata ?? (await fetchOidcMetadata({ issuerUri }));
|
|
436
|
+
|
|
381
437
|
const canUseIframe = (() => {
|
|
382
438
|
if (noIframe) {
|
|
383
439
|
return false;
|
|
384
440
|
}
|
|
385
441
|
|
|
386
442
|
third_party_cookies: {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
url1: window.location.origin,
|
|
390
|
-
url2: issuerUri
|
|
391
|
-
}) === false;
|
|
392
|
-
|
|
393
|
-
if (!isOidcServerThirdPartyRelativeToApp) {
|
|
394
|
-
break third_party_cookies;
|
|
443
|
+
if (oidcMetadata === undefined) {
|
|
444
|
+
return false;
|
|
395
445
|
}
|
|
396
446
|
|
|
397
|
-
const
|
|
398
|
-
const ua = navigator.userAgent;
|
|
399
|
-
const vendor = navigator.vendor;
|
|
447
|
+
const { authorization_endpoint } = oidcMetadata;
|
|
400
448
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
+
});
|
|
405
459
|
|
|
406
|
-
if (
|
|
460
|
+
if (!isOidcServerThirdPartyRelativeToApp) {
|
|
407
461
|
break third_party_cookies;
|
|
408
462
|
}
|
|
409
463
|
|
|
410
|
-
|
|
411
|
-
[
|
|
412
|
-
"Can't use iframe because your auth server is on a third party domain relative",
|
|
413
|
-
"to the domain of your app and third party cookies are blocked by navigators."
|
|
414
|
-
].join(" ")
|
|
415
|
-
);
|
|
464
|
+
const isLikelyDevServer = getIsLikelyDevServer();
|
|
416
465
|
|
|
417
|
-
|
|
418
|
-
}
|
|
466
|
+
const domain_auth = new URL(authorization_endpoint).origin.split("//")[1];
|
|
419
467
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
468
|
+
assert(domain_auth !== undefined, "33921384");
|
|
469
|
+
|
|
470
|
+
const domain_here = window.location.origin.split("//")[1];
|
|
471
|
+
|
|
472
|
+
let isWellKnownProviderDomain = false;
|
|
473
|
+
let isIp = false;
|
|
423
474
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
authority: issuerUri,
|
|
429
|
-
client_id: clientId,
|
|
430
|
-
redirect_uri: homeUrlAndRedirectUri,
|
|
431
|
-
silent_redirect_uri: homeUrlAndRedirectUri,
|
|
432
|
-
post_logout_redirect_uri: homeUrlAndRedirectUri,
|
|
433
|
-
response_mode: isKeycloak({ issuerUri }) ? "fragment" : "query",
|
|
434
|
-
response_type: "code",
|
|
435
|
-
scope: Array.from(new Set(["openid", ...scopes])).join(" "),
|
|
436
|
-
automaticSilentRenew: false,
|
|
437
|
-
userStore: new WebStorageStateStore({
|
|
438
|
-
store: (() => {
|
|
439
|
-
if (canUseIframe) {
|
|
440
|
-
isUserStoreInMemoryOnly = true;
|
|
441
|
-
return new InMemoryWebStorage();
|
|
475
|
+
const suggestedDeployments = (() => {
|
|
476
|
+
if (/^(?:\d{1,3}\.){3}\d{1,3}$|^\[?[A-Fa-f0-9:]+\]?$/.test(domain_auth)) {
|
|
477
|
+
isIp = true;
|
|
478
|
+
return [];
|
|
442
479
|
}
|
|
443
480
|
|
|
444
|
-
|
|
481
|
+
const baseDomain = (() => {
|
|
482
|
+
const segments = domain_auth.split(".");
|
|
445
483
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
484
|
+
if (segments.length >= 3) {
|
|
485
|
+
segments.shift();
|
|
486
|
+
}
|
|
487
|
+
return segments.join(".");
|
|
488
|
+
})();
|
|
449
489
|
|
|
450
|
-
|
|
490
|
+
{
|
|
491
|
+
const baseDomain_low = baseDomain.toLowerCase();
|
|
451
492
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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 [];
|
|
455
502
|
}
|
|
503
|
+
}
|
|
456
504
|
|
|
457
|
-
|
|
458
|
-
});
|
|
505
|
+
const baseUrl = new URL(homeUrlAndRedirectUri).pathname;
|
|
459
506
|
|
|
460
|
-
return
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
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
|
+
});
|
|
467
641
|
|
|
468
642
|
const evtInitializationOutcomeUserNotLoggedIn = createEvt<void>();
|
|
469
643
|
|
|
@@ -493,6 +667,14 @@ export async function createOidc_nonMemoized<
|
|
|
493
667
|
backFromAuthServer: Oidc.LoggedIn["backFromAuthServer"]; // Undefined is silent signin
|
|
494
668
|
}
|
|
495
669
|
> => {
|
|
670
|
+
if (oidcMetadata === undefined) {
|
|
671
|
+
return (
|
|
672
|
+
await import("./diagnostic")
|
|
673
|
+
).createWellKnownOidcConfigurationEndpointUnreachableInitializationError({
|
|
674
|
+
issuerUri
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
|
|
496
678
|
handle_redirect_auth_response: {
|
|
497
679
|
let stateDataAndAuthResponse:
|
|
498
680
|
| { stateData: StateData.Redirect; authResponse: AuthResponse }
|
|
@@ -677,6 +859,8 @@ export async function createOidc_nonMemoized<
|
|
|
677
859
|
// NOTE: We almost never persist tokens, we have to only to support edge case
|
|
678
860
|
// of multiple oidc instance in a single App with no iframe support.
|
|
679
861
|
restore_from_session_storage: {
|
|
862
|
+
assert(isUserStoreInMemoryOnly !== undefined, "3392204");
|
|
863
|
+
|
|
680
864
|
if (isUserStoreInMemoryOnly) {
|
|
681
865
|
break restore_from_session_storage;
|
|
682
866
|
}
|
|
@@ -747,20 +931,6 @@ export async function createOidc_nonMemoized<
|
|
|
747
931
|
}
|
|
748
932
|
|
|
749
933
|
if (!canUseIframe) {
|
|
750
|
-
if (
|
|
751
|
-
!(await getIsValidRemoteJson(
|
|
752
|
-
`${issuerUri}${id<typeof WELL_KNOWN_PATH>(
|
|
753
|
-
"/.well-known/openid-configuration"
|
|
754
|
-
)}`
|
|
755
|
-
))
|
|
756
|
-
) {
|
|
757
|
-
return (
|
|
758
|
-
await import("./diagnostic")
|
|
759
|
-
).createWellKnownOidcConfigurationEndpointUnreachableInitializationError({
|
|
760
|
-
issuerUri
|
|
761
|
-
});
|
|
762
|
-
}
|
|
763
|
-
|
|
764
934
|
break actual_silent_signin;
|
|
765
935
|
}
|
|
766
936
|
|
|
@@ -781,26 +951,13 @@ export async function createOidc_nonMemoized<
|
|
|
781
951
|
|
|
782
952
|
assert(result_loginSilent.outcome !== "token refreshed using refresh token", "876995");
|
|
783
953
|
|
|
784
|
-
if (result_loginSilent.outcome === "
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
});
|
|
792
|
-
case "timeout":
|
|
793
|
-
return (await import("./diagnostic")).createIframeTimeoutInitializationError(
|
|
794
|
-
{
|
|
795
|
-
redirectUri: homeUrlAndRedirectUri,
|
|
796
|
-
clientId,
|
|
797
|
-
issuerUri,
|
|
798
|
-
noIframe
|
|
799
|
-
}
|
|
800
|
-
);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
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
|
+
});
|
|
804
961
|
}
|
|
805
962
|
|
|
806
963
|
assert<Equals<typeof result_loginSilent.outcome, "got auth response from iframe">>();
|
|
@@ -864,9 +1021,7 @@ export async function createOidc_nonMemoized<
|
|
|
864
1021
|
});
|
|
865
1022
|
}
|
|
866
1023
|
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
loginOrGoToAuthServer({
|
|
1024
|
+
await loginOrGoToAuthServer({
|
|
870
1025
|
action: "login",
|
|
871
1026
|
doForceReloadOnBfCache: true,
|
|
872
1027
|
redirectUrl: getRootRelativeOriginalLocationHref(),
|
|
@@ -885,19 +1040,7 @@ export async function createOidc_nonMemoized<
|
|
|
885
1040
|
}
|
|
886
1041
|
|
|
887
1042
|
return "ensure no interaction";
|
|
888
|
-
})()
|
|
889
|
-
onCantFetchWellKnownEndpointError: () => {
|
|
890
|
-
dCantFetchWellKnownEndpointOrNever.resolve();
|
|
891
|
-
}
|
|
892
|
-
});
|
|
893
|
-
|
|
894
|
-
await dCantFetchWellKnownEndpointOrNever.pr;
|
|
895
|
-
|
|
896
|
-
return (
|
|
897
|
-
await import("./diagnostic")
|
|
898
|
-
).createFailedToFetchTokenEndpointInitializationError({
|
|
899
|
-
clientId,
|
|
900
|
-
issuerUri
|
|
1043
|
+
})()
|
|
901
1044
|
});
|
|
902
1045
|
}
|
|
903
1046
|
|
|
@@ -1018,11 +1161,7 @@ export async function createOidc_nonMemoized<
|
|
|
1018
1161
|
interaction:
|
|
1019
1162
|
getPersistedAuthState({ configId }) === "explicitly logged out"
|
|
1020
1163
|
? "ensure interaction"
|
|
1021
|
-
: "directly redirect if active session show login otherwise"
|
|
1022
|
-
onCantFetchWellKnownEndpointError: () => {
|
|
1023
|
-
log?.("Login called but the auth server seems to be down..");
|
|
1024
|
-
alert("Authentication unavailable please try again later.");
|
|
1025
|
-
}
|
|
1164
|
+
: "directly redirect if active session show login otherwise"
|
|
1026
1165
|
});
|
|
1027
1166
|
},
|
|
1028
1167
|
initializationError: undefined
|
|
@@ -1254,16 +1393,7 @@ export async function createOidc_nonMemoized<
|
|
|
1254
1393
|
extraQueryParams_local: undefined,
|
|
1255
1394
|
transformUrlBeforeRedirect_local: undefined,
|
|
1256
1395
|
doNavigateBackToLastPublicUrlIfTheTheUserNavigateBack: false,
|
|
1257
|
-
interaction: "directly redirect if active session show login otherwise"
|
|
1258
|
-
onCantFetchWellKnownEndpointError: () => {
|
|
1259
|
-
log?.(
|
|
1260
|
-
[
|
|
1261
|
-
"The auth server seems to be down while we needed to refresh the token",
|
|
1262
|
-
"with a full page redirect. Reloading the page"
|
|
1263
|
-
].join(" ")
|
|
1264
|
-
);
|
|
1265
|
-
window.location.reload();
|
|
1266
|
-
}
|
|
1396
|
+
interaction: "directly redirect if active session show login otherwise"
|
|
1267
1397
|
});
|
|
1268
1398
|
assert(false, "136134");
|
|
1269
1399
|
};
|
|
@@ -1298,10 +1428,10 @@ export async function createOidc_nonMemoized<
|
|
|
1298
1428
|
log
|
|
1299
1429
|
});
|
|
1300
1430
|
|
|
1301
|
-
if (result_loginSilent.outcome === "
|
|
1431
|
+
if (result_loginSilent.outcome === "timeout") {
|
|
1302
1432
|
log?.(
|
|
1303
1433
|
[
|
|
1304
|
-
`Silent refresh of the token failed
|
|
1434
|
+
`Silent refresh of the token failed the iframe didn't post a response (timeout).`,
|
|
1305
1435
|
`This isn't recoverable, reloading the page.`
|
|
1306
1436
|
].join(" ")
|
|
1307
1437
|
);
|
|
@@ -1491,11 +1621,7 @@ export async function createOidc_nonMemoized<
|
|
|
1491
1621
|
action: "go to auth server",
|
|
1492
1622
|
redirectUrl: redirectUrl ?? window.location.href,
|
|
1493
1623
|
extraQueryParams_local: extraQueryParams,
|
|
1494
|
-
transformUrlBeforeRedirect_local: transformUrlBeforeRedirect
|
|
1495
|
-
onCantFetchWellKnownEndpointError: () => {
|
|
1496
|
-
log?.("goToAuthServer called but the auth server seems to be down..");
|
|
1497
|
-
alert("Authentication unavailable please try again later.");
|
|
1498
|
-
}
|
|
1624
|
+
transformUrlBeforeRedirect_local: transformUrlBeforeRedirect
|
|
1499
1625
|
}),
|
|
1500
1626
|
backFromAuthServer: resultOfLoginProcess.backFromAuthServer,
|
|
1501
1627
|
isNewBrowserSession: (() => {
|
package/src/core/diagnostic.ts
CHANGED
|
@@ -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: [
|
package/src/core/earlyInit.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
preventSessionStorageSetItemOfPublicKeyByThirdParty
|
|
8
8
|
} from "./iframeMessageProtection";
|
|
9
9
|
import { setOidcRequiredPostHydrationReplaceNavigationUrl } from "./requiredPostHydrationReplaceNavigationUrl";
|
|
10
|
+
import { setBASE_URL } from "./BASE_URL";
|
|
11
|
+
import { resolvePrShouldLoadApp } from "./prShouldLoadApp";
|
|
10
12
|
import { isBrowser } from "../tools/isBrowser";
|
|
11
13
|
|
|
12
14
|
let hasEarlyInitBeenCalled = false;
|
|
@@ -18,6 +20,7 @@ export function oidcEarlyInit(params: {
|
|
|
18
20
|
// Will be made mandatory next major.
|
|
19
21
|
freezeWebSocket?: boolean;
|
|
20
22
|
isPostLoginRedirectManual?: boolean;
|
|
23
|
+
BASE_URL?: string;
|
|
21
24
|
}) {
|
|
22
25
|
if (hasEarlyInitBeenCalled) {
|
|
23
26
|
throw new Error("oidc-spa: oidcEarlyInit() Should be called only once");
|
|
@@ -35,8 +38,9 @@ export function oidcEarlyInit(params: {
|
|
|
35
38
|
freezeFetch,
|
|
36
39
|
freezeXMLHttpRequest,
|
|
37
40
|
freezeWebSocket = false,
|
|
38
|
-
isPostLoginRedirectManual = false
|
|
39
|
-
|
|
41
|
+
isPostLoginRedirectManual = false,
|
|
42
|
+
BASE_URL
|
|
43
|
+
} = params;
|
|
40
44
|
|
|
41
45
|
const { shouldLoadApp } = handleOidcCallback({ isPostLoginRedirectManual });
|
|
42
46
|
|
|
@@ -83,8 +87,14 @@ export function oidcEarlyInit(params: {
|
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
preventSessionStorageSetItemOfPublicKeyByThirdParty();
|
|
90
|
+
|
|
91
|
+
if (BASE_URL !== undefined) {
|
|
92
|
+
setBASE_URL({ BASE_URL });
|
|
93
|
+
}
|
|
86
94
|
}
|
|
87
95
|
|
|
96
|
+
resolvePrShouldLoadApp({ shouldLoadApp });
|
|
97
|
+
|
|
88
98
|
return { shouldLoadApp };
|
|
89
99
|
}
|
|
90
100
|
|
|
@@ -93,15 +103,8 @@ let redirectAuthResponse: AuthResponse | undefined = undefined;
|
|
|
93
103
|
export function getRedirectAuthResponse():
|
|
94
104
|
| { authResponse: AuthResponse; clearAuthResponse: () => void }
|
|
95
105
|
| { authResponse: undefined; clearAuthResponse?: never } {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
[
|
|
99
|
-
"oidc-spa setup error.",
|
|
100
|
-
"oidcEarlyInit() wasn't called.",
|
|
101
|
-
"In newer version, using oidc-spa/entrypoint is no longer optional."
|
|
102
|
-
].join(" ")
|
|
103
|
-
);
|
|
104
|
-
}
|
|
106
|
+
assert(hasEarlyInitBeenCalled, "34933395");
|
|
107
|
+
|
|
105
108
|
return redirectAuthResponse === undefined
|
|
106
109
|
? { authResponse: undefined }
|
|
107
110
|
: {
|