@strivacity/sdk-core 3.0.0-rc.0 → 3.0.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 (44) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +384 -79
  3. package/dist/flows/EmbeddedFlow.cjs +1 -1
  4. package/dist/flows/EmbeddedFlow.cjs.map +1 -1
  5. package/dist/flows/EmbeddedFlow.d.ts +2 -1
  6. package/dist/flows/EmbeddedFlow.mjs +1 -1
  7. package/dist/flows/EmbeddedFlow.mjs.map +1 -1
  8. package/dist/flows/NativeFlow.cjs +1 -1
  9. package/dist/flows/NativeFlow.cjs.map +1 -1
  10. package/dist/flows/NativeFlow.d.ts +1 -1
  11. package/dist/flows/NativeFlow.mjs +1 -1
  12. package/dist/flows/NativeFlow.mjs.map +1 -1
  13. package/dist/handlers/BaseFlowHandler.cjs +2 -0
  14. package/dist/handlers/BaseFlowHandler.cjs.map +1 -0
  15. package/dist/{utils/NativeFlowHandler.d.ts → handlers/BaseFlowHandler.d.ts} +11 -12
  16. package/dist/handlers/BaseFlowHandler.mjs +2 -0
  17. package/dist/handlers/BaseFlowHandler.mjs.map +1 -0
  18. package/dist/handlers/EmbeddedFlowHandler.cjs +2 -0
  19. package/dist/handlers/EmbeddedFlowHandler.cjs.map +1 -0
  20. package/dist/{utils → handlers}/EmbeddedFlowHandler.d.ts +3 -35
  21. package/dist/handlers/EmbeddedFlowHandler.mjs +2 -0
  22. package/dist/handlers/EmbeddedFlowHandler.mjs.map +1 -0
  23. package/dist/handlers/NativeFlowHandler.cjs +2 -0
  24. package/dist/handlers/NativeFlowHandler.cjs.map +1 -0
  25. package/dist/handlers/NativeFlowHandler.d.ts +30 -0
  26. package/dist/handlers/NativeFlowHandler.mjs +2 -0
  27. package/dist/handlers/NativeFlowHandler.mjs.map +1 -0
  28. package/dist/index.cjs +1 -1
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.ts +5 -2
  31. package/dist/index.mjs +1 -1
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/types.cjs.map +1 -1
  34. package/dist/types.d.ts +48 -56
  35. package/dist/types.mjs.map +1 -1
  36. package/package.json +7 -1
  37. package/dist/utils/EmbeddedFlowHandler.cjs +0 -2
  38. package/dist/utils/EmbeddedFlowHandler.cjs.map +0 -1
  39. package/dist/utils/EmbeddedFlowHandler.mjs +0 -2
  40. package/dist/utils/EmbeddedFlowHandler.mjs.map +0 -1
  41. package/dist/utils/NativeFlowHandler.cjs +0 -2
  42. package/dist/utils/NativeFlowHandler.cjs.map +0 -1
  43. package/dist/utils/NativeFlowHandler.mjs +0 -2
  44. package/dist/utils/NativeFlowHandler.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,36 @@
