@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.
- package/CHANGELOG.md +40 -0
- package/README.md +387 -78
- package/dist/flows/BaseFlow.cjs.map +1 -1
- package/dist/flows/BaseFlow.d.ts +1 -1
- package/dist/flows/BaseFlow.mjs.map +1 -1
- package/dist/flows/EmbeddedFlow.cjs +2 -0
- package/dist/flows/EmbeddedFlow.cjs.map +1 -0
- package/dist/flows/EmbeddedFlow.d.ts +25 -0
- package/dist/flows/EmbeddedFlow.mjs +2 -0
- package/dist/flows/EmbeddedFlow.mjs.map +1 -0
- package/dist/flows/NativeFlow.cjs +1 -1
- package/dist/flows/NativeFlow.cjs.map +1 -1
- package/dist/flows/NativeFlow.d.ts +2 -2
- package/dist/flows/NativeFlow.mjs +1 -1
- package/dist/flows/NativeFlow.mjs.map +1 -1
- package/dist/flows/PopupFlow.cjs +1 -1
- package/dist/flows/PopupFlow.cjs.map +1 -1
- package/dist/flows/PopupFlow.mjs +1 -1
- package/dist/flows/PopupFlow.mjs.map +1 -1
- package/dist/flows/RedirectFlow.cjs +1 -1
- package/dist/flows/RedirectFlow.cjs.map +1 -1
- package/dist/flows/RedirectFlow.mjs +1 -1
- package/dist/flows/RedirectFlow.mjs.map +1 -1
- package/dist/handlers/BaseFlowHandler.cjs +2 -0
- package/dist/handlers/BaseFlowHandler.cjs.map +1 -0
- package/dist/{utils/NativeFlowHandler.d.ts → handlers/BaseFlowHandler.d.ts} +3 -12
- package/dist/handlers/BaseFlowHandler.mjs +2 -0
- package/dist/handlers/BaseFlowHandler.mjs.map +1 -0
- package/dist/handlers/EmbeddedFlowHandler.cjs +2 -0
- package/dist/handlers/EmbeddedFlowHandler.cjs.map +1 -0
- package/dist/handlers/EmbeddedFlowHandler.d.ts +29 -0
- package/dist/handlers/EmbeddedFlowHandler.mjs +2 -0
- package/dist/handlers/EmbeddedFlowHandler.mjs.map +1 -0
- package/dist/handlers/NativeFlowHandler.cjs +2 -0
- package/dist/handlers/NativeFlowHandler.cjs.map +1 -0
- package/dist/handlers/NativeFlowHandler.d.ts +30 -0
- package/dist/handlers/NativeFlowHandler.mjs +2 -0
- package/dist/handlers/NativeFlowHandler.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -4
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +89 -56
- package/dist/types.mjs.map +1 -1
- package/dist/utils/errors.cjs +1 -1
- package/dist/utils/errors.cjs.map +1 -1
- package/dist/utils/errors.d.ts +12 -0
- package/dist/utils/errors.mjs +1 -1
- package/dist/utils/errors.mjs.map +1 -1
- package/dist/utils/handlers.cjs +1 -1
- package/dist/utils/handlers.cjs.map +1 -1
- package/dist/utils/handlers.d.ts +1 -3
- package/dist/utils/handlers.mjs +1 -1
- package/dist/utils/handlers.mjs.map +1 -1
- package/package.json +7 -1
- package/dist/utils/NativeFlowHandler.cjs +0 -2
- package/dist/utils/NativeFlowHandler.cjs.map +0 -1
- package/dist/utils/NativeFlowHandler.mjs +0 -2
- 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
|
-
|
|
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
|
-
|
|
15
|
+
## Install
|
|
8
16
|
|
|
9
17
|
```bash
|
|
10
18
|
npm install @strivacity/sdk-core
|
|
11
19
|
```
|
|
12
20
|
|
|
13
|
-
|
|
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'
|
|
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
|
-
|
|
49
|
+
#### Callback handling
|
|
30
50
|
|
|
31
|
-
|
|
51
|
+
Process the authorization callback after the identity provider redirects back to your application:
|
|
32
52
|
|
|
33
|
-
|
|
53
|
+
```js
|
|
54
|
+
await sdk.handleCallback();
|
|
55
|
+
```
|
|
34
56
|
|
|
35
|
-
|
|
57
|
+
#### Logout
|
|
36
58
|
|
|
37
|
-
|
|
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
|
-
|
|
61
|
+
```js
|
|
62
|
+
await sdk.logout({ postLogoutRedirectUri: location.origin });
|
|
63
|
+
```
|
|
40
64
|
|
|
41
|
-
|
|
65
|
+
#### Token refresh
|
|
42
66
|
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
77
|
+
```js
|
|
78
|
+
await sdk.revoke();
|
|
79
|
+
```
|
|
57
80
|
|
|
58
|
-
|
|
81
|
+
### Native mode
|
|
59
82
|
|
|
60
|
-
|
|
83
|
+
In `native` mode, `login()` returns a `NativeFlowHandler` instance that drives the authentication UI step by step.
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
#### Login page example
|
|
63
86
|
|
|
64
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
111
|
+
// Finalize the session when the flow is complete
|
|
85
112
|
await handler.finalizeSession(state.finalizeUrl);
|
|
86
113
|
} else {
|
|
87
|
-
//
|
|
88
|
-
console.log('
|
|
114
|
+
// Render the form from state.widgets and handle user input
|
|
115
|
+
console.log('Current form state:', state);
|
|
89
116
|
}
|
|
117
|
+
```
|
|
90
118
|
|
|
91
|
-
|
|
119
|
+
#### Submitting a form
|
|
120
|
+
|
|
121
|
+
```js
|
|
92
122
|
const formState = await handler.submitForm('formId', {
|
|
93
|
-
|
|
123
|
+
email: 'user@example.com',
|
|
124
|
+
password: 'secret',
|
|
94
125
|
});
|
|
95
126
|
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
101
|
-
|
|
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
|
-
|
|
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
|
-
####
|
|
192
|
+
#### Creating a custom flow class
|
|
110
193
|
|
|
111
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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' });
|
|
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
|
-
|
|
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
|
-
|
|
301
|
+
### Event subscription
|
|
126
302
|
|
|
127
|
-
|
|
303
|
+
The SDK provides an event system for listening to authentication lifecycle events:
|
|
128
304
|
|
|
129
305
|
```js
|
|
130
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
147
|
-
sdk
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
sdk
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
392
|
+
### `initFlow(options)`
|
|
168
393
|
|
|
169
|
-
|
|
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
|
-
|
|
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
|
-
|
|
176
|
-
|
|
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.
|