@thunderid/browser 1.14.1 → 1.16.0

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/index.js CHANGED
@@ -170,6 +170,30 @@ var BackendClient = class BackendClient {
170
170
  }).toString()}`;
171
171
  }
172
172
  /**
173
+ * Switches the session to the organization unit `ouId` at the backend, without leaving the page. On
174
+ * success the cached session is dropped, so the next read returns the unit's; on a refusal the
175
+ * session stays as it was.
176
+ *
177
+ * @returns The refusal, with the backend's OAuth `error` when it sent one, or `undefined` on success.
178
+ */
179
+ async switchOrganizationUnit(ouId) {
180
+ const url = `${this.endpoints.ouSwitch}?${new URLSearchParams({ ouId }).toString()}`;
181
+ const readError = async (response$1) => (await response$1.json().catch(() => ({}))).error;
182
+ let response = await this.send(url, "POST");
183
+ let error = response.ok ? void 0 : await readError(response);
184
+ if (response.status === 401 && error === "session_expired") {
185
+ if (!await this.refresh()) return { error: "login_required" };
186
+ response = await this.send(url, "POST");
187
+ error = response.ok ? void 0 : await readError(response);
188
+ }
189
+ if (response.ok) {
190
+ this.session = void 0;
191
+ return;
192
+ }
193
+ if (error === "login_required") this.markSignedOut();
194
+ return error ? { error } : {};
195
+ }
196
+ /**
173
197
  * Ends the backend session.
174
198
  *
175
199
  * @returns The URL the browser visits to end the session at the authorization server.
@@ -3063,7 +3087,10 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends ThunderIDJavaS
3063
3087
  * - Embedded mode starts an `AUTHENTICATION` flow with `ouId`, presenting the SSO session handles kept
3064
3088
  * from earlier flow steps. A flow that needs input fails with `interaction_required`; render the
3065
3089
  * sign-in for the unit instead.
3066
- * - Backend mode sends the page to the backend's sign-in endpoint with `ouId`.
3090
+ * - Backend mode sends `POST {ouSwitch}?ouId=` to the backend, which switches its session, then reads
3091
+ * the session again, so the page stays where it is. When the backend needs the user, it sends the
3092
+ * page to the backend's sign-in endpoint with `ouId` (unless `redirect` is `false`). The extra
3093
+ * parameters do not apply.
3067
3094
  *
3068
3095
  * A failed switch leaves the previous session as it was.
3069
3096
  *
@@ -3072,11 +3099,7 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends ThunderIDJavaS
3072
3099
  async switchOrganizationUnit(organizationUnitId, options = {}) {
3073
3100
  await this.isInitialized();
3074
3101
  if (typeof organizationUnitId !== "string" || organizationUnitId.trim() === "") throw new ThunderIDAPIError("An organization unit identifier is required.", OrganizationUnitSwitchErrorCodes.InvalidOrganizationUnit, "browser", 400);
3075
- if (this._backend) {
3076
- location.href = this._backend.getSignInUrl(`${window.location.pathname}${window.location.search}`, organizationUnitId);
3077
- await SPAUtils_default.waitTillPageRedirect();
3078
- return;
3079
- }
3102
+ if (this._backend) return this._switchOrganizationUnitOnBackend(organizationUnitId, options.redirect !== false);
3080
3103
  const { redirect = true,...params } = options;
3081
3104
  const sm = this.getStorageManager();
3082
3105
  const config = await sm.getConfigData();
@@ -3110,6 +3133,28 @@ var ThunderIDBrowserClient = class ThunderIDBrowserClient extends ThunderIDJavaS
3110
3133
  await SPAUtils_default.waitTillPageRedirect();
3111
3134
  }
3112
3135
  /**
3136
+ * Backend mode: asks the backend's `ouSwitch` endpoint to switch, then reads its session again, so the
3137
+ * page stays where it is. When the backend needs the user, the page goes to the backend's sign-in for
3138
+ * the unit instead, unless `redirect` is off.
3139
+ */
3140
+ async _switchOrganizationUnitOnBackend(organizationUnitId, redirect) {
3141
+ let refusal;
3142
+ try {
3143
+ refusal = await this._backend.switchOrganizationUnit(organizationUnitId);
3144
+ } catch (error) {
3145
+ throw ThunderIDBrowserClient._toSwitchError(void 0, error);
3146
+ }
3147
+ if (refusal) {
3148
+ if (!redirect || !refusal.error || !INTERACTION_ERRORS.includes(refusal.error)) throw ThunderIDBrowserClient._toSwitchError(refusal.error);
3149
+ location.href = this._backend.getSignInUrl(`${window.location.pathname}${window.location.search}`, organizationUnitId);
3150
+ await SPAUtils_default.waitTillPageRedirect();
3151
+ return;
3152
+ }
3153
+ const user = await this.getUser();
3154
+ this._emitHook(Hooks_default.SignIn, user);
3155
+ return user;
3156
+ }
3157
+ /**
3113
3158
  * Switches back-channel by exchanging the session's device secret at the unit's token endpoint.
3114
3159
  *
3115
3160
  * @returns The user, `false` when the server needs the user, or `undefined` when the session holds no