1
+ ## 3.0.1 (2026-04-20)
2
+
3
+ ### 🩹 Fixes
4
+
5
+ - handle language parameter from response body url correctly ([e42294b](https://github.com/Strivacity/sdk-js/commit/e42294b))
6
+
7
+ ### 🧱 Updated Dependencies
8
+
9
+ - Updated testing to 3.0.1
10
+
11
+ # 3.0.0 (2026-04-09)
12
+
13
+ ### 🚀 Features
14
+
15
+ - custom sdk mode added ([17812c6](https://github.com/Strivacity/sdk-js/commit/17812c6))
16
+ - ⚠️ EmbeddedFlow implemented ([a0e3ad8](https://github.com/Strivacity/sdk-js/commit/a0e3ad8))
17
+ - ⚠️ NativeFlow entry function now returns an object instead of a string ([9a8942d](https://github.com/Strivacity/sdk-js/commit/9a8942d))
18
+ - popupUrlHandler refactored ([886f6ea](https://github.com/Strivacity/sdk-js/commit/886f6ea))
19
+
20
+ ### 🩹 Fixes
21
+
22
+ - select and multiselect default value handling fixed ([25ecacd](https://github.com/Strivacity/sdk-js/commit/25ecacd))
23
+ - widget type definitions fixed ([c2e9b12](https://github.com/Strivacity/sdk-js/commit/c2e9b12))
24
+
25
+ ### ⚠️ Breaking Changes
26
+
27
+ - EmbeddedFlow implemented ([a0e3ad8](https://github.com/Strivacity/sdk-js/commit/a0e3ad8))
28
+ - NativeFlow entry function now returns an object instead of a string ([9a8942d](https://github.com/Strivacity/sdk-js/commit/9a8942d))
29
+
30
+ ### 🧱 Updated Dependencies
31
+
32
+ - Updated testing to 3.0.0
33
+
1
34
  ## 3.0.0-rc.0 (2026-02-18)
2
35
 
3
36
  ### 🚀 Features
package/README.md CHANGED
@@ -1,65 +1,90 @@
1
1
  # @strivacity/sdk-core
2
2
 
3
- ## Example App
3
+ A framework-agnostic JavaScript/TypeScript client that integrates Strivacity's policy-driven authentication journeys into any application using the OAuth 2.0 PKCE flow. Supports `redirect`, `popup`, `native`, and `embedded` modes.
4
+
5
+ See our [Developer Portal](https://www.strivacity.com/learn-support/developer-hub) to get started with developing with the Strivacity product.
6
+
7
+ ## Overview
8
+
9
+ This SDK provides the core authentication primitives for Strivacity's policy-driven journeys. It is a standalone JavaScript/TypeScript library with no framework dependencies that can be used directly or as the foundation for framework-specific SDKs (React, Vue, Angular, etc.). The SDK uses the OAuth 2.0 PKCE flow to authenticate with Strivacity.
10
+
11
+ ## Demo Application
4
12
 
5
13
  - [Example app](https://github.com/Strivacity/sdk-js/tree/main/apps/web-component)
6
14
 
7
- ### Install
15
+ ## Install
8
16
 
9
17
  ```bash
10
18
  npm install @strivacity/sdk-core
11
19
  ```
12
20
 
13
- ### Usage
21
+ ## Usage
22
+
23
+ ### Initialization
24
+
25
+ Create a flow instance using the `initFlow` factory function:
14
26
 
15
27
  ```js
16
28
  import { initFlow } from '@strivacity/sdk-core';
17
29
 
18
30
  const sdk = initFlow({
19
- mode: 'redirect', // or 'popup' or 'native'
31
+ mode: 'redirect', // or 'popup', 'native', 'embedded'
20
32
  issuer: 'https://<YOUR_DOMAIN>',
21
33
  scopes: ['openid', 'profile'],
22
34
  clientId: '<YOUR_CLIENT_ID>',
23
35
  redirectUri: '<YOUR_REDIRECT_URI>',
24
36
  });
37
+ ```
38
+
39
+ ### Redirect / Popup mode
25
40
 
41
+ In `redirect` mode the user is taken to the identity provider in the same window; in `popup` mode authentication happens in a popup. Both are initiated the same way from code.
42
+
43
+ #### Login
44
+
45
+ ```js
26
46
  await sdk.login();
27
47
  ```
28
48
 
29
- ### API Documentation
49
+ #### Callback handling
30
50
 
31
- #### `initFlow(options: SDKOptions & { mode?: 'popup' | 'redirect' | 'native' }): PopupFlow | RedirectFlow | NativeFlow`
51
+ Process the authorization callback after the identity provider redirects back to your application:
32
52
 
33
- The `initFlow` function initializes and returns an instance of either `PopupFlow`, `RedirectFlow`, or `NativeFlow`, based on the specified `mode`.
53
+ ```js
54
+ await sdk.handleCallback();
55
+ ```
34
56
 
35
- **Parameters:**
57
+ #### Logout
36
58
 
37
- - `options`: An object containing configuration options for the SDK.
59
+ The `postLogoutRedirectUri` parameter is optional and specifies where users are redirected after logout. This URI must be configured in the Admin Console as an allowed post-logout redirect URI.
38
60
 
39
- **Type:** `SDKOptions & { mode?: 'popup' | 'redirect' | 'native' }`
61
+ ```js
62
+ await sdk.logout({ postLogoutRedirectUri: location.origin });
63
+ ```
40
64
 
41
- **Properties:**
42
- - `issuer` (string): The issuer URL of the OpenID Provider.
43
- - `clientId` (string): The client identifier for the application.
44
- - `redirectUri` (string): The URI to redirect to after authentication.
45
- - `scopes` (Array<string>): The scopes to request during authentication.
46
- - `responseType` (ResponseType): The response type requested from the OpenID Provider.
47
- - `responseMode` (ResponseMode): The response mode to use.
48
- - `storageTokenName` (string): The name of the token in storage.
49
- - `storage` (SDKStorageType): A custom storage implementation.
65
+ #### Token refresh
50
66
 
51
- **Mode:**
52
- - `popup`: Uses a popup window for authentication. Returns an instance of `PopupFlow`.
53
- - `redirect`: Uses a full-page redirect for authentication. Returns an instance of `RedirectFlow`.
54
- - `native`: Uses a native flow for authentication. Returns an instance of `NativeFlow`.
67
+ Refreshes the access token using the stored refresh token, keeping the session alive without requiring the user to log in again.
55
68
 
56
- ## Custom native flow
69
+ ```js
70
+ await sdk.refresh();
71
+ ```
72
+
73
+ #### Token revocation
74
+
75
+ Revokes the current access and refresh tokens on the server, invalidating the session immediately.
76
+
77
+ ```js
78
+ await sdk.revoke();
79
+ ```
80
+
81
+ ### Native mode
57
82
 
58
- You can use the `NativeFlowHandler` class if there is no existing Strivacity implementation for your JavaScript framework, or if you want to build a fully custom authentication flow.
83
+ In `native` mode, `login()` returns a `NativeFlowHandler` instance that drives the authentication UI step by step.
59
84
 
60
- If you are looking for example implementations for different frameworks, visit [packages](https://github.com/Strivacity/sdk-js/tree/main/packages).
85
+ #### Login page example
61
86
 
62
- ### Usage
87
+ The login page extracts `session_id` and optionally `language` from the URL on load and passes them to `startSession()` to resume an existing flow or start a new one. When a `language` parameter is present it overrides `uiLocales` to display the authentication UI in the specified language:
63
88
 
64
89
  ```js
65
90
  import { initFlow } from '@strivacity/sdk-core';
@@ -72,60 +97,243 @@ const sdk = initFlow({
72
97
  redirectUri: '<YOUR_REDIRECT_URI>',
73
98
  });
74
99
 
75
- // This will return with a `NativeFlowHandler` instance
100
+ // Returns a NativeFlowHandler instance
76
101
  const handler = await sdk.login();
77
102
 
103
+ // Extract session_id from URL if present
104
+ const url = new URL(window.location.href);
105
+ const sessionId = url.searchParams.get('session_id');
106
+
78
107
  // Start a new session or resume an existing one
79
- const state = await handler.startSession();
108
+ const state = await handler.startSession(sessionId);
80
109
 
81
110
  if (state.finalizeUrl) {
82
- // If the response contains a finalize URL, you can finalize the session
111
+ // Finalize the session when the flow is complete
83
112
  await handler.finalizeSession(state.finalizeUrl);
84
113
  } else {
85
- // Handle the response as needed
86
- console.log('Form submitted successfully:', state);
114
+ // Render the form from state.widgets and handle user input
115
+ console.log('Current form state:', state);
87
116
  }
117
+ ```
88
118
 
89
- // Submit a form in the native flow
119
+ #### Submitting a form
120
+
121
+ ```js
90
122
  const formState = await handler.submitForm('formId', {
91
- // Your form data here
123
+ email: 'user@example.com',
124
+ password: 'secret',
92
125
  });
93
126
 
94
- if (state.finalizeUrl) {
95
- // If the response contains a finalize URL, you can finalize the session
96
- await handler.finalizeSession(state.finalizeUrl);
127
+ if (formState.finalizeUrl) {
128
+ await handler.finalizeSession(formState.finalizeUrl);
129
+ }
130
+ ```
131
+
132
+ #### Callback page example
133
+
134
+ When a `session_id` is present in the URL the native flow is resumed by forwarding it to the login page. Otherwise the standard `handleCallback()` path is used:
135
+
136
+ ```js
137
+ const url = new URL(location.href);
138
+ const sessionId = url.searchParams.get('session_id');
139
+
140
+ if (sessionId) {
141
+ // Forward to login page with session_id to resume the native flow
142
+ window.location.href = `/login?session_id=${sessionId}`;
97
143
  } else {
98
- // Handle the response as needed
99
- console.log('Form submitted successfully:', state);
144
+ try {
145
+ await sdk.handleCallback();
146
+ window.location.href = '/profile';
147
+ } catch (error) {
148
+ console.error('Error during callback handling:', error);
149
+ }
100
150
  }
101
151
  ```
102
152
 
103
- ---
153
+ #### Entry page example
154
+
155
+ The entry page processes flows started by an external process (e.g. password reset) by calling `entry()` to extract the necessary parameters to resume the flow:
156
+
157
+ ```js
158
+ try {
159
+ const data = await sdk.entry();
160
+
161
+ if (data && Object.keys(data).length > 0) {
162
+ window.location.href = `/callback?${new URLSearchParams(data).toString()}`;
163
+ } else {
164
+ window.location.href = '/';
165
+ }
166
+ } catch (error) {
167
+ console.error('Entry failed:', error);
168
+ window.location.href = '/';
169
+ }
170
+ ```
171
+
172
+ ### Custom mode
173
+
174
+ Custom mode lets you replace the built-in flow implementations with your own classes. This is useful when you need to proxy authentication through a backend server (BFF pattern) rather than communicating with the identity provider directly from the browser.
175
+
176
+ Pass `mode: 'custom'` together with a `customFlow` class that extends one of the built-in flow base classes (`NativeFlow`, `EmbeddedFlow`, etc.):
104
177
 
105
- ### API Documentation
178
+ ```ts
179
+ import { initFlow } from '@strivacity/sdk-core';
180
+ import { CustomNativeFlow } from './sdk/CustomNativeFlow';
106
181
 
107
- #### `startSession(sessionId?: string | null): Promise<LoginFlowState | void>`
182
+ const sdk = initFlow({
183
+ mode: 'custom',
184
+ issuer: 'https://<YOUR_DOMAIN>',
185
+ scopes: ['openid', 'profile'],
186
+ clientId: '<YOUR_CLIENT_ID>',
187
+ redirectUri: '<YOUR_REDIRECT_URI>',
188
+ customFlow: CustomNativeFlow,
189
+ });
190
+ ```
108
191
 
109
- Starts a new authentication session. If a `sessionId` is provided, resumes the session; otherwise, initiates a new one.
192
+ #### Creating a custom flow class
110
193
 
111
- #### `submitForm(formId?: string, body?: Record<string, unknown>): Promise<LoginFlowState>`
194
+ Extend `NativeFlow` (or `EmbeddedFlow`) and override the methods you need to change. The example below delegates session management to a backend API instead of calling the identity provider directly:
112
195
 
113
- Submits a form in the native flow. Optionally specify a form ID and request body.
196
+ ```ts
197
+ import type { NativeParams } from '@strivacity/sdk-core';
198
+ import { NativeFlow } from '@strivacity/sdk-core/flows/NativeFlow';
199
+ import { Session } from '@strivacity/sdk-core/utils/Session';
200
+ import { CustomNativeFlowHandler } from './CustomNativeFlowHandler';
114
201
 
115
- #### `finalizeSession(finalizeUrl: string): Promise<void>`
202
+ export class CustomNativeFlow extends NativeFlow {
203
+ override login(params: NativeParams = {}): CustomNativeFlowHandler {
204
+ this.dispatchEvent('loginInitiated', []);
205
+ return new CustomNativeFlowHandler(this, params);
206
+ }
116
207
 
117
- Finalizes the session using the provided URL. You can gather the finalize URL from the `LoginFlowState` returned by `startSession` or `submitForm`.
208
+ override register(params: NativeParams = {}): CustomNativeFlowHandler {
209
+ params.prompt = 'create';
210
+ return this.login(params);
211
+ }
118
212
 
119
- ---
213
+ async fetchSessionData(): Promise<void> {
214
+ const response = await this.httpClient.request(new URL('/api/session/info', location.origin).toString(), { method: 'GET', credentials: 'include' });
215
+
216
+ this.session = Object.assign(new Session(), await response.json());
217
+
218
+ if (!this.accessTokenExpired) {
219
+ this.dispatchEvent('loggedIn', [{ claims: this.idTokenClaims! }]);
220
+ }
221
+ }
222
+
223
+ override async refresh(): Promise<void> {
224
+ const response = await this.httpClient.request(new URL('/api/session/refresh', location.origin).toString(), { method: 'POST', credentials: 'include' });
120
225
 
121
- ## Event Subscription
226
+ if (!response.ok) {
227
+ this.session = null;
228
+ this.dispatchEvent('tokenRefreshFailed', [{}]);
229
+ return;
230
+ }
122
231
 
123
- The SDK provides an event subscription system that allows you to listen to various authentication lifecycle events.
232
+ this.session = Object.assign(new Session(), await response.json());
233
+ this.dispatchEvent('tokenRefreshed', [{ claims: this.idTokenClaims! }]);
234
+ }
124
235
 
125
- ### Usage
236
+ override async logout(): Promise<void> {
237
+ this.dispatchEvent('logoutInitiated', []);
238
+
239
+ await this.httpClient.request(new URL('/api/session/logout', location.origin).toString(), { method: 'POST', credentials: 'include' });
240
+
241
+ this.session = null;
242
+ }
243
+ }
244
+ ```
245
+
246
+ #### Creating a custom flow handler
247
+
248
+ Extend `NativeFlowHandler` and override `startSession` and `finalizeSession` to communicate with your backend:
249
+
250
+ ```ts
251
+ import type { LoginFlowState } from '@strivacity/sdk-core';
252
+ import { NativeFlowHandler } from '@strivacity/sdk-core/handlers/NativeFlowHandler';
253
+ import { CustomNativeFlow } from './CustomNativeFlow';
254
+
255
+ export class CustomNativeFlowHandler extends NativeFlowHandler {
256
+ declare sdk: CustomNativeFlow;
257
+
258
+ override async startSession(sessionId?: string | null): Promise<LoginFlowState | void> {
259
+ if (sessionId) {
260
+ this.sessionId = sessionId;
261
+ return this.submitForm();
262
+ }
263
+
264
+ const response = await this.sdk.httpClient.request(new URL('/api/session/start', location.origin).toString(), {
265
+ method: 'POST',
266
+ credentials: 'include',
267
+ headers: { 'Content-Type': 'application/json' },
268
+ body: JSON.stringify(this.params),
269
+ });
270
+
271
+ const data = await response.json();
272
+ this.sessionId = data.session_id;
273
+
274
+ return this.submitForm();
275
+ }
276
+
277
+ override async finalizeSession(finalizeUrl: string): Promise<void> {
278
+ const finalizeResponse = await this.sdk.httpClient.request(finalizeUrl, {
279
+ method: 'GET',
280
+ headers: { Authorization: `Bearer ${this.sessionId}` },
281
+ credentials: 'include',
282
+ });
283
+
284
+ const redirectUri = new URL(await finalizeResponse.text());
285
+
286
+ await this.sdk.httpClient.request(new URL('/api/session/finalize', location.origin).toString(), {
287
+ method: 'POST',
288
+ headers: {
289
+ 'Content-Type': 'application/json',
290
+ Authorization: `Bearer ${this.sessionId}`,
291
+ },
292
+ body: JSON.stringify(Object.fromEntries(redirectUri.searchParams)),
293
+ credentials: 'include',
294
+ });
295
+
296
+ await this.sdk.fetchSessionData();
297
+ }
298
+ }
299
+ ```
300
+
301
+ ### Event subscription
302
+
303
+ The SDK provides an event system for listening to authentication lifecycle events:
126
304
 
127
305
  ```js
128
- import { initFlow } from '@strivacity/sdk-core';
306
+ const { dispose } = sdk.subscribeToEvent('loggedIn', (eventData) => {
307
+ console.log('User logged in:', eventData);
308
+ });
309
+
310
+ // Later: unsubscribe
311
+ dispose();
312
+ ```
313
+
314
+ Available events:
315
+
316
+ - **`init`**: Fired when the SDK is initialized.
317
+ - **`loggedIn`**: Fired when a user successfully logs in.
318
+ - **`loginInitiated`**: Fired when a login flow is initiated.
319
+ - **`sessionLoaded`**: Fired when an existing session is loaded.
320
+ - **`accessTokenExpired`**: Fired when the access token expires.
321
+ - **`tokenRefreshed`**: Fired when access tokens are successfully refreshed.
322
+ - **`tokenRefreshFailed`**: Fired when token refresh fails.
323
+ - **`logoutInitiated`**: Fired when logout is initiated.
324
+ - **`tokenRevoked`**: Fired when tokens are successfully revoked.
325
+ - **`tokenRevokeFailed`**: Fired when token revocation fails.
326
+
327
+ ## Logging
328
+
329
+ The SDK supports optional logging to help you debug authentication flows and monitor SDK behavior. You can enable the built-in console logger or provide your own custom logger implementation.
330
+
331
+ ### Using the Default Logger
332
+
333
+ Enable the default console logger by adding the `logging` option when calling `initFlow`:
334
+
335
+ ```js
336
+ import { initFlow, DefaultLogging } from '@strivacity/sdk-core';
129
337
 
130
338
  const sdk = initFlow({
131
339
  mode: 'redirect',
@@ -133,48 +341,145 @@ const sdk = initFlow({
133
341
  scopes: ['openid', 'profile'],
134
342
  clientId: '<YOUR_CLIENT_ID>',
135
343
  redirectUri: '<YOUR_REDIRECT_URI>',
344
+ logging: DefaultLogging,
136
345
  });
346
+ ```
347
+
348
+ The default logger writes to the browser console and automatically prefixes messages with a correlation ID when available (via the `xEventId` property).
349
+
350
+ ### Creating a Custom Logger
351
+
352
+ Implement the `SDKLogging` interface and pass your class to the `logging` option:
353
+
354
+ ```typescript
355
+ import type { SDKLogging } from '@strivacity/sdk-core';
137
356
 
138
- // Subscribe to events
139
- function updateSession(eventData) {
140
- console.log('Event received:', eventData);
141
- // Handle the event as needed
357
+ export class MyLogger implements SDKLogging {
358
+ xEventId?: string;
359
+
360
+ debug(message: string): void {
361
+ console.debug(this.xEventId ? `[${this.xEventId}] ${message}` : message);
362
+ }
363
+
364
+ info(message: string): void {
365
+ console.info(this.xEventId ? `[${this.xEventId}] ${message}` : message);
366
+ }
367
+
368
+ warn(message: string): void {
369
+ console.warn(this.xEventId ? `[${this.xEventId}] ${message}` : message);
370
+ }
371
+
372
+ error(message: string, error: Error): void {
373
+ console.error(this.xEventId ? `[${this.xEventId}] ${message}` : message, error);
374
+ }
142
375
  }
376
+ ```
377
+
378
+ ```js
379
+ import { initFlow } from '@strivacity/sdk-core';
380
+ import { MyLogger } from './logging/MyLogger';
381
+
382
+ const sdk = initFlow({
383
+ // ...other options
384
+ logging: MyLogger,
385
+ });
386
+ ```
387
+
388
+ The `SDKLogging` interface requires `debug`, `info`, `warn`, and `error` methods. The optional `xEventId` property, when set by the SDK, provides a correlation ID to trace related log messages across the authentication flow.
389
+
390
+ ## API Documentation
391
+
392
+ ### `initFlow(options)`
143
393
 
144
- sdk.subscribeToEvent('init', updateSession);
145
- sdk.subscribeToEvent('loggedIn', updateSession);
146
- sdk.subscribeToEvent('sessionLoaded', updateSession);
147
- sdk.subscribeToEvent('tokenRefreshed', updateSession);
148
- sdk.subscribeToEvent('tokenRefreshFailed', updateSession);
149
- sdk.subscribeToEvent('logoutInitiated', updateSession);
150
- sdk.subscribeToEvent('tokenRevoked', updateSession);
151
- sdk.subscribeToEvent('tokenRevokeFailed', updateSession);
394
+ ```typescript
395
+ initFlow(options: SDKOptions): PopupFlow | RedirectFlow | NativeFlow | EmbeddedFlow
152
396
  ```
153
397
 
154
- ### Available Events
398
+ The `initFlow` function creates and returns a flow instance based on the `mode` specified in `options`.
399
+
400
+ **Parameters:**
401
+
402
+ | Name | Type | Required | Description |
403
+ | ------------------ | ------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------ |
404
+ | `issuer` | `string` | ✅ | The issuer URL of the OpenID Provider. |
405
+ | `clientId` | `string` | ✅ | The client identifier for the application. |
406
+ | `redirectUri` | `string` | ✅ | The URI to redirect to after authentication. |
407
+ | `mode` | `'redirect' \| 'popup' \| 'native' \| 'embedded' \| 'custom'` | ⬜ | The authentication flow mode. Defaults to `'redirect'`. |
408
+ | `scopes` | `string[]` | ⬜ | The scopes to request. Defaults to `['openid']`. |
409
+ | `responseType` | `'code' \| 'id_token'` | ⬜ | The response type. |
410
+ | `responseMode` | `'query' \| 'fragment'` | ⬜ | The response mode. |
411
+ | `storageTokenName` | `string` | ⬜ | Custom name for the session storage key. Defaults to `'sty.session'`. |
412
+ | `storage` | `SDKStorageType` | ⬜ | Custom storage implementation. Defaults to `LocalStorage`. |
413
+ | `httpClient` | `SDKHttpClientType` | ⬜ | Custom HTTP client implementation. |
414
+ | `logging` | `SDKLoggingType` | ⬜ | Logging implementation class. |
415
+ | `customFlow` | `FlowType` | ⬜ | Custom flow class. Required when `mode` is `'custom'`. Must extend `BaseFlow`. |
416
+
417
+ **Returns:** A flow instance (`PopupFlow`, `RedirectFlow`, `NativeFlow`, `EmbeddedFlow`, or your custom flow class) depending on the configured `mode`.
418
+
419
+ ---
420
+
421
+ ### Flow instance methods
422
+
423
+ All flow instances share the following methods:
155
424
 
156
- - **`init`**: Fired when the SDK is initialized
157
- - **`loggedIn`**: Fired when a user successfully logs in
158
- - **`sessionLoaded`**: Fired when an existing session is loaded
159
- - **`tokenRefreshed`**: Fired when access tokens are successfully refreshed
160
- - **`tokenRefreshFailed`**: Fired when token refresh fails
161
- - **`logoutInitiated`**: Fired when logout process is initiated
162
- - **`tokenRevoked`**: Fired when tokens are successfully revoked
163
- - **`tokenRevokeFailed`**: Fired when token revocation fails
425
+ - **`login(options?: LoginOptions): Promise<void | NativeFlowHandler>`**: Initiates login. In `native` mode returns a `NativeFlowHandler`.
426
+ - **`register(options?: RegisterOptions): Promise<void | NativeFlowHandler>`**: Initiates registration.
427
+ - **`entry(url?: string): Promise<Record<string, string>>`**: Processes an externally-initiated flow URL and returns parameters needed to resume the flow.
428
+ - **`handleCallback(url?: string): Promise<void>`**: Processes the authorization callback.
429
+ - **`refresh(): Promise<void>`**: Refreshes the session tokens.
430
+ - **`revoke(): Promise<void>`**: Revokes the current session tokens.
431
+ - **`logout(options?: LogoutOptions): Promise<void>`**: Logs the user out.
432
+ - **`subscribeToEvent(eventType: string, callback: Function): { dispose(): void }`**: Subscribes to an authentication lifecycle event. Returns an object with a `dispose()` method to unsubscribe.
164
433
 
165
- ### API Documentation
434
+ **Session state getters:**
166
435
 
167
- #### `subscribeToEvent(eventType: string, callback: (eventData: any) => void): void`
436
+ - **`isAuthenticated: Promise<boolean>`**: Resolves to `true` when a valid session exists.
437
+ - **`isAuthenticatedSync: boolean`**: Synchronous check for an active session.
438
+ - **`idTokenClaims: IdTokenClaims | null`**: Claims from the ID token.
439
+ - **`accessToken: string | null`**: The current access token.
440
+ - **`refreshToken: string | null`**: The current refresh token.
441
+ - **`accessTokenExpired: boolean`**: `true` when the access token has expired.
442
+ - **`accessTokenExpirationDate: number | null`**: Expiration timestamp (Unix seconds) of the access token.
168
443
 
169
- Subscribe to SDK events to handle authentication state changes.
444
+ ---
445
+
446
+ ### `NativeFlowHandler`
447
+
448
+ Returned by `NativeFlow.login()` and `NativeFlow.register()` to drive the step-by-step native authentication UI.
449
+
450
+ - **`startSession(sessionId?: string | null): Promise<LoginFlowState | void>`**: Starts a new authentication session or resumes an existing one when `sessionId` is provided.
451
+ - **`submitForm(formId?: string, body?: Record<string, unknown>): Promise<LoginFlowState>`**: Submits a form step in the authentication flow.
452
+ - **`finalizeSession(finalizeUrl: string): Promise<void>`**: Finalizes the session using the URL returned in `LoginFlowState.finalizeUrl`.
453
+
454
+ ---
455
+
456
+ ### `subscribeToEvent(eventType, callback)`
457
+
458
+ Subscribe to SDK lifecycle events.
170
459
 
171
460
  **Parameters:**
172
461
 
173
- - `eventType` (string): The type of event to listen for
174
- - `callback` (function): The function to call when the event is fired
462
+ | Name | Type | Required | Description |
463
+ | ----------- | -------------------------- | -------- | ---------------------------------------- |
464
+ | `eventType` | `string` | ✅ | The event type to listen for. |
465
+ | `callback` | `(eventData: any) => void` | ✅ | The handler called when the event fires. |
466
+
467
+ **Returns:** `{ dispose(): void }` — call `dispose()` to unsubscribe.
468
+
469
+ ## Vulnerability Reporting
470
+
471
+ The [Guidelines for responsible disclosure](https://www.strivacity.com/report-a-security-issue) details the procedure for disclosing security issues. Please do not report security vulnerabilities on the public issue tracker.
472
+
473
+ ## License
474
+
475
+ @strivacity/sdk-core is available under the MIT License. See the [LICENSE](https://github.com/Strivacity/sdk-js/blob/main/LICENSE) file for more info.
476
+
477
+ ## Contributing
478
+
479
+ Please see our [contributing guide](https://github.com/Strivacity/sdk-js/blob/main/CONTRIBUTING.md).
175
480
 
176
481
  ## Migrating to v3.0
177
482
 
178
483
  ### Entry API Major Changes
179
484
 
180
- Strivacity SDK's `entry()` API now returns a structured object instead of a plain string. To see examples of these changes, check the apps folder in this repository.
485
+ Strivacity SDK's `entry()` API now returns a structured object instead of a plain string. Check the example above in the usage section for more details.
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("../utils/handlers.cjs"),h=require("../utils/EmbeddedFlowHandler.cjs"),g=require("./BaseFlow.cjs");require("../utils/errors.cjs");require("../utils/State.cjs");require("../utils/crypto.cjs");require("../utils/base64Url.cjs");require("../utils/date.cjs");require("../utils/jwt.cjs");require("../utils/Metadata.cjs");require("../utils/Session.cjs");class u extends g.BaseFlow{constructor(r,e,s,i){r.urlHandler||(r.urlHandler=c.redirectUrlHandler),r.callbackHandler||(r.callbackHandler=c.redirectCallbackHandler),super(r,e,s,i),globalThis.sty||(globalThis.sty={}),globalThis.sty.oidcService=this}login(r={}){return this.dispatchEvent("loginInitiated",[]),new h.EmbeddedFlowHandler(this,r)}register(r={}){return r.prompt="create",this.login(r)}async entry(r){r||(r=globalThis.window?.location.href);const e=new URL(r);e.searchParams.append("sdk","web-embedded"),e.searchParams.append("client_id",this.options.clientId),e.searchParams.append("redirect_uri",this.options.redirectUri);const s=await this.httpClient.request(`${this.options.issuer}/provider/flow/entry?${e.searchParams.toString()}`);if(!s.ok){if(s.status===400){const o=await s.json();let n="Entry request failed with status 400";typeof o=="object"&&(o.error?n=`${o.error}: ${o.error_description}`:o.errorKey&&(n=o.errorKey));const d=new Error(n);throw this.logging?.error("Entry request error",d),d}const t=new Error(`Entry request failed with status ${s.status}`);throw this.logging?.error("Entry request error",t),t}let i;try{i=new URL(await s.text())}catch{i=new URL(s.url)}const a=i.searchParams.get("short_app_id"),l=i.searchParams.get("session_id");if(!a){const t=new Error('"short_app_id" is missing from the response');throw this.logging?.error("Entry response error",t),t}if(!l){const t=new Error('"session_id" is missing from the response');throw this.logging?.error("Entry response error",t),t}return{session_id:l,short_app_id:a}}async handleCallback(r){if(typeof this.options.callbackHandler!="function"){const e=new Error("Missing option: callbackHandler");throw this.logging?.error("Required option missing",e),e}r||(r=globalThis.window?.location.href),await this.tokenExchange(await this.options.callbackHandler(r,this.options.responseMode||"fragment"))}}exports.EmbeddedFlow=u;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("../utils/handlers.cjs"),g=require("../handlers/EmbeddedFlowHandler.cjs"),u=require("./BaseFlow.cjs");require("../utils/errors.cjs");require("../handlers/BaseFlowHandler.cjs");require("../utils/State.cjs");require("../utils/crypto.cjs");require("../utils/base64Url.cjs");require("../utils/date.cjs");require("../utils/jwt.cjs");require("../utils/Metadata.cjs");require("../utils/Session.cjs");class p extends u.BaseFlow{constructor(r,e,s,i){r.urlHandler||(r.urlHandler=c.redirectUrlHandler),r.callbackHandler||(r.callbackHandler=c.redirectCallbackHandler),super(r,e,s,i),globalThis.sty||(globalThis.sty={}),globalThis.sty.oidcService=this}login(r={}){return this.dispatchEvent("loginInitiated",[]),new g.EmbeddedFlowHandler(this,r)}register(r={}){return r.prompt="create",this.login(r)}async entry(r){r||(r=globalThis.window?.location.href);const e=new URL(r);e.searchParams.append("sdk","web-embedded"),e.searchParams.append("client_id",this.options.clientId),e.searchParams.append("redirect_uri",this.options.redirectUri);const s=await this.httpClient.request(`${this.options.issuer}/provider/flow/entry?${e.searchParams.toString()}`,{headers:{"Accept-Language":"*"}});if(!s.ok){if(s.status===400){const o=await s.json();let n="Entry request failed with status 400";typeof o=="object"&&(o.error?n=`${o.error}: ${o.error_description}`:o.errorKey&&(n=o.errorKey));const d=new Error(n);throw this.logging?.error("Entry request error",d),d}const t=new Error(`Entry request failed with status ${s.status}`);throw this.logging?.error("Entry request error",t),t}let i;try{i=new URL(await s.text())}catch{i=new URL(s.url)}const a=i.searchParams.get("short_app_id"),l=i.searchParams.get("session_id"),h=i.searchParams.get("language")||navigator.language;if(!a){const t=new Error('"short_app_id" is missing from the response');throw this.logging?.error("Entry response error",t),t}if(!l){const t=new Error('"session_id" is missing from the response');throw this.logging?.error("Entry response error",t),t}return{session_id:l,short_app_id:a,language:h}}async handleCallback(r){if(typeof this.options.callbackHandler!="function"){const e=new Error("Missing option: callbackHandler");throw this.logging?.error("Required option missing",e),e}r||(r=globalThis.window?.location.href),await this.tokenExchange(await this.options.callbackHandler(r,this.options.responseMode||"fragment"))}}exports.EmbeddedFlow=p;
2
2
  //# sourceMappingURL=EmbeddedFlow.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddedFlow.cjs","sources":["../../src/flows/EmbeddedFlow.ts"],"sourcesContent":["import type { SDKOptions, SDKStorage, SDKHttpClient, SDKLogging, ExtraRequestArgs } from '../types';\nimport { redirectUrlHandler, redirectCallbackHandler } from '../utils/handlers';\nimport { EmbeddedFlowHandler } from '../utils/EmbeddedFlowHandler';\nimport { BaseFlow } from './BaseFlow';\n\nexport class EmbeddedFlow extends BaseFlow<SDKOptions, ExtraRequestArgs> {\n\tconstructor(options: SDKOptions, storage: SDKStorage, httpClient: SDKHttpClient, logging?: SDKLogging) {\n\t\tif (!options.urlHandler) {\n\t\t\toptions.urlHandler = redirectUrlHandler;\n\t\t}\n\t\tif (!options.callbackHandler) {\n\t\t\toptions.callbackHandler = redirectCallbackHandler;\n\t\t}\n\n\t\tsuper(options, storage, httpClient, logging);\n\n\t\tif (!globalThis.sty) {\n\t\t\tglobalThis.sty = {};\n\t\t}\n\n\t\t// NOTE: Register the OIDC service instance globally for use in the login component\n\t\tglobalThis.sty.oidcService = this;\n\t}\n\n\t/**\n\t * Initiates the login process via embedded UI.\n\t * @param {ExtraRequestArgs} [params={}] Optional parameters for the login request.\n\t * @returns {EmbeddedFlowHandler} Returns with an embedded login handler.\n\t */\n\toverride login(params: ExtraRequestArgs = {}): EmbeddedFlowHandler {\n\t\tthis.dispatchEvent('loginInitiated', []);\n\n\t\treturn new EmbeddedFlowHandler(this, params);\n\t}\n\n\toverride register(params: ExtraRequestArgs = {}) {\n\t\tparams.prompt = 'create';\n\n\t\treturn this.login(params);\n\t}\n\n\toverride async entry(url?: string) {\n\t\tif (!url) {\n\t\t\turl = globalThis.window?.location.href;\n\t\t}\n\n\t\tconst entryUrl = new URL(url);\n\t\tentryUrl.searchParams.append('sdk', 'web-embedded');\n\t\tentryUrl.searchParams.append('client_id', this.options.clientId);\n\t\tentryUrl.searchParams.append('redirect_uri', this.options.redirectUri);\n\n\t\tconst response = await this.httpClient.request<string | Record<string, string>>(\n\t\t\t`${this.options.issuer}/provider/flow/entry?${entryUrl.searchParams.toString()}`,\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 400) {\n\t\t\t\tconst data = await response.json();\n\t\t\t\tlet message = 'Entry request failed with status 400';\n\n\t\t\t\tif (typeof data === 'object') {\n\t\t\t\t\tif (data.error) {\n\t\t\t\t\t\tmessage = `${data.error}: ${data.error_description}`;\n\t\t\t\t\t} else if (data.errorKey) {\n\t\t\t\t\t\tmessage = data.errorKey;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst error = new Error(message);\n\t\t\t\tthis.logging?.error('Entry request error', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tconst error = new Error(`Entry request failed with status ${response.status}`);\n\t\t\tthis.logging?.error('Entry request error', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\tlet uri: URL;\n\n\t\ttry {\n\t\t\turi = new URL(await response.text());\n\t\t} catch {\n\t\t\turi = new URL(response.url);\n\t\t}\n\n\t\tconst shortAppId = uri.searchParams.get('short_app_id');\n\t\tconst sessionId = uri.searchParams.get('session_id');\n\n\t\tif (!shortAppId) {\n\t\t\tconst error = new Error('\"short_app_id\" is missing from the response');\n\t\t\tthis.logging?.error('Entry response error', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!sessionId) {\n\t\t\tconst error = new Error('\"session_id\" is missing from the response');\n\t\t\tthis.logging?.error('Entry response error', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn { session_id: sessionId, short_app_id: shortAppId };\n\t}\n\n\t/**\n\t * Handles the callback after login or registration via a redirect.\n\t * @param {string} [url] The URL to handle the callback from. Defaults to the current window location.\n\t * @returns {Promise<void>} A promise that resolves when the callback is handled.\n\t *\n\t * @throws {Error} Throws an error if callback handler is not defined.\n\t */\n\tasync handleCallback(url?: string): Promise<void> {\n\t\tif (typeof this.options.callbackHandler !== 'function') {\n\t\t\tconst error = new Error('Missing option: callbackHandler');\n\t\t\tthis.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (!url) {\n\t\t\turl = globalThis.window?.location.href;\n\t\t}\n\n\t\tawait this.tokenExchange((await this.options.callbackHandler(url, this.options.responseMode || 'fragment')) as Record<string, string>);\n\t}\n}\n"],"names":["EmbeddedFlow","BaseFlow","options","storage","httpClient","logging","redirectUrlHandler","redirectCallbackHandler","params","EmbeddedFlowHandler","url","entryUrl","response","data","message","error","uri","shortAppId","sessionId"],"mappings":"2bAKO,MAAMA,UAAqBC,EAAAA,QAAuC,CACxE,YAAYC,EAAqBC,EAAqBC,EAA2BC,EAAsB,CACjGH,EAAQ,aACZA,EAAQ,WAAaI,EAAAA,oBAEjBJ,EAAQ,kBACZA,EAAQ,gBAAkBK,EAAAA,yBAG3B,MAAML,EAASC,EAASC,EAAYC,CAAO,EAEtC,WAAW,MACf,WAAW,IAAM,CAAA,GAIlB,WAAW,IAAI,YAAc,IAC9B,CAOS,MAAMG,EAA2B,GAAyB,CAClE,YAAK,cAAc,iBAAkB,EAAE,EAEhC,IAAIC,EAAAA,oBAAoB,KAAMD,CAAM,CAC5C,CAES,SAASA,EAA2B,GAAI,CAChD,OAAAA,EAAO,OAAS,SAET,KAAK,MAAMA,CAAM,CACzB,CAEA,MAAe,MAAME,EAAc,CAC7BA,IACJA,EAAM,WAAW,QAAQ,SAAS,MAGnC,MAAMC,EAAW,IAAI,IAAID,CAAG,EAC5BC,EAAS,aAAa,OAAO,MAAO,cAAc,EAClDA,EAAS,aAAa,OAAO,YAAa,KAAK,QAAQ,QAAQ,EAC/DA,EAAS,aAAa,OAAO,eAAgB,KAAK,QAAQ,WAAW,EAErE,MAAMC,EAAW,MAAM,KAAK,WAAW,QACtC,GAAG,KAAK,QAAQ,MAAM,wBAAwBD,EAAS,aAAa,UAAU,EAAA,EAG/E,GAAI,CAACC,EAAS,GAAI,CACjB,GAAIA,EAAS,SAAW,IAAK,CAC5B,MAAMC,EAAO,MAAMD,EAAS,KAAA,EAC5B,IAAIE,EAAU,uCAEV,OAAOD,GAAS,WACfA,EAAK,MACRC,EAAU,GAAGD,EAAK,KAAK,KAAKA,EAAK,iBAAiB,GACxCA,EAAK,WACfC,EAAUD,EAAK,WAIjB,MAAME,EAAQ,IAAI,MAAMD,CAAO,EAC/B,WAAK,SAAS,MAAM,sBAAuBC,CAAK,EAC1CA,CACP,CAEA,MAAMA,EAAQ,IAAI,MAAM,oCAAoCH,EAAS,MAAM,EAAE,EAC7E,WAAK,SAAS,MAAM,sBAAuBG,CAAK,EAC1CA,CACP,CAEA,IAAIC,EAEJ,GAAI,CACHA,EAAM,IAAI,IAAI,MAAMJ,EAAS,MAAM,CACpC,MAAQ,CACPI,EAAM,IAAI,IAAIJ,EAAS,GAAG,CAC3B,CAEA,MAAMK,EAAaD,EAAI,aAAa,IAAI,cAAc,EAChDE,EAAYF,EAAI,aAAa,IAAI,YAAY,EAEnD,GAAI,CAACC,EAAY,CAChB,MAAMF,EAAQ,IAAI,MAAM,6CAA6C,EACrE,WAAK,SAAS,MAAM,uBAAwBA,CAAK,EAC3CA,CACP,CACA,GAAI,CAACG,EAAW,CACf,MAAMH,EAAQ,IAAI,MAAM,2CAA2C,EACnE,WAAK,SAAS,MAAM,uBAAwBA,CAAK,EAC3CA,CACP,CAEA,MAAO,CAAE,WAAYG,EAAW,aAAcD,CAAA,CAC/C,CASA,MAAM,eAAeP,EAA6B,CACjD,GAAI,OAAO,KAAK,QAAQ,iBAAoB,WAAY,CACvD,MAAMK,EAAQ,IAAI,MAAM,iCAAiC,EACzD,WAAK,SAAS,MAAM,0BAA2BA,CAAK,EAC9CA,CACP,CAEKL,IACJA,EAAM,WAAW,QAAQ,SAAS,MAGnC,MAAM,KAAK,cAAe,MAAM,KAAK,QAAQ,gBAAgBA,EAAK,KAAK,QAAQ,cAAgB,UAAU,CAA4B,CACtI,CACD"}
1
+ {"version":3,"file":"EmbeddedFlow.cjs","sources":["../../src/flows/EmbeddedFlow.ts"],"sourcesContent":["import type { SDKOptions, SDKStorage, SDKHttpClient, SDKLogging, ExtraRequestArgs } from '../types';\nimport { redirectUrlHandler, redirectCallbackHandler } from '../utils/handlers';\nimport { EmbeddedFlowHandler } from '../handlers/EmbeddedFlowHandler';\nimport { BaseFlow } from './BaseFlow';\n\nexport class EmbeddedFlow extends BaseFlow<SDKOptions, ExtraRequestArgs> {\n\tconstructor(options: SDKOptions, storage: SDKStorage, httpClient: SDKHttpClient, logging?: SDKLogging) {\n\t\tif (!options.urlHandler) {\n\t\t\toptions.urlHandler = redirectUrlHandler;\n\t\t}\n\t\tif (!options.callbackHandler) {\n\t\t\toptions.callbackHandler = redirectCallbackHandler;\n\t\t}\n\n\t\tsuper(options, storage, httpClient, logging);\n\n\t\tif (!globalThis.sty) {\n\t\t\tglobalThis.sty = {};\n\t\t}\n\n\t\t// NOTE: Register the OIDC service instance globally for use in the login component\n\t\tglobalThis.sty.oidcService = this;\n\t}\n\n\t/**\n\t * Initiates the login process via embedded UI.\n\t * @param {ExtraRequestArgs} [params={}] Optional parameters for the login request.\n\t * @returns {EmbeddedFlowHandler} Returns with an embedded login handler.\n\t */\n\toverride login(params: ExtraRequestArgs = {}): EmbeddedFlowHandler {\n\t\tthis.dispatchEvent('loginInitiated', []);\n\n\t\treturn new EmbeddedFlowHandler(this, params);\n\t}\n\n\toverride register(params: ExtraRequestArgs = {}) {\n\t\tparams.prompt = 'create';\n\n\t\treturn this.login(params);\n\t}\n\n\toverride async entry(url?: string) {\n\t\tif (!url) {\n\t\t\turl = globalThis.window?.location.href;\n\t\t}\n\n\t\tconst entryUrl = new URL(url);\n\t\tentryUrl.searchParams.append('sdk', 'web-embedded');\n\t\tentryUrl.searchParams.append('client_id', this.options.clientId);\n\t\tentryUrl.searchParams.append('redirect_uri', this.options.redirectUri);\n\n\t\tconst response = await this.httpClient.request<string | Record<string, string>>(\n\t\t\t`${this.options.issuer}/provider/flow/entry?${entryUrl.searchParams.toString()}`,\n\t\t\t{\n\t\t\t\theaders: {\n\t\t\t\t\t'Accept-Language': '*',\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (!response.ok) {\n\t\t\tif (response.status === 400) {\n\t\t\t\tconst data = await response.json();\n\t\t\t\tlet message = 'Entry request failed with status 400';\n\n\t\t\t\tif (typeof data === 'object') {\n\t\t\t\t\tif (data.error) {\n\t\t\t\t\t\tmessage = `${data.error}: ${data.error_description}`;\n\t\t\t\t\t} else if (data.errorKey) {\n\t\t\t\t\t\tmessage = data.errorKey;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst error = new Error(message);\n\t\t\t\tthis.logging?.error('Entry request error', error);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tconst error = new Error(`Entry request failed with status ${response.status}`);\n\t\t\tthis.logging?.error('Entry request error', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\tlet uri: URL;\n\n\t\ttry {\n\t\t\turi = new URL(await response.text());\n\t\t} catch {\n\t\t\turi = new URL(response.url);\n\t\t}\n\n\t\tconst shortAppId = uri.searchParams.get('short_app_id');\n\t\tconst sessionId = uri.searchParams.get('session_id');\n\t\tconst language = uri.searchParams.get('language') || navigator.language;\n\n\t\tif (!shortAppId) {\n\t\t\tconst error = new Error('\"short_app_id\" is missing from the response');\n\t\t\tthis.logging?.error('Entry response error', error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (!sessionId) {\n\t\t\tconst error = new Error('\"session_id\" is missing from the response');\n\t\t\tthis.logging?.error('Entry response error', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\treturn { session_id: sessionId, short_app_id: shortAppId, language: language };\n\t}\n\n\t/**\n\t * Handles the callback after login or registration via a redirect.\n\t * @param {string} [url] The URL to handle the callback from. Defaults to the current window location.\n\t * @returns {Promise<void>} A promise that resolves when the callback is handled.\n\t *\n\t * @throws {Error} Throws an error if callback handler is not defined.\n\t */\n\tasync handleCallback(url?: string): Promise<void> {\n\t\tif (typeof this.options.callbackHandler !== 'function') {\n\t\t\tconst error = new Error('Missing option: callbackHandler');\n\t\t\tthis.logging?.error('Required option missing', error);\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (!url) {\n\t\t\turl = globalThis.window?.location.href;\n\t\t}\n\n\t\tawait this.tokenExchange((await this.options.callbackHandler(url, this.options.responseMode || 'fragment')) as Record<string, string>);\n\t}\n}\n"],"names":["EmbeddedFlow","BaseFlow","options","storage","httpClient","logging","redirectUrlHandler","redirectCallbackHandler","params","EmbeddedFlowHandler","url","entryUrl","response","data","message","error","uri","shortAppId","sessionId","language"],"mappings":"yeAKO,MAAMA,UAAqBC,EAAAA,QAAuC,CACxE,YAAYC,EAAqBC,EAAqBC,EAA2BC,EAAsB,CACjGH,EAAQ,aACZA,EAAQ,WAAaI,EAAAA,oBAEjBJ,EAAQ,kBACZA,EAAQ,gBAAkBK,EAAAA,yBAG3B,MAAML,EAASC,EAASC,EAAYC,CAAO,EAEtC,WAAW,MACf,WAAW,IAAM,CAAA,GAIlB,WAAW,IAAI,YAAc,IAC9B,CAOS,MAAMG,EAA2B,GAAyB,CAClE,YAAK,cAAc,iBAAkB,EAAE,EAEhC,IAAIC,EAAAA,oBAAoB,KAAMD,CAAM,CAC5C,CAES,SAASA,EAA2B,GAAI,CAChD,OAAAA,EAAO,OAAS,SAET,KAAK,MAAMA,CAAM,CACzB,CAEA,MAAe,MAAME,EAAc,CAC7BA,IACJA,EAAM,WAAW,QAAQ,SAAS,MAGnC,MAAMC,EAAW,IAAI,IAAID,CAAG,EAC5BC,EAAS,aAAa,OAAO,MAAO,cAAc,EAClDA,EAAS,aAAa,OAAO,YAAa,KAAK,QAAQ,QAAQ,EAC/DA,EAAS,aAAa,OAAO,eAAgB,KAAK,QAAQ,WAAW,EAErE,MAAMC,EAAW,MAAM,KAAK,WAAW,QACtC,GAAG,KAAK,QAAQ,MAAM,wBAAwBD,EAAS,aAAa,UAAU,GAC9E,CACC,QAAS,CACR,kBAAmB,GAAA,CACpB,CACD,EAGD,GAAI,CAACC,EAAS,GAAI,CACjB,GAAIA,EAAS,SAAW,IAAK,CAC5B,MAAMC,EAAO,MAAMD,EAAS,KAAA,EAC5B,IAAIE,EAAU,uCAEV,OAAOD,GAAS,WACfA,EAAK,MACRC,EAAU,GAAGD,EAAK,KAAK,KAAKA,EAAK,iBAAiB,GACxCA,EAAK,WACfC,EAAUD,EAAK,WAIjB,MAAME,EAAQ,IAAI,MAAMD,CAAO,EAC/B,WAAK,SAAS,MAAM,sBAAuBC,CAAK,EAC1CA,CACP,CAEA,MAAMA,EAAQ,IAAI,MAAM,oCAAoCH,EAAS,MAAM,EAAE,EAC7E,WAAK,SAAS,MAAM,sBAAuBG,CAAK,EAC1CA,CACP,CAEA,IAAIC,EAEJ,GAAI,CACHA,EAAM,IAAI,IAAI,MAAMJ,EAAS,MAAM,CACpC,MAAQ,CACPI,EAAM,IAAI,IAAIJ,EAAS,GAAG,CAC3B,CAEA,MAAMK,EAAaD,EAAI,aAAa,IAAI,cAAc,EAChDE,EAAYF,EAAI,aAAa,IAAI,YAAY,EAC7CG,EAAWH,EAAI,aAAa,IAAI,UAAU,GAAK,UAAU,SAE/D,GAAI,CAACC,EAAY,CAChB,MAAMF,EAAQ,IAAI,MAAM,6CAA6C,EACrE,WAAK,SAAS,MAAM,uBAAwBA,CAAK,EAC3CA,CACP,CACA,GAAI,CAACG,EAAW,CACf,MAAMH,EAAQ,IAAI,MAAM,2CAA2C,EACnE,WAAK,SAAS,MAAM,uBAAwBA,CAAK,EAC3CA,CACP,CAEA,MAAO,CAAE,WAAYG,EAAW,aAAcD,EAAY,SAAAE,CAAA,CAC3D,CASA,MAAM,eAAeT,EAA6B,CACjD,GAAI,OAAO,KAAK,QAAQ,iBAAoB,WAAY,CACvD,MAAMK,EAAQ,IAAI,MAAM,iCAAiC,EACzD,WAAK,SAAS,MAAM,0BAA2BA,CAAK,EAC9CA,CACP,CAEKL,IACJA,EAAM,WAAW,QAAQ,SAAS,MAGnC,MAAM,KAAK,cAAe,MAAM,KAAK,QAAQ,gBAAgBA,EAAK,KAAK,QAAQ,cAAgB,UAAU,CAA4B,CACtI,CACD"}