@strivacity/sdk-core 2.3.0 → 3.0.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +387 -78
  3. package/dist/flows/BaseFlow.cjs.map +1 -1
  4. package/dist/flows/BaseFlow.d.ts +1 -1
  5. package/dist/flows/BaseFlow.mjs.map +1 -1
  6. package/dist/flows/EmbeddedFlow.cjs +2 -0
  7. package/dist/flows/EmbeddedFlow.cjs.map +1 -0
  8. package/dist/flows/EmbeddedFlow.d.ts +25 -0
  9. package/dist/flows/EmbeddedFlow.mjs +2 -0
  10. package/dist/flows/EmbeddedFlow.mjs.map +1 -0
  11. package/dist/flows/NativeFlow.cjs +1 -1
  12. package/dist/flows/NativeFlow.cjs.map +1 -1
  13. package/dist/flows/NativeFlow.d.ts +2 -2
  14. package/dist/flows/NativeFlow.mjs +1 -1
  15. package/dist/flows/NativeFlow.mjs.map +1 -1
  16. package/dist/flows/PopupFlow.cjs +1 -1
  17. package/dist/flows/PopupFlow.cjs.map +1 -1
  18. package/dist/flows/PopupFlow.mjs +1 -1
  19. package/dist/flows/PopupFlow.mjs.map +1 -1
  20. package/dist/flows/RedirectFlow.cjs +1 -1
  21. package/dist/flows/RedirectFlow.cjs.map +1 -1
  22. package/dist/flows/RedirectFlow.mjs +1 -1
  23. package/dist/flows/RedirectFlow.mjs.map +1 -1
  24. package/dist/handlers/BaseFlowHandler.cjs +2 -0
  25. package/dist/handlers/BaseFlowHandler.cjs.map +1 -0
  26. package/dist/{utils/NativeFlowHandler.d.ts → handlers/BaseFlowHandler.d.ts} +3 -12
  27. package/dist/handlers/BaseFlowHandler.mjs +2 -0
  28. package/dist/handlers/BaseFlowHandler.mjs.map +1 -0
  29. package/dist/handlers/EmbeddedFlowHandler.cjs +2 -0
  30. package/dist/handlers/EmbeddedFlowHandler.cjs.map +1 -0
  31. package/dist/handlers/EmbeddedFlowHandler.d.ts +29 -0
  32. package/dist/handlers/EmbeddedFlowHandler.mjs +2 -0
  33. package/dist/handlers/EmbeddedFlowHandler.mjs.map +1 -0
  34. package/dist/handlers/NativeFlowHandler.cjs +2 -0
  35. package/dist/handlers/NativeFlowHandler.cjs.map +1 -0
  36. package/dist/handlers/NativeFlowHandler.d.ts +30 -0
  37. package/dist/handlers/NativeFlowHandler.mjs +2 -0
  38. package/dist/handlers/NativeFlowHandler.mjs.map +1 -0
  39. package/dist/index.cjs +1 -1
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.ts +11 -4
  42. package/dist/index.mjs +1 -1
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/types.cjs.map +1 -1
  45. package/dist/types.d.ts +89 -56
  46. package/dist/types.mjs.map +1 -1
  47. package/dist/utils/errors.cjs +1 -1
  48. package/dist/utils/errors.cjs.map +1 -1
  49. package/dist/utils/errors.d.ts +12 -0
  50. package/dist/utils/errors.mjs +1 -1
  51. package/dist/utils/errors.mjs.map +1 -1
  52. package/dist/utils/handlers.cjs +1 -1
  53. package/dist/utils/handlers.cjs.map +1 -1
  54. package/dist/utils/handlers.d.ts +1 -3
  55. package/dist/utils/handlers.mjs +1 -1
  56. package/dist/utils/handlers.mjs.map +1 -1
  57. package/package.json +7 -1
  58. package/dist/utils/NativeFlowHandler.cjs +0 -2
  59. package/dist/utils/NativeFlowHandler.cjs.map +0 -1
  60. package/dist/utils/NativeFlowHandler.mjs +0 -2
  61. package/dist/utils/NativeFlowHandler.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,43 @@
1
+ # 3.0.0 (2026-04-09)
2
+
3
+ ### 🚀 Features
4
+
5
+ - custom sdk mode added ([17812c6](https://github.com/Strivacity/sdk-js/commit/17812c6))
6
+ - ⚠️ EmbeddedFlow implemented ([a0e3ad8](https://github.com/Strivacity/sdk-js/commit/a0e3ad8))
7
+ - ⚠️ NativeFlow entry function now returns an object instead of a string ([9a8942d](https://github.com/Strivacity/sdk-js/commit/9a8942d))
8
+ - popupUrlHandler refactored ([886f6ea](https://github.com/Strivacity/sdk-js/commit/886f6ea))
9
+
10
+ ### 🩹 Fixes
11
+
12
+ - select and multiselect default value handling fixed ([25ecacd](https://github.com/Strivacity/sdk-js/commit/25ecacd))
13
+ - widget type definitions fixed ([c2e9b12](https://github.com/Strivacity/sdk-js/commit/c2e9b12))
14
+
15
+ ### ⚠️ Breaking Changes
16
+
17
+ - EmbeddedFlow implemented ([a0e3ad8](https://github.com/Strivacity/sdk-js/commit/a0e3ad8))
18
+ - NativeFlow entry function now returns an object instead of a string ([9a8942d](https://github.com/Strivacity/sdk-js/commit/9a8942d))
19
+
20
+ ### 🧱 Updated Dependencies
21
+
22
+ - Updated testing to 3.0.0
23
+
24
+ ## 3.0.0-rc.0 (2026-02-18)
25
+
26
+ ### 🚀 Features
27
+
28
+ - ⚠️ EmbeddedFlow implemented ([a0e3ad8](https://github.com/Strivacity/sdk-js/commit/a0e3ad8))
29
+ - ⚠️ NativeFlow entry function now returns an object instead of a string ([9a8942d](https://github.com/Strivacity/sdk-js/commit/9a8942d))
30
+ - popupUrlHandler refactored ([886f6ea](https://github.com/Strivacity/sdk-js/commit/886f6ea))
31
+
32
+ ### ⚠️ Breaking Changes
33
+
34
+ - EmbeddedFlow implemented ([a0e3ad8](https://github.com/Strivacity/sdk-js/commit/a0e3ad8))
35
+ - NativeFlow entry function now returns an object instead of a string ([9a8942d](https://github.com/Strivacity/sdk-js/commit/9a8942d))
36
+
37
+ ### 🧱 Updated Dependencies
38
+
39
+ - Updated testing to 3.0.0-rc.0
40
+
1
41
  ## 2.3.0 (2026-02-10)
2
42
 
3
43
  ### 🚀 Features
package/README.md CHANGED
@@ -1,67 +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:**
65
+ #### Token refresh
42
66
 
43
- - `issuer` (string): The issuer URL of the OpenID Provider.
44
- - `clientId` (string): The client identifier for the application.
45
- - `redirectUri` (string): The URI to redirect to after authentication.
46
- - `scopes` (Array<string>): The scopes to request during authentication.
47
- - `responseType` (ResponseType): The response type requested from the OpenID Provider.
48
- - `responseMode` (ResponseMode): The response mode to use.
49
- - `storageTokenName` (string): The name of the token in storage.
50
- - `storage` (SDKStorageType): A custom storage implementation.
67
+ Refreshes the access token using the stored refresh token, keeping the session alive without requiring the user to log in again.
51
68
 
52
- **Mode:**
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.
53
76
 
54
- - `popup`: Uses a popup window for authentication. Returns an instance of `PopupFlow`.
55
- - `redirect`: Uses a full-page redirect for authentication. Returns an instance of `RedirectFlow`.
56
- - `native`: Uses a native flow for authentication. Returns an instance of `NativeFlow`.
77
+ ```js
78
+ await sdk.revoke();
79
+ ```
57
80
 
58
- ## Custom native flow
81
+ ### Native mode
59
82
 
60
- 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.
61
84
 
62
- 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
63
86
 
64
- ### Usage
87
+ The login page extracts `session_id` from the URL on load and passes it to `startSession()` to resume an existing flow or start a new one:
65
88
 
66
89
  ```js
67
90
  import { initFlow } from '@strivacity/sdk-core';
@@ -74,60 +97,243 @@ const sdk = initFlow({
74
97
  redirectUri: '<YOUR_REDIRECT_URI>',
75
98
  });
76
99
 
77
- // This will return with a `NativeFlowHandler` instance
100
+ // Returns a NativeFlowHandler instance
78
101
  const handler = await sdk.login();
79
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
+
80
107
  // Start a new session or resume an existing one
81
- const state = await handler.startSession();
108
+ const state = await handler.startSession(sessionId);
82
109
 
83
110
  if (state.finalizeUrl) {
84
- // If the response contains a finalize URL, you can finalize the session
111
+ // Finalize the session when the flow is complete
85
112
  await handler.finalizeSession(state.finalizeUrl);
86
113
  } else {
87
- // Handle the response as needed
88
- console.log('Form submitted successfully:', state);
114
+ // Render the form from state.widgets and handle user input
115
+ console.log('Current form state:', state);
89
116
  }
117
+ ```
90
118
 
91
- // Submit a form in the native flow
119
+ #### Submitting a form
120
+
121
+ ```js
92
122
  const formState = await handler.submitForm('formId', {
93
- // Your form data here
123
+ email: 'user@example.com',
124
+ password: 'secret',
94
125
  });
95
126
 
96
- if (state.finalizeUrl) {
97
- // If the response contains a finalize URL, you can finalize the session
98
- 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}`;
99
143
  } else {
100
- // Handle the response as needed
101
- 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
+ }
102
150
  }
103
151
  ```
104
152
 
105
- ---
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.):
177
+
178
+ ```ts
179
+ import { initFlow } from '@strivacity/sdk-core';
180
+ import { CustomNativeFlow } from './sdk/CustomNativeFlow';
106
181
 
107
- ### API Documentation
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
- #### `startSession(sessionId?: string | null): Promise<LoginFlowState | void>`
192
+ #### Creating a custom flow class
110
193
 
111
- Starts a new authentication session. If a `sessionId` is provided, resumes the session; otherwise, initiates a new one.
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
- #### `submitForm(formId?: string, body?: Record<string, unknown>): Promise<LoginFlowState>`
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
- Submits a form in the native flow. Optionally specify a form ID and request body.
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
- #### `finalizeSession(finalizeUrl: string): Promise<void>`
208
+ override register(params: NativeParams = {}): CustomNativeFlowHandler {
209
+ params.prompt = 'create';
210
+ return this.login(params);
211
+ }
118
212
 
119
- Finalizes the session using the provided URL. You can gather the finalize URL from the `LoginFlowState` returned by `startSession` or `submitForm`.
213
+ async fetchSessionData(): Promise<void> {
214
+ const response = await this.httpClient.request(new URL('/api/session/info', location.origin).toString(), { method: 'GET', credentials: 'include' });
120
215
 
121
- ---
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' });
225
+
226
+ if (!response.ok) {
227
+ this.session = null;
228
+ this.dispatchEvent('tokenRefreshFailed', [{}]);
229
+ return;
230
+ }
231
+
232
+ this.session = Object.assign(new Session(), await response.json());
233
+ this.dispatchEvent('tokenRefreshed', [{ claims: this.idTokenClaims! }]);
234
+ }
235
+
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
+ ```
122
245
 
123
- ## Event Subscription
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
+ ```
124
300
 
125
- The SDK provides an event subscription system that allows you to listen to various authentication lifecycle events.
301
+ ### Event subscription
126
302
 
127
- ### Usage
303
+ The SDK provides an event system for listening to authentication lifecycle events:
128
304
 
129
305
  ```js
130
- 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';
131
337
 
132
338
  const sdk = initFlow({
133
339
  mode: 'redirect',
@@ -135,42 +341,145 @@ const sdk = initFlow({
135
341
  scopes: ['openid', 'profile'],
136
342
  clientId: '<YOUR_CLIENT_ID>',
137
343
  redirectUri: '<YOUR_REDIRECT_URI>',
344
+ logging: DefaultLogging,
138
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';
356
+
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
+ }
139
367
 
140
- // Subscribe to events
141
- function updateSession(eventData) {
142
- console.log('Event received:', eventData);
143
- // Handle the event as needed
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
+ }
144
375
  }
376
+ ```
145
377
 
146
- sdk.subscribeToEvent('init', updateSession);
147
- sdk.subscribeToEvent('loggedIn', updateSession);
148
- sdk.subscribeToEvent('sessionLoaded', updateSession);
149
- sdk.subscribeToEvent('tokenRefreshed', updateSession);
150
- sdk.subscribeToEvent('tokenRefreshFailed', updateSession);
151
- sdk.subscribeToEvent('logoutInitiated', updateSession);
152
- sdk.subscribeToEvent('tokenRevoked', updateSession);
153
- sdk.subscribeToEvent('tokenRevokeFailed', updateSession);
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
+ });
154
386
  ```
155
387
 
156
- ### Available Events
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.
157
389
 
158
- - **`init`**: Fired when the SDK is initialized
159
- - **`loggedIn`**: Fired when a user successfully logs in
160
- - **`sessionLoaded`**: Fired when an existing session is loaded
161
- - **`tokenRefreshed`**: Fired when access tokens are successfully refreshed
162
- - **`tokenRefreshFailed`**: Fired when token refresh fails
163
- - **`logoutInitiated`**: Fired when logout process is initiated
164
- - **`tokenRevoked`**: Fired when tokens are successfully revoked
165
- - **`tokenRevokeFailed`**: Fired when token revocation fails
390
+ ## API Documentation
166
391
 
167
- ### API Documentation
392
+ ### `initFlow(options)`
168
393
 
169
- #### `subscribeToEvent(eventType: string, callback: (eventData: any) => void): void`
394
+ ```typescript
395
+ initFlow(options: SDKOptions): PopupFlow | RedirectFlow | NativeFlow | EmbeddedFlow
396
+ ```
397
+
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:
424
+
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.
433
+
434
+ **Session state getters:**
435
+
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.
443
+
444
+ ---
445
+
446
+ ### `NativeFlowHandler`
170
447
 
171
- Subscribe to SDK events to handle authentication state changes.
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.
172
459
 
173
460
  **Parameters:**
174
461
 
175
- - `eventType` (string): The type of event to listen for
176
- - `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).
480
+
481
+ ## Migrating to v3.0
482
+
483
+ ### Entry API Major Changes
484
+
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.