@thunderid/browser 1.11.0 → 1.12.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/dist/BackendClient.d.ts +3 -2
- package/dist/BackendClient.d.ts.map +1 -1
- package/dist/ThunderIDBrowserClient.d.ts +46 -1
- package/dist/ThunderIDBrowserClient.d.ts.map +1 -1
- package/dist/cjs/index.cjs +260 -9
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +259 -11
- package/dist/index.js.map +1 -1
- package/dist/utils/AuthenticationHelper.d.ts +1 -1
- package/dist/utils/AuthenticationHelper.d.ts.map +1 -1
- package/dist/utils/currentProjectStorage.d.ts +25 -0
- package/dist/utils/currentProjectStorage.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/BackendClient.d.ts
CHANGED
|
@@ -64,9 +64,10 @@ declare class BackendClient {
|
|
|
64
64
|
*/
|
|
65
65
|
refresh(): Promise<boolean>;
|
|
66
66
|
/**
|
|
67
|
-
* The URL that starts sign-in at the backend and comes back to `returnTo`.
|
|
67
|
+
* The URL that starts sign-in at the backend and comes back to `returnTo`. With `ouId`, the backend
|
|
68
|
+
* bounds the sign-in to that organization unit.
|
|
68
69
|
*/
|
|
69
|
-
getSignInUrl(returnTo: string): string;
|
|
70
|
+
getSignInUrl(returnTo: string, ouId?: string): string;
|
|
70
71
|
/**
|
|
71
72
|
* Ends the backend session.
|
|
72
73
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BackendClient.d.ts","sourceRoot":"","sources":["../src/BackendClient.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,cAAc,EAAE,wBAAwB,EAAE,WAAW,EAAyB,MAAM,uBAAuB,CAAC;AAEpH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAOzD;;;GAGG;AACH,cAAM,aAAa;IAcL,OAAO,CAAC,QAAQ,CAAC,SAAS;IAbtC,OAAO,CAAC,OAAO,CAAsC;IAErD,OAAO,CAAC,UAAU,CAA+B;IAEjD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,0FAA0F;IAC1F,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,SAAS,CAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;gBAE5B,SAAS,EAAE,wBAAwB;IAEhE;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIvC;;OAEG;IACH,aAAa,IAAI,IAAI;IAUrB;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAmBtC;;;;;OAKG;IACH,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,IAAI;IA0BtC;;;;;OAKG;IACH,UAAU,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAiBnD;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,wBAAwB,GAAG,OAAO;IAS1D;;;OAGG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAkB3B
|
|
1
|
+
{"version":3,"file":"BackendClient.d.ts","sourceRoot":"","sources":["../src/BackendClient.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,cAAc,EAAE,wBAAwB,EAAE,WAAW,EAAyB,MAAM,uBAAuB,CAAC;AAEpH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AAOzD;;;GAGG;AACH,cAAM,aAAa;IAcL,OAAO,CAAC,QAAQ,CAAC,SAAS;IAbtC,OAAO,CAAC,OAAO,CAAsC;IAErD,OAAO,CAAC,UAAU,CAA+B;IAEjD,OAAO,CAAC,gBAAgB,CAAS;IAEjC,0FAA0F;IAC1F,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,SAAS,CAAK;IAEtB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAsB;gBAE5B,SAAS,EAAE,wBAAwB;IAEhE;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAIvC;;OAEG;IACH,aAAa,IAAI,IAAI;IAUrB;;;;;OAKG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAmBtC;;;;;OAKG;IACH,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,IAAI;IA0BtC;;;;;OAKG;IACH,UAAU,CAAC,MAAM,UAAQ,GAAG,OAAO,CAAC,cAAc,CAAC;IAiBnD;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,wBAAwB,GAAG,OAAO;IAS1D;;;OAGG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAkB3B;;;OAGG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAIrD;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAiBhC;;;;;;OAMG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAkB3C;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAMhC;;OAEG;IACH,qBAAqB,IAAI,OAAO;IAIhC;;;;;OAKG;IACG,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAuBzD;;;OAGG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,GAAG;QAC3F,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACjC;YAIa,WAAW;IA4BzB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,IAAI;CAGb;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthorizeRequestParamValue, ThunderIDJavaScriptClient, User, IsomorphicCrypto, IdToken, OIDCEndpoints, Storage, TokenResponse, HttpRequestConfig, HttpResponse, UserProfile } from '@thunderid/javascript';
|
|
1
|
+
import { AuthorizeRequestParamValue, ThunderIDJavaScriptClient, User, IsomorphicCrypto, IdToken, OIDCEndpoints, Storage, TokenResponse, HttpRequestConfig, HttpResponse, UserProfile, SwitchOrganizationUnitOptions } from '@thunderid/javascript';
|
|
2
2
|
import FetchHttpClient from './FetchHttpClient';
|
|
3
3
|
import { BrowserAuthConfig } from './models/BrowserConfig';
|
|
4
4
|
import SignInConfig from './models/SignInConfig';
|
|
@@ -32,6 +32,51 @@ declare class ThunderIDBrowserClient<T = BrowserAuthConfig> extends ThunderIDJav
|
|
|
32
32
|
}): Promise<User | undefined>;
|
|
33
33
|
private _signInInternal;
|
|
34
34
|
private _exchangeCodeForTokens;
|
|
35
|
+
/**
|
|
36
|
+
* Prepares the sign-out URL and the token refresh for tokens just stored, and reads the user.
|
|
37
|
+
*/
|
|
38
|
+
private _startSession;
|
|
39
|
+
/**
|
|
40
|
+
* Signs in again bounded to the organization unit `organizationUnitId`, and replaces the session with
|
|
41
|
+
* the one it gets. The server reuses the SSO session when the user can sign in there, so normally no
|
|
42
|
+
* credentials are asked.
|
|
43
|
+
*
|
|
44
|
+
* - Redirect mode exchanges the session's device secret at `{baseUrl}/ou/{ouId}/oauth2/token` when it
|
|
45
|
+
* holds one, which a sign-in with the `device_sso` scope returns. Otherwise it tries a `prompt=none`
|
|
46
|
+
* request to `{baseUrl}/ou/{ouId}/oauth2/authorize` in a hidden iframe. When the server needs the
|
|
47
|
+
* user, it redirects the page there (unless `redirect` is `false`), and the callback replaces the
|
|
48
|
+
* session.
|
|
49
|
+
* - Embedded mode starts an `AUTHENTICATION` flow with `ouId`, presenting the SSO session handles kept
|
|
50
|
+
* from earlier flow steps. A flow that needs input fails with `interaction_required`; render the
|
|
51
|
+
* sign-in for the unit instead.
|
|
52
|
+
* - Backend mode sends the page to the backend's sign-in endpoint with `ouId`.
|
|
53
|
+
*
|
|
54
|
+
* A failed switch leaves the previous session as it was.
|
|
55
|
+
*
|
|
56
|
+
* @throws {ThunderIDAPIError} With a code from `OrganizationUnitSwitchErrorCodes`.
|
|
57
|
+
*/
|
|
58
|
+
switchOrganizationUnit(organizationUnitId: string, options?: SwitchOrganizationUnitOptions): Promise<User | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Switches back-channel by exchanging the session's device secret at the unit's token endpoint.
|
|
61
|
+
*
|
|
62
|
+
* @returns The user, `false` when the server needs the user, or `undefined` when the session holds no
|
|
63
|
+
* device secret.
|
|
64
|
+
*/
|
|
65
|
+
private _switchOrganizationUnitWithDeviceSecret;
|
|
66
|
+
/**
|
|
67
|
+
* Maps an OAuth error from a bounded sign-in onto the switch's documented errors.
|
|
68
|
+
*/
|
|
69
|
+
private static _toSwitchError;
|
|
70
|
+
/**
|
|
71
|
+
* Embedded mode: starts a sign-in flow bounded to the unit. When the SSO session is reused, the flow
|
|
72
|
+
* completes at once and its assertion replaces the session.
|
|
73
|
+
*/
|
|
74
|
+
private _switchOrganizationUnitEmbedded;
|
|
75
|
+
/**
|
|
76
|
+
* Completes a switch that left the page for the unit's authorization endpoint: redeems the returned
|
|
77
|
+
* code, or reports the returned error and keeps the previous session.
|
|
78
|
+
*/
|
|
79
|
+
private _completeOrganizationUnitSwitch;
|
|
35
80
|
signInSilently(additionalParams?: Record<string, AuthorizeRequestParamValue>, tokenRequestConfig?: {
|
|
36
81
|
params: Record<string, unknown>;
|
|
37
82
|
}): Promise<User | boolean | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThunderIDBrowserClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDBrowserClient.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EAEzB,IAAI,EACJ,gBAAgB,EAChB,OAAO,EACP,aAAa,EAGb,OAAO,EACP,aAAa,EAGb,iBAAiB,EACjB,YAAY,EACZ,WAAW,
|
|
1
|
+
{"version":3,"file":"ThunderIDBrowserClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDBrowserClient.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -162,10 +162,14 @@ var BackendClient = class BackendClient {
|
|
|
162
162
|
return this.refreshing;
|
|
163
163
|
}
|
|
164
164
|
/**
|
|
165
|
-
* The URL that starts sign-in at the backend and comes back to `returnTo`.
|
|
165
|
+
* The URL that starts sign-in at the backend and comes back to `returnTo`. With `ouId`, the backend
|
|
166
|
+
* bounds the sign-in to that organization unit.
|
|
166
167
|
*/
|
|
167
|
-
getSignInUrl(returnTo) {
|
|
168
|
-
return `${this.endpoints.signIn}?${new URLSearchParams({
|
|
168
|
+
getSignInUrl(returnTo, ouId) {
|
|
169
|
+
return `${this.endpoints.signIn}?${new URLSearchParams({
|
|
170
|
+
returnTo,
|
|
171
|
+
...ouId ? { ouId } : {}
|
|
172
|
+
}).toString()}`;
|
|
169
173
|
}
|
|
170
174
|
/**
|
|
171
175
|
* Ends the backend session.
|
|
@@ -931,7 +935,7 @@ var AuthenticationHelper = class {
|
|
|
931
935
|
* @param timeout - How long to wait for the iframe's response, in milliseconds.
|
|
932
936
|
* @returns The user session, or `false` if the user is not signed in.
|
|
933
937
|
*/
|
|
934
|
-
async signInSilently(constructSilentSignInUrl, requestAccessToken, additionalParams, tokenRequestConfig, timeout = SILENT_SIGN_IN_TIMEOUT) {
|
|
938
|
+
async signInSilently(constructSilentSignInUrl, requestAccessToken, additionalParams, tokenRequestConfig, timeout = SILENT_SIGN_IN_TIMEOUT, onSignedOut) {
|
|
935
939
|
if (SPAUtils_default.isInitializedSilentSignIn()) {
|
|
936
940
|
await this.handleSilentSignInResponse();
|
|
937
941
|
return Promise.resolve({
|
|
@@ -966,6 +970,7 @@ var AuthenticationHelper = class {
|
|
|
966
970
|
const data = e.data;
|
|
967
971
|
if (data?.type === SILENT_SIGN_IN_SIGNED_OUT) {
|
|
968
972
|
cleanUp();
|
|
973
|
+
onSignedOut?.(typeof data?.data?.error === "string" ? data.data.error : void 0);
|
|
969
974
|
resolve(false);
|
|
970
975
|
}
|
|
971
976
|
if (data?.type === SILENT_SIGN_IN_SIGNED_IN && data?.data?.code) {
|
|
@@ -996,7 +1001,14 @@ var AuthenticationHelper = class {
|
|
|
996
1001
|
state
|
|
997
1002
|
},
|
|
998
1003
|
type: SILENT_SIGN_IN_SIGNED_IN
|
|
999
|
-
} : {
|
|
1004
|
+
} : {
|
|
1005
|
+
data: url.searchParams.get("error") ? {
|
|
1006
|
+
code: "",
|
|
1007
|
+
error: url.searchParams.get("error") ?? "",
|
|
1008
|
+
state
|
|
1009
|
+
} : void 0,
|
|
1010
|
+
type: SILENT_SIGN_IN_SIGNED_OUT
|
|
1011
|
+
};
|
|
1000
1012
|
window.parent.postMessage(message, window.location.origin);
|
|
1001
1013
|
window.location.href = "about:blank";
|
|
1002
1014
|
await SPAUtils_default.waitTillPageRedirect();
|
|
@@ -2787,6 +2799,24 @@ var SPAHelper_default = SPAHelper;
|
|
|
2787
2799
|
|
|
2788
2800
|
//#endregion
|
|
2789
2801
|
//#region src/ThunderIDBrowserClient.ts
|
|
2802
|
+
/**
|
|
2803
|
+
* OAuth errors that mean the server needs the user, so a silent switch falls back to a redirect.
|
|
2804
|
+
*/
|
|
2805
|
+
const INTERACTION_ERRORS = [
|
|
2806
|
+
"interaction_required",
|
|
2807
|
+
"login_required",
|
|
2808
|
+
"consent_required",
|
|
2809
|
+
"account_selection_required"
|
|
2810
|
+
];
|
|
2811
|
+
/**
|
|
2812
|
+
* OAuth errors for a device secret the server cannot use, which the SDK drops before signing in again.
|
|
2813
|
+
*/
|
|
2814
|
+
const UNUSABLE_DEVICE_SECRET_ERRORS = ["invalid_request", "invalid_grant"];
|
|
2815
|
+
/**
|
|
2816
|
+
* Temporary-data key that marks a switch to another organization unit left the page, so its callback is
|
|
2817
|
+
* redeemed although the previous session is still signed in.
|
|
2818
|
+
*/
|
|
2819
|
+
const ORGANIZATION_UNIT_SWITCH_KEY = "organization_unit_switch";
|
|
2790
2820
|
const logger$2 = (0, __thunderid_javascript.createPackageComponentLogger)("@thunderid/browser", "ThunderIDBrowserClient");
|
|
2791
2821
|
const BROWSER_DEFAULT_CONFIG = {
|
|
2792
2822
|
autoLogoutOnTokenRefreshError: false,
|
|
@@ -2920,7 +2950,8 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends __thunderid_ja
|
|
|
2920
2950
|
await this.isInitialized();
|
|
2921
2951
|
if (this._backend) {
|
|
2922
2952
|
if (config?.callOnlyOnRedirect) return;
|
|
2923
|
-
|
|
2953
|
+
const backendOuId = config?.["organizationUnitId"];
|
|
2954
|
+
location.href = this._backend.getSignInUrl(`${window.location.pathname}${window.location.search}`, typeof backendOuId === "string" && backendOuId !== "" ? backendOuId : void 0);
|
|
2924
2955
|
await SPAUtils_default.waitTillPageRedirect();
|
|
2925
2956
|
return;
|
|
2926
2957
|
}
|
|
@@ -2933,6 +2964,8 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends __thunderid_ja
|
|
|
2933
2964
|
async _signInInternal(signInConfig, authorizationCode, state, tokenRequestConfig) {
|
|
2934
2965
|
const sm = this.getStorageManager();
|
|
2935
2966
|
const config = await sm.getConfigData();
|
|
2967
|
+
const switchedUser = await this._completeOrganizationUnitSwitch(tokenRequestConfig);
|
|
2968
|
+
if (switchedUser) return switchedUser;
|
|
2936
2969
|
const basicUserInfo = await this._authHelper.handleSignIn();
|
|
2937
2970
|
if (basicUserInfo) return basicUserInfo;
|
|
2938
2971
|
let resolvedAuthorizationCode;
|
|
@@ -2984,14 +3017,186 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends __thunderid_ja
|
|
|
2984
3017
|
await this.setPKCECode(pkce, pkceKey);
|
|
2985
3018
|
}
|
|
2986
3019
|
await this.requestAccessToken(authorizationCode, state ?? "", void 0, tokenRequestConfig);
|
|
3020
|
+
return this._startSession(config.clientId);
|
|
3021
|
+
}
|
|
3022
|
+
/**
|
|
3023
|
+
* Prepares the sign-out URL and the token refresh for tokens just stored, and reads the user.
|
|
3024
|
+
*/
|
|
3025
|
+
async _startSession(clientId) {
|
|
2987
3026
|
try {
|
|
2988
3027
|
const signOutUrl = await this.getSignOutUrl();
|
|
2989
|
-
SPAUtils_default.setSignOutURL(signOutUrl,
|
|
3028
|
+
SPAUtils_default.setSignOutURL(signOutUrl, clientId, this._browserInstanceId);
|
|
2990
3029
|
} catch {}
|
|
2991
3030
|
await this._spaHelper.clearRefreshTokenTimeout();
|
|
2992
3031
|
await this._spaHelper.refreshAccessTokenAutomatically(() => this.refreshAccessToken());
|
|
2993
3032
|
return this.getUser();
|
|
2994
3033
|
}
|
|
3034
|
+
/**
|
|
3035
|
+
* Signs in again bounded to the organization unit `organizationUnitId`, and replaces the session with
|
|
3036
|
+
* the one it gets. The server reuses the SSO session when the user can sign in there, so normally no
|
|
3037
|
+
* credentials are asked.
|
|
3038
|
+
*
|
|
3039
|
+
* - Redirect mode exchanges the session's device secret at `{baseUrl}/ou/{ouId}/oauth2/token` when it
|
|
3040
|
+
* holds one, which a sign-in with the `device_sso` scope returns. Otherwise it tries a `prompt=none`
|
|
3041
|
+
* request to `{baseUrl}/ou/{ouId}/oauth2/authorize` in a hidden iframe. When the server needs the
|
|
3042
|
+
* user, it redirects the page there (unless `redirect` is `false`), and the callback replaces the
|
|
3043
|
+
* session.
|
|
3044
|
+
* - Embedded mode starts an `AUTHENTICATION` flow with `ouId`, presenting the SSO session handles kept
|
|
3045
|
+
* from earlier flow steps. A flow that needs input fails with `interaction_required`; render the
|
|
3046
|
+
* sign-in for the unit instead.
|
|
3047
|
+
* - Backend mode sends the page to the backend's sign-in endpoint with `ouId`.
|
|
3048
|
+
*
|
|
3049
|
+
* A failed switch leaves the previous session as it was.
|
|
3050
|
+
*
|
|
3051
|
+
* @throws {ThunderIDAPIError} With a code from `OrganizationUnitSwitchErrorCodes`.
|
|
3052
|
+
*/
|
|
3053
|
+
async switchOrganizationUnit(organizationUnitId, options = {}) {
|
|
3054
|
+
await this.isInitialized();
|
|
3055
|
+
if (typeof organizationUnitId !== "string" || organizationUnitId.trim() === "") throw new __thunderid_javascript.ThunderIDAPIError("An organization unit identifier is required.", __thunderid_javascript.OrganizationUnitSwitchErrorCodes.InvalidOrganizationUnit, "browser", 400);
|
|
3056
|
+
if (this._backend) {
|
|
3057
|
+
location.href = this._backend.getSignInUrl(`${window.location.pathname}${window.location.search}`, organizationUnitId);
|
|
3058
|
+
await SPAUtils_default.waitTillPageRedirect();
|
|
3059
|
+
return;
|
|
3060
|
+
}
|
|
3061
|
+
const { redirect = true,...params } = options;
|
|
3062
|
+
const sm = this.getStorageManager();
|
|
3063
|
+
const config = await sm.getConfigData();
|
|
3064
|
+
if (config?.mode === "embedded") return this._switchOrganizationUnitEmbedded(organizationUnitId, config);
|
|
3065
|
+
const exchangedUser = await this._switchOrganizationUnitWithDeviceSecret(organizationUnitId, config);
|
|
3066
|
+
if (exchangedUser) return exchangedUser;
|
|
3067
|
+
let silentError;
|
|
3068
|
+
let silentUser = false;
|
|
3069
|
+
if (exchangedUser === void 0) try {
|
|
3070
|
+
silentUser = await this._authHelper.signInSilently((additional) => this._constructSilentSignInUrl(additional), (code$1, s, trc) => this._exchangeCodeForTokens(code$1, s, trc), {
|
|
3071
|
+
...params,
|
|
3072
|
+
organizationUnitId
|
|
3073
|
+
}, void 0, config?.session?.silentSignIn?.timeout, (error) => {
|
|
3074
|
+
silentError = error;
|
|
3075
|
+
});
|
|
3076
|
+
} catch (error) {
|
|
3077
|
+
throw ThunderIDBrowserClient._toSwitchError(error instanceof Error ? error.message : void 0, error);
|
|
3078
|
+
}
|
|
3079
|
+
if (silentUser && typeof silentUser === "object") {
|
|
3080
|
+
this._emitHook(Hooks_default.SignIn, silentUser);
|
|
3081
|
+
return silentUser;
|
|
3082
|
+
}
|
|
3083
|
+
if (silentError && !INTERACTION_ERRORS.includes(silentError)) throw ThunderIDBrowserClient._toSwitchError(silentError);
|
|
3084
|
+
if (!redirect) throw ThunderIDBrowserClient._toSwitchError("interaction_required");
|
|
3085
|
+
const url = await this.getSignInUrl({
|
|
3086
|
+
...params,
|
|
3087
|
+
organizationUnitId
|
|
3088
|
+
});
|
|
3089
|
+
await sm.setTemporaryDataParameter(ORGANIZATION_UNIT_SWITCH_KEY, organizationUnitId);
|
|
3090
|
+
location.href = url;
|
|
3091
|
+
await SPAUtils_default.waitTillPageRedirect();
|
|
3092
|
+
}
|
|
3093
|
+
/**
|
|
3094
|
+
* Switches back-channel by exchanging the session's device secret at the unit's token endpoint.
|
|
3095
|
+
*
|
|
3096
|
+
* @returns The user, `false` when the server needs the user, or `undefined` when the session holds no
|
|
3097
|
+
* device secret.
|
|
3098
|
+
*/
|
|
3099
|
+
async _switchOrganizationUnitWithDeviceSecret(organizationUnitId, config) {
|
|
3100
|
+
let result;
|
|
3101
|
+
try {
|
|
3102
|
+
result = await this.switchOrganizationUnitWithDeviceSecret(organizationUnitId);
|
|
3103
|
+
} catch (error) {
|
|
3104
|
+
throw ThunderIDBrowserClient._toSwitchError(void 0, error);
|
|
3105
|
+
}
|
|
3106
|
+
if (!result) return;
|
|
3107
|
+
if ("error" in result) {
|
|
3108
|
+
if (INTERACTION_ERRORS.includes(result.error) || UNUSABLE_DEVICE_SECRET_ERRORS.includes(result.error)) return false;
|
|
3109
|
+
throw ThunderIDBrowserClient._toSwitchError(result.error);
|
|
3110
|
+
}
|
|
3111
|
+
const user = await this._startSession(config.clientId ?? "");
|
|
3112
|
+
this._emitHook(Hooks_default.SignIn, user);
|
|
3113
|
+
return user;
|
|
3114
|
+
}
|
|
3115
|
+
/**
|
|
3116
|
+
* Maps an OAuth error from a bounded sign-in onto the switch's documented errors.
|
|
3117
|
+
*/
|
|
3118
|
+
static _toSwitchError(oauthError, cause) {
|
|
3119
|
+
if (cause instanceof __thunderid_javascript.ThunderIDAPIError && Object.values(__thunderid_javascript.OrganizationUnitSwitchErrorCodes).includes(cause.code)) return cause;
|
|
3120
|
+
let code$1 = __thunderid_javascript.OrganizationUnitSwitchErrorCodes.Failed;
|
|
3121
|
+
if (oauthError === "unauthorized_client") code$1 = __thunderid_javascript.OrganizationUnitSwitchErrorCodes.UnauthorizedClient;
|
|
3122
|
+
else if (oauthError && INTERACTION_ERRORS.includes(oauthError)) code$1 = __thunderid_javascript.OrganizationUnitSwitchErrorCodes.InteractionRequired;
|
|
3123
|
+
const serverCode = oauthError ?? "switch_failed";
|
|
3124
|
+
return new __thunderid_javascript.ThunderIDAPIError(JSON.stringify({
|
|
3125
|
+
code: serverCode,
|
|
3126
|
+
message: { defaultValue: serverCode }
|
|
3127
|
+
}), code$1, "browser", oauthError === "unauthorized_client" ? 400 : void 0, void 0, "Switching the organization unit failed");
|
|
3128
|
+
}
|
|
3129
|
+
/**
|
|
3130
|
+
* Embedded mode: starts a sign-in flow bounded to the unit. When the SSO session is reused, the flow
|
|
3131
|
+
* completes at once and its assertion replaces the session.
|
|
3132
|
+
*/
|
|
3133
|
+
async _switchOrganizationUnitEmbedded(organizationUnitId, config) {
|
|
3134
|
+
let response;
|
|
3135
|
+
const sessionData = await this.getFlowSessions();
|
|
3136
|
+
try {
|
|
3137
|
+
response = await (0, __thunderid_javascript.executeEmbeddedSignInFlow)({
|
|
3138
|
+
baseUrl: config?.baseUrl,
|
|
3139
|
+
payload: {
|
|
3140
|
+
applicationId: config?.applicationId ?? "",
|
|
3141
|
+
flowType: __thunderid_javascript.EmbeddedFlowType.Authentication,
|
|
3142
|
+
ouId: organizationUnitId,
|
|
3143
|
+
...sessionData.length > 0 ? { sessionData } : {}
|
|
3144
|
+
},
|
|
3145
|
+
url: (0, __thunderid_javascript.resolveResourceEndpoint)("flowExecute", config)
|
|
3146
|
+
});
|
|
3147
|
+
} catch (error) {
|
|
3148
|
+
const serverCode = error instanceof __thunderid_javascript.ThunderIDAPIError ? error.serverError?.code : void 0;
|
|
3149
|
+
throw ThunderIDBrowserClient._toSwitchError(serverCode === "FES-1023" ? "unauthorized_client" : serverCode, error);
|
|
3150
|
+
}
|
|
3151
|
+
await this.storeFlowSessions(response);
|
|
3152
|
+
if (response?.flowStatus === __thunderid_javascript.EmbeddedSignInFlowStatus.Complete && response.assertion) {
|
|
3153
|
+
const claims = await this.decodeJwtToken(response.assertion);
|
|
3154
|
+
const iat = typeof claims["iat"] === "number" ? claims["iat"] : void 0;
|
|
3155
|
+
const exp = typeof claims["exp"] === "number" ? claims["exp"] : void 0;
|
|
3156
|
+
await this.setSession({
|
|
3157
|
+
access_token: response.assertion,
|
|
3158
|
+
created_at: iat ? iat * 1e3 : Date.now(),
|
|
3159
|
+
expires_in: exp && iat ? exp - iat : 3600,
|
|
3160
|
+
id_token: response.assertion,
|
|
3161
|
+
scope: claims["scope"],
|
|
3162
|
+
token_type: "Bearer"
|
|
3163
|
+
});
|
|
3164
|
+
const user = await this.getUser();
|
|
3165
|
+
this._emitHook(Hooks_default.SignIn, user);
|
|
3166
|
+
return user;
|
|
3167
|
+
}
|
|
3168
|
+
if (response?.flowStatus === __thunderid_javascript.EmbeddedSignInFlowStatus.Error) throw ThunderIDBrowserClient._toSwitchError("access_denied");
|
|
3169
|
+
throw ThunderIDBrowserClient._toSwitchError("interaction_required");
|
|
3170
|
+
}
|
|
3171
|
+
/**
|
|
3172
|
+
* Completes a switch that left the page for the unit's authorization endpoint: redeems the returned
|
|
3173
|
+
* code, or reports the returned error and keeps the previous session.
|
|
3174
|
+
*/
|
|
3175
|
+
async _completeOrganizationUnitSwitch(tokenRequestConfig) {
|
|
3176
|
+
const sm = this.getStorageManager();
|
|
3177
|
+
if (!await sm.getTemporaryDataParameter(ORGANIZATION_UNIT_SWITCH_KEY) || SPAUtils_default.isInitializedSilentSignIn()) return;
|
|
3178
|
+
const url = new URL(window.location.href);
|
|
3179
|
+
const code$1 = url.searchParams.get(__thunderid_javascript.OIDCRequestConstants.Params.AUTHORIZATION_CODE);
|
|
3180
|
+
const state = url.searchParams.get(__thunderid_javascript.OIDCRequestConstants.Params.STATE);
|
|
3181
|
+
const error = url.searchParams.get("error");
|
|
3182
|
+
if (code$1 && state) {
|
|
3183
|
+
await sm.removeTemporaryDataParameter(ORGANIZATION_UNIT_SWITCH_KEY);
|
|
3184
|
+
SPAUtils_default.removeAuthorizationCode();
|
|
3185
|
+
try {
|
|
3186
|
+
return await this._exchangeCodeForTokens(code$1, state, tokenRequestConfig);
|
|
3187
|
+
} catch (exchangeError) {
|
|
3188
|
+
throw ThunderIDBrowserClient._toSwitchError(void 0, exchangeError);
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
if (error) {
|
|
3192
|
+
await sm.removeTemporaryDataParameter(ORGANIZATION_UNIT_SWITCH_KEY);
|
|
3193
|
+
url.searchParams.delete("error");
|
|
3194
|
+
url.searchParams.delete("error_description");
|
|
3195
|
+
url.searchParams.delete(__thunderid_javascript.OIDCRequestConstants.Params.STATE);
|
|
3196
|
+
history.replaceState(null, document.title, url.toString());
|
|
3197
|
+
throw ThunderIDBrowserClient._toSwitchError(error);
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
2995
3200
|
async signInSilently(additionalParams, tokenRequestConfig) {
|
|
2996
3201
|
await this.isInitialized();
|
|
2997
3202
|
if (this._backend) return await this.isSignedIn() ? this.getUser() : false;
|
|
@@ -3288,13 +3493,14 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends __thunderid_ja
|
|
|
3288
3493
|
const config = await this.getStorageManager().getConfigData();
|
|
3289
3494
|
const urlString = await this.getSignInUrl({
|
|
3290
3495
|
prompt: "none",
|
|
3496
|
+
response_mode: "query",
|
|
3291
3497
|
state: SILENT_SIGN_IN_STATE,
|
|
3292
3498
|
...additionalParams
|
|
3293
3499
|
});
|
|
3294
3500
|
const urlObject = new URL(urlString);
|
|
3295
|
-
urlObject.searchParams.set("response_mode", "query");
|
|
3501
|
+
if (!urlObject.searchParams.has("request_uri")) urlObject.searchParams.set("response_mode", "query");
|
|
3296
3502
|
if (this._storage === BrowserStorage_default.BrowserMemory && config.enablePKCE) {
|
|
3297
|
-
const state = urlObject.searchParams.get(__thunderid_javascript.OIDCRequestConstants.Params.STATE);
|
|
3503
|
+
const state = urlObject.searchParams.get(__thunderid_javascript.OIDCRequestConstants.Params.STATE) ?? this.lastAuthorizeRequestState;
|
|
3298
3504
|
SPAUtils_default.setPKCE((0, __thunderid_javascript.extractPkceStorageKeyFromState)(state ?? ""), await this.getPKCECode(state ?? ""));
|
|
3299
3505
|
}
|
|
3300
3506
|
return urlObject.toString();
|
|
@@ -3379,6 +3585,48 @@ const copyTextToClipboard = async (text) => {
|
|
|
3379
3585
|
};
|
|
3380
3586
|
var copyTextToClipboard_default = copyTextToClipboard;
|
|
3381
3587
|
|
|
3588
|
+
//#endregion
|
|
3589
|
+
//#region src/utils/currentProjectStorage.ts
|
|
3590
|
+
/**
|
|
3591
|
+
* The `localStorage` key the current project is kept under, scoped to the vendor like the SDK's
|
|
3592
|
+
* other UI preferences.
|
|
3593
|
+
*
|
|
3594
|
+
* @param vendor - The vendor prefix.
|
|
3595
|
+
* @returns The key.
|
|
3596
|
+
*/
|
|
3597
|
+
const getCurrentProjectStorageKey = (vendor) => `${(0, __thunderid_javascript.getVendorPrefix)(vendor)}-current-project`;
|
|
3598
|
+
/**
|
|
3599
|
+
* Reads the project the user last chose. The current project is a client-side preference for the
|
|
3600
|
+
* management UI: it does not change the session, the tokens or what the server allows.
|
|
3601
|
+
*
|
|
3602
|
+
* @param vendor - The vendor prefix.
|
|
3603
|
+
* @returns The project, or `null` when none is kept or storage is unavailable.
|
|
3604
|
+
*/
|
|
3605
|
+
const readCurrentProject = (vendor) => {
|
|
3606
|
+
try {
|
|
3607
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
3608
|
+
const stored = window.localStorage.getItem(getCurrentProjectStorageKey(vendor));
|
|
3609
|
+
const parsed = stored ? JSON.parse(stored) : null;
|
|
3610
|
+
return parsed && typeof parsed === "object" && typeof parsed.id === "string" ? parsed : null;
|
|
3611
|
+
} catch {
|
|
3612
|
+
return null;
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3615
|
+
/**
|
|
3616
|
+
* Keeps the project the user chose, or forgets it with `null`.
|
|
3617
|
+
*
|
|
3618
|
+
* @param vendor - The vendor prefix.
|
|
3619
|
+
* @param project - The project, or `null`.
|
|
3620
|
+
*/
|
|
3621
|
+
const writeCurrentProject = (vendor, project) => {
|
|
3622
|
+
try {
|
|
3623
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
3624
|
+
const key = getCurrentProjectStorageKey(vendor);
|
|
3625
|
+
if (project) window.localStorage.setItem(key, JSON.stringify(project));
|
|
3626
|
+
else window.localStorage.removeItem(key);
|
|
3627
|
+
} catch {}
|
|
3628
|
+
};
|
|
3629
|
+
|
|
3382
3630
|
//#endregion
|
|
3383
3631
|
//#region src/utils/handleWebAuthnAuthentication.ts
|
|
3384
3632
|
const logger$1 = (0, __thunderid_javascript.createPackageComponentLogger)("@thunderid/browser", "WebAuthn");
|
|
@@ -4270,6 +4518,7 @@ exports.detectThemeMode = detectThemeMode;
|
|
|
4270
4518
|
exports.extractAvatarParamsFromUri = extractAvatarParamsFromUri_default;
|
|
4271
4519
|
exports.generateAvatarDataUri = generateAvatarDataUri_default;
|
|
4272
4520
|
exports.getActiveTheme = getActiveTheme_default;
|
|
4521
|
+
exports.getCurrentProjectStorageKey = getCurrentProjectStorageKey;
|
|
4273
4522
|
exports.handleWebAuthnAuthentication = handleWebAuthnAuthentication_default;
|
|
4274
4523
|
exports.hasAuthParamsInUrl = hasAuthParamsInUrl_default;
|
|
4275
4524
|
exports.hasCalledForThisInstanceInUrl = hasCalledForThisInstanceInUrl_default;
|
|
@@ -4279,8 +4528,10 @@ exports.navigate = navigate_default;
|
|
|
4279
4528
|
exports.normalizeBorderRadius = normalizeBorderRadius_default;
|
|
4280
4529
|
exports.pickAnonymousAvatarName = pickAnonymousAvatarName_default;
|
|
4281
4530
|
exports.pickAnonymousEntityName = pickAnonymousEntityName_default;
|
|
4531
|
+
exports.readCurrentProject = readCurrentProject;
|
|
4282
4532
|
exports.resolveEmojiUrisInHtml = resolveEmojiUrisInHtml_default;
|
|
4283
4533
|
exports.resolveLogoUri = resolveLogoUri_default;
|
|
4534
|
+
exports.writeCurrentProject = writeCurrentProject;
|
|
4284
4535
|
Object.keys(__thunderid_javascript).forEach(function (k) {
|
|
4285
4536
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
4286
4537
|
enumerable: true,
|