@schibsted/account-sdk-browser 6.0.0-alpha.5 → 6.0.0-alpha.7
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/README.md +278 -224
- package/dist/account-sdk.d.ts +18 -0
- package/dist/account.d.ts +139 -3
- package/dist/identity.d.ts +38 -40
- package/dist/index.d.ts +1 -1
- package/dist/index.js +225 -242
- package/dist/index.js.map +1 -1
- package/dist/monetization.d.ts +4 -10
- package/dist/sdk-error.d.ts +2 -0
- package/dist/types/account.d.ts +30 -8
- package/dist/types/common.d.ts +7 -1
- package/dist/types/login.d.ts +16 -11
- package/dist/types/monetization.d.ts +6 -1
- package/dist/types/session.d.ts +28 -3
- package/dist/version.d.ts +1 -1
- package/package.json +1 -4
- package/src/account-sdk.ts +18 -0
- package/src/account.ts +155 -5
- package/src/identity.ts +125 -110
- package/src/index.ts +1 -1
- package/src/monetization.ts +12 -24
- package/src/sdk-error.ts +2 -0
- package/src/types/account.ts +35 -13
- package/src/types/common.ts +7 -1
- package/src/types/login.ts +16 -11
- package/src/types/monetization.ts +6 -1
- package/src/types/session.ts +28 -3
- package/src/version.ts +1 -1
package/README.md
CHANGED
|
@@ -2,287 +2,341 @@
|
|
|
2
2
|
[](https://codecov.io/gh/schibsted/account-sdk-browser)
|
|
3
3
|
[](https://snyk.io/test/github/schibsted/account-sdk-browser)
|
|
4
4
|
|
|
5
|
-
# Schibsted
|
|
5
|
+
# Schibsted Account SDK for browsers
|
|
6
6
|
|
|
7
|
-
Welcome! This is the home of the Schibsted
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
products and subscriptions, etc.
|
|
7
|
+
Welcome! This is the home of the Schibsted Account JavaScript SDK for browsers. Use it to let users
|
|
8
|
+
sign up and log in with Schibsted Account, read the current session, and check access to products
|
|
9
|
+
and features.
|
|
11
10
|
|
|
12
|
-
##
|
|
11
|
+
## Public API
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
Create one SDK instance with `createAccountSdk()`. Use `getAccountSdk()` when another module needs
|
|
14
|
+
to wait for that initialized `Account` instance.
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
and will not be sent with a XHR request.
|
|
16
|
+
The package publishes ES modules and modern JavaScript, including async/await and WHATWG browser
|
|
17
|
+
APIs. It does not include polyfills.
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
## Installation
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
```sh
|
|
22
|
+
npm install --save @schibsted/account-sdk-browser
|
|
23
|
+
```
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
syntax (including async/await and other ES2017 and WHATWG features). We recommend that you do
|
|
30
|
-
any transpilation yourself for the browser versions you need to cater to. We do not add polyfills.
|
|
31
|
-
4. Initiate the SDK with `createAccountSdk` and provide `clientId`, `redirectUri` and `sessionDomain`.
|
|
32
|
-
Set `env` if you do not want to use the default `PRE` environment.
|
|
25
|
+
```js
|
|
26
|
+
import { createAccountSdk, getAccountSdk } from '@schibsted/account-sdk-browser';
|
|
27
|
+
```
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
[support](mailto:schibstedaccount@schibsted.com) to initiate the process.
|
|
29
|
+
## Before You Start
|
|
36
30
|
|
|
37
|
-
|
|
31
|
+
The SDK communicates mainly with Session Service on a brand domain such as `id.vg.no`. Your website
|
|
32
|
+
and Session Service domain must share the same top-level site so browser cookies are sent with XHR
|
|
33
|
+
requests.
|
|
38
34
|
|
|
39
|
-
|
|
35
|
+
For local development:
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
- serve your site over HTTPS, because Session Service is hosted over HTTPS
|
|
38
|
+
- use a local hostname with the same top-level site as the configured Session Service domain
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
1. If the user is not logged-in to your site, call the [showSimplifiedLoginWidget](https://schibsted.github.io/account-sdk-browser/classes/Account.html#showsimplifiedloginwidget) function. The `showSimplifiedLoginWidget` accepts the same params as login function (`state` is required, it might be string or async function). If the simplified login prompt is to be loaded, `showSimplifiedLoginWidget` will return `true`.
|
|
47
|
-
1. Set up a way to store information about which users have been shown the simplified login prompt. How you do this is up to you, but one way is to use localStorage. Use this information to execute on the rules defined in #2.
|
|
40
|
+
For example, if your pre-production site is `pre.sdk-example.com` and uses
|
|
41
|
+
`id.pre.sdk-example.com` as Session Service, use a local hostname such as
|
|
42
|
+
`local.sdk-example.com`.
|
|
48
43
|
|
|
49
|
-
|
|
44
|
+
If this is a new site and you do not have a `sessionDomain` yet, contact
|
|
45
|
+
[support](mailto:schibstedaccount@schibsted.com).
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
[here](https://schibsted.ghe.com/user-identity/sdk-example), and you can see it live
|
|
53
|
-
[here](https://pro.sdk-example.com). You have a use-case that we haven't thought of? Ask us to add
|
|
54
|
-
it by creating an [issue](https://schibsted.ghe.com/user-identity/sdk-example/issues/new).
|
|
47
|
+
## Initialize the SDK
|
|
55
48
|
|
|
56
|
-
|
|
57
|
-
module is used for authenticating the user with Schibsted account. Take a look at how the SDK is
|
|
58
|
-
initialized.
|
|
49
|
+
Create the SDK once during application startup:
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
This means we pass a `code` in the query string of that redirect URI.
|
|
63
|
-
You can use that `code` on your site's backend, along with your client credentials (client ID and secret), to obtain an *Access Token* (AT) and a *Refresh Token* (RT).
|
|
64
|
-
You should not send the AT (and **never** the RT!) to the browser. Instead, keep them on the server side and associate them with the specific user session.
|
|
65
|
-
This allows you to call Schibsted Account APIs on behalf of that user.
|
|
51
|
+
```js
|
|
52
|
+
import { createAccountSdk } from '@schibsted/account-sdk-browser';
|
|
66
53
|
|
|
67
|
-
|
|
54
|
+
const account = createAccountSdk({
|
|
55
|
+
clientId: '56e9a5d1eee0000000000000',
|
|
56
|
+
redirectUri: 'https://awesomenews.site/callback',
|
|
57
|
+
sessionDomain: 'https://id.awesomenews.site',
|
|
58
|
+
env: 'PRE',
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Required configuration:
|
|
63
|
+
|
|
64
|
+
- `clientId`: your Schibsted Account client id
|
|
65
|
+
- `redirectUri`: the callback URL registered for your client
|
|
66
|
+
- `sessionDomain`: your client-configured Session Service domain
|
|
67
|
+
|
|
68
|
+
Optional configuration:
|
|
69
|
+
|
|
70
|
+
- `env`: defaults to `PRE`; supported keys include `LOCAL`, `DEV`, `PRE`, `PRO`, `PRO_NO`,
|
|
71
|
+
`PRO_FI`, and `PRO_DK`
|
|
72
|
+
- `callbackBeforeRedirect`: called before a full-page session refresh redirect
|
|
73
|
+
- `log`: receives SDK debug log lines
|
|
74
|
+
- `varnish`: enables Varnish cookie handling
|
|
75
|
+
- `window`: overrides the browser window object, mostly useful in tests
|
|
76
|
+
|
|
77
|
+
`createAccountSdk()` registers the instance on `window.schAccount` and emits
|
|
78
|
+
`schAccount:ready` event.
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
window.addEventListener('schAccount:ready', (event) => {
|
|
82
|
+
const account = event.detail.instance;
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
If another module needs the initialized instance, use `getAccountSdk()`:
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
import { getAccountSdk } from '@schibsted/account-sdk-browser';
|
|
90
|
+
|
|
91
|
+
const account = await getAccountSdk();
|
|
92
|
+
```
|
|
68
93
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
familiar interface that's very similar to Node's [EventEmitter](https://nodejs.org/api/events.html). The most important
|
|
72
|
-
methods are `.on(eventName, listener)` (to subscribe to an event) and `.off(eventName, listener)`
|
|
73
|
-
(to unsubscribe to an event).
|
|
94
|
+
`getAccountSdk()` resolves immediately if the SDK has already been initialized. Otherwise it waits
|
|
95
|
+
for `schAccount:ready` and rejects if initialization does not happen within 4000 ms.
|
|
74
96
|
|
|
75
|
-
|
|
97
|
+
## Basic Usage
|
|
76
98
|
|
|
77
|
-
|
|
78
|
-
| ------------ | ----------------------- |
|
|
79
|
-
| Account | `schAccount:ready` |
|
|
99
|
+
After initialization, use the `Account` instance to render user state and start login when needed:
|
|
80
100
|
|
|
81
101
|
```js
|
|
82
|
-
|
|
83
|
-
|
|
102
|
+
async function renderLoginState() {
|
|
103
|
+
const container = document.getElementById('login-container');
|
|
104
|
+
|
|
105
|
+
if (await account.isConnected()) {
|
|
106
|
+
const user = await account.getUser();
|
|
107
|
+
container.textContent = `Hello ${user.givenName || user.displayName || user.userId}`;
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
container.innerHTML = '<button type="button">Log in</button>';
|
|
112
|
+
container.querySelector('button').addEventListener('click', () => {
|
|
113
|
+
account.login({ state: createLoginState() });
|
|
114
|
+
});
|
|
84
115
|
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Login Flow
|
|
119
|
+
|
|
120
|
+
Use `account.login()` to start the OAuth authorization flow:
|
|
85
121
|
|
|
122
|
+
```js
|
|
123
|
+
account.login({
|
|
124
|
+
state: createLoginState(),
|
|
125
|
+
scope: 'openid',
|
|
126
|
+
preferPopup: false,
|
|
127
|
+
});
|
|
86
128
|
```
|
|
87
129
|
|
|
88
|
-
|
|
130
|
+
By default the SDK redirects the current window. Set `preferPopup: true` when login is triggered by
|
|
131
|
+
a user gesture and you want to try a popup first. If the popup cannot be opened, the SDK falls back
|
|
132
|
+
to the redirect flow.
|
|
133
|
+
|
|
134
|
+
If you only need the URL, use `account.loginUrl()`:
|
|
89
135
|
|
|
90
|
-
|
|
136
|
+
```js
|
|
137
|
+
const url = account.loginUrl({ state: createLoginState() });
|
|
138
|
+
```
|
|
91
139
|
|
|
92
|
-
|
|
140
|
+
### Handling `state`
|
|
93
141
|
|
|
94
|
-
|
|
95
|
-
|
|
142
|
+
`state` is an opaque OpenID Connect value that is returned to your `redirectUri` with the
|
|
143
|
+
authorization `code`. Use it to protect against CSRF and to restore application state.
|
|
144
|
+
|
|
145
|
+
A common pattern is:
|
|
146
|
+
|
|
147
|
+
1. Your backend creates a random token and stores it temporarily.
|
|
148
|
+
2. Your frontend calls `account.login({ state })` with that token, or with an encoded payload that
|
|
149
|
+
contains it.
|
|
150
|
+
3. Schibsted Account redirects back to your `redirectUri` with `code` and `state`.
|
|
151
|
+
4. Your backend validates the returned `state` before exchanging `code` for tokens.
|
|
152
|
+
|
|
153
|
+
Keep Access Tokens and Refresh Tokens on your backend. Do not send them to the browser.
|
|
154
|
+
|
|
155
|
+
### Authentication Methods
|
|
156
|
+
|
|
157
|
+
Use `acrValues` when you need to request a specific authentication method:
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
account.login({
|
|
161
|
+
state: createLoginState(),
|
|
162
|
+
acrValues: 'otp-email',
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Supported values include `password`, `otp`, `sms`, `otp-email`, `eid`, `eid-no`, `eid-se`,
|
|
167
|
+
`eid-fi`, and `eid-dk`. Values other than `otp-email` can be combined as a space-separated string
|
|
168
|
+
where supported by the account flow. Verify the resulting AMR claim in the ID token on your backend
|
|
169
|
+
if you need to enforce a completed authentication method.
|
|
170
|
+
|
|
171
|
+
## Session and User Data
|
|
172
|
+
|
|
173
|
+
Use these methods to inspect the current Session Service state:
|
|
174
|
+
|
|
175
|
+
- `account.hasSession()` returns the raw SDK-known session response
|
|
176
|
+
- `account.isLoggedIn()` returns whether the browser has a Schibsted Account session
|
|
177
|
+
- `account.isConnected()` returns whether the user is connected to your client
|
|
178
|
+
- `account.getUser()` returns the connected user session data
|
|
179
|
+
- `account.getUserId()` returns the realm-specific user id as a string
|
|
180
|
+
- `account.getUserUuid()` returns the globally unique user id
|
|
181
|
+
- `account.getUserSDRN()` returns the user SDRN
|
|
182
|
+
- `account.getSpId()` returns the Varnish `sp_id` value when present
|
|
96
183
|
|
|
184
|
+
Some session methods can trigger a full-page Session Service refresh redirect, especially for
|
|
185
|
+
Safari-based browsers. Use `callbackBeforeRedirect` if you need to persist client state before that
|
|
186
|
+
happens.
|
|
187
|
+
|
|
188
|
+
```js
|
|
97
189
|
const account = createAccountSdk({
|
|
98
|
-
clientId
|
|
99
|
-
redirectUri
|
|
100
|
-
|
|
101
|
-
|
|
190
|
+
clientId,
|
|
191
|
+
redirectUri,
|
|
192
|
+
sessionDomain,
|
|
193
|
+
callbackBeforeRedirect: () => {
|
|
194
|
+
saveCurrentUiState();
|
|
195
|
+
},
|
|
102
196
|
});
|
|
197
|
+
```
|
|
103
198
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
199
|
+
## Logout and Account Page
|
|
200
|
+
|
|
201
|
+
Use `account.logout()` to remove the brand Session Service session and redirect the browser:
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
account.logout('https://awesomenews.site/logged-out');
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Use `account.logoutUrl()` when you need the logout URL without navigating immediately:
|
|
208
|
+
|
|
209
|
+
```js
|
|
210
|
+
const logoutUrl = account.logoutUrl('https://awesomenews.site/logged-out');
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Use `account.accountUrl()` to send the user to their Schibsted Account profile page:
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
window.location.href = account.accountUrl('https://awesomenews.site/account-return');
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Access Checks
|
|
220
|
+
|
|
221
|
+
Use `account.hasAccess()` to check access to Schibsted Account product ids or Zuora feature ids:
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
const userId = await account.getUserId();
|
|
225
|
+
const access = await account.hasAccess(['product-id'], userId);
|
|
226
|
+
|
|
227
|
+
if (access?.entitled) {
|
|
228
|
+
showPremiumContent();
|
|
229
|
+
} else {
|
|
230
|
+
showPaywall();
|
|
114
231
|
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`hasAccess()` requires `sessionDomain`. Results are cached according to the Session Service TTL.
|
|
235
|
+
Use `account.clearCachedAccessResult(productIds, userId)` when you need to invalidate that cache.
|
|
115
236
|
|
|
116
|
-
|
|
117
|
-
|
|
237
|
+
## Simplified Login Widget
|
|
238
|
+
|
|
239
|
+
Before using the simplified login widget, make sure your site has no site-specific terms and
|
|
240
|
+
conditions in the Schibsted Account login flow.
|
|
241
|
+
|
|
242
|
+
The widget is shown only when the SDK can read enough user context from the global account session.
|
|
243
|
+
Your application decides when and how often to show it.
|
|
244
|
+
|
|
245
|
+
```js
|
|
246
|
+
if (!(await account.isConnected()) && shouldShowSimplifiedLogin()) {
|
|
247
|
+
const opened = await account.showSimplifiedLoginWidget(
|
|
248
|
+
{ state: createLoginState },
|
|
249
|
+
{ locale: 'nb' },
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
if (opened) {
|
|
253
|
+
rememberSimplifiedLoginWasShown();
|
|
254
|
+
}
|
|
118
255
|
}
|
|
119
256
|
```
|
|
120
257
|
|
|
121
|
-
|
|
258
|
+
`state` may be a string or a function that returns a string or `Promise<string>`. The function is
|
|
259
|
+
called only if the user continues from the widget.
|
|
122
260
|
|
|
123
|
-
|
|
124
|
-
import { getAccountSdk } from '@schibsted/account-sdk-browser';
|
|
261
|
+
## Events
|
|
125
262
|
|
|
126
|
-
|
|
263
|
+
The SDK exposes fluent `on()` and `off()` aliases for browser-native event listeners.
|
|
264
|
+
Payload-bearing events are `CustomEvent` instances and expose their payload through `detail`:
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import type { AccountEventListener } from '@schibsted/account-sdk-browser';
|
|
268
|
+
|
|
269
|
+
const handleLogin: AccountEventListener<'login'> = (event) => {
|
|
270
|
+
console.log('Login started', event.detail.url, event.detail.method);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
account.on('login', handleLogin);
|
|
274
|
+
account.off('login', handleLogin);
|
|
127
275
|
```
|
|
128
276
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
This parameter is an OpenID Connect parameter (described in [this paragraph in the
|
|
132
|
-
spec](http://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.1)). It's formatted as
|
|
133
|
-
an opaque string. This means you can send anything that can be serialized to a string. In practice,
|
|
134
|
-
we have good experience sending something like a JSON value like a base64-url-encoded value — it's
|
|
135
|
-
just an easy way to avoid browsers or backends messing with special characters.
|
|
136
|
-
|
|
137
|
-
But as a trivial example, if you call `account.login(..)` with params
|
|
138
|
-
`redirectUri=https://site.com&state=article%3D1234` — then at the end of the authentication flow,
|
|
139
|
-
the user will be sent back to your redirectUri, and the `state` parameter will be forwarded along
|
|
140
|
-
with the auth `code` parameter.
|
|
141
|
-
|
|
142
|
-
It is recommended that you provide a unique identifier as part of the state, to prevent CSRF
|
|
143
|
-
attacks. For example this can be accomplished by:
|
|
144
|
-
|
|
145
|
-
1. Your backend generates random token: `1234abcd`, saves it in some tokenCache, and forwards to
|
|
146
|
-
your browser frontend
|
|
147
|
-
1. Your frontend calls `account.login` with `state = base64Urlencode({ token: '1234abcd', article:
|
|
148
|
-
'1234', ... })`
|
|
149
|
-
1. When auth flow completes, the user is redirected back to your site. Then, your backend sees the
|
|
150
|
-
query parameters `code` (which it can exchange for OAuth tokens for the user) and `state`
|
|
151
|
-
1. Your backend can do `decodedState = base64Urldecode(query.state)` and then verify that its
|
|
152
|
-
`tokenCache.contains(decodedState.token)`. If that fails, then possibly a CSRF attack was
|
|
153
|
-
attempted. If successful, remove the token from the tokenCache so the same token can't be used
|
|
154
|
-
again, and continue to show `decodedState.article`
|
|
155
|
-
|
|
156
|
-
#### Authentication methods
|
|
157
|
-
|
|
158
|
-
Although Schibsted account abstracts away the details of how the users sign up or log in, it's worth
|
|
159
|
-
mentioning that your end users have a few ways to log in:
|
|
160
|
-
|
|
161
|
-
* Username & password: pretty self-explanatory; users register using an email address and a
|
|
162
|
-
self-chosen password
|
|
163
|
-
* Passwordless - email: here, the users enter their email address and receive a one-time code that
|
|
164
|
-
they can use to log in
|
|
165
|
-
* Multifactor authentication: first client indicates which methods should be preferred, later these
|
|
166
|
-
will be included (if fulfilled) in `AMR` claim of IDToken
|
|
167
|
-
|
|
168
|
-
The default is username & password. If you wish to use one of the passwordless login methods,
|
|
169
|
-
`account.login()` takes an optional parameter called `acrValues` (Authentication Context Class Reference).
|
|
170
|
-
The `acrValues` parameter with multifactor authentication can take following values:
|
|
171
|
-
|
|
172
|
-
* `eid` - authentication using BankID (for DEV and PRE environments you can choose between country specific solution by specifying `eid-no` or `eid-se` instead)
|
|
173
|
-
* `otp-email` - passwordless authentication using code sent to registered email
|
|
174
|
-
* `password` - force password authentication (even if user is already logged in)
|
|
175
|
-
* `otp` - authentication using registered one time code generator (https://tools.ietf.org/html/rfc6238)
|
|
176
|
-
* `sms` - authentication using SMS code sent to phone number
|
|
177
|
-
* `password otp sms` - those authentication methods might be combined
|
|
178
|
-
|
|
179
|
-
The classic way to authenticate a user, is to send them from your site to the Schibsted account
|
|
180
|
-
domain, let the user authenticate there, and then have us redirect them back to your site. If you
|
|
181
|
-
prefer, we also provide a popup that you can use. In this method, the authentication happens on a
|
|
182
|
-
separate popup window and at the end of the auth flow. We recommend that you make the popup send a
|
|
183
|
-
signal to your main page — using
|
|
184
|
-
[postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) or something
|
|
185
|
-
similar — to indicate that the user is logged in. If the popup window fails to open, it'll
|
|
186
|
-
automatically fall back to the redirect flow. The SDK Example project mentioned above demonstrates
|
|
187
|
-
how it can work. Again, you can see [sdk-example](https://schibsted.ghe.com/user-identity/sdk-example) if you
|
|
188
|
-
want a working example.
|
|
189
|
-
|
|
190
|
-
#### Is the user logged in?
|
|
191
|
-
|
|
192
|
-
Schibsted account relies on browser cookies to determine whether a user is recognized as logged in.
|
|
193
|
-
The SDK provides functions that can be used to check if the user that's visiting your site is
|
|
194
|
-
already a Schibsted user or not.
|
|
195
|
-
|
|
196
|
-
* `account.isLoggedIn()`
|
|
197
|
-
tells you if the user that is visiting your site is already logged in to Schibsted account or not.
|
|
198
|
-
|
|
199
|
-
* `account.isConnected()`
|
|
200
|
-
tells you if the user is connected to your client. A user might have `isLoggedIn=true` and at the
|
|
201
|
-
same time `isConnected=false` if they have logged in to Schibsted account, but not accepted terms
|
|
202
|
-
and privacy policy for your site.
|
|
203
|
-
|
|
204
|
-
If you've lately changed your terms & conditions, maybe the user still hasn't accepted them. In that
|
|
205
|
-
case they are considered *not connected*. In that case, if they click "Log in" from your site, we
|
|
206
|
-
will just ask them to accept those terms and redirect them right back to your site.
|
|
207
|
-
|
|
208
|
-
#### Logging out
|
|
209
|
-
|
|
210
|
-
If you want to log the user out of Schibsted account, you can call
|
|
211
|
-
`account.logout()`. This
|
|
212
|
-
will remove the Schibsted account brand session. User will still be logged into Schibsted account.
|
|
277
|
+
Available Account events:
|
|
213
278
|
|
|
214
|
-
|
|
279
|
+
- `login` — a `CustomEvent` whose `detail` contains `url` and the `method` (`popup` or `default`)
|
|
280
|
+
- `logout` — a `CustomEvent` whose `detail` contains the logout `url`
|
|
281
|
+
- `simplifiedLoginOpened` — an `Event` emitted when the widget is displayed
|
|
282
|
+
- `simplifiedLoginCancelled` — an `Event` emitted when the widget is closed
|
|
215
283
|
|
|
216
|
-
The
|
|
217
|
-
`account.hasAccess()`.
|
|
218
|
-
It requires using Session Service, and supports both Schibsted account productId's and Zuora
|
|
219
|
-
feature id's.
|
|
284
|
+
The SDK also emits `schAccount:ready` on `window` when an Account instance is created.
|
|
220
285
|
|
|
221
|
-
|
|
286
|
+
## Errors
|
|
222
287
|
|
|
223
|
-
|
|
224
|
-
|
|
288
|
+
Validation, network, and service failures from API calls reject or throw `SDKError`. Convenience
|
|
289
|
+
methods such as `isLoggedIn()`, `isConnected()`, and `getSpId()` return fallback values instead of
|
|
290
|
+
throwing when the session lookup fails.
|
|
291
|
+
|
|
292
|
+
```js
|
|
293
|
+
import { SDKError } from '@schibsted/account-sdk-browser';
|
|
225
294
|
|
|
226
295
|
try {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
} catch (err) {
|
|
233
|
-
alert(`Could not query if the user has access to ${productId} because ${err}`);
|
|
296
|
+
await account.getUser();
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error instanceof SDKError) {
|
|
299
|
+
console.error(error.toString());
|
|
300
|
+
}
|
|
234
301
|
}
|
|
235
302
|
```
|
|
236
303
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
There are some cookies used by Schibsted account. They should all be considered opaque on the
|
|
240
|
-
browser side. Nevertheless, here is a short description of them.
|
|
241
|
-
|
|
242
|
-
1. The **autologin** cookie (often called 'the remember-me-cookie'): The cookie name in the
|
|
243
|
-
production environments is `vgs_email`, because reasons (on PRE, it is called `spid-pre-data`).
|
|
244
|
-
It's a JSON string that's encoded using the standard `encodeURIComponent()` function and is an
|
|
245
|
-
object that contains two pieces of information that's important:
|
|
246
|
-
* `remember`: if set to `true`, the user chose to be remembered and this means we usually support
|
|
247
|
-
auto-login (that is, if you call the Schibsted account hassession service, and no session can
|
|
248
|
-
be found in the session database, it will automatically create a new one for the user so that
|
|
249
|
-
they don't have to authenticate again. If it is `false`, it should be interpreted as the user
|
|
250
|
-
does not want to be automatically logged in to any site when their session expires
|
|
251
|
-
* `v`: the version number
|
|
252
|
-
1. The **session** cookies: Cookie names in production environments are `identity`, and `SPID_SE` or
|
|
253
|
-
`SPID_NO`. It contains:
|
|
254
|
-
* `user`: an object (if it's missing, a call to hassession will return a `401` with a
|
|
255
|
-
`UserException` that says `No session found`)
|
|
256
|
-
* `userId` identifies the user. We use this property to compare "old" user with "new" user and
|
|
257
|
-
fire events that indicate that the user has changed
|
|
258
|
-
* `is_logged_in` indicates if the user is logged in
|
|
259
|
-
* `user_tags`: a map that contains some flags about the user; namely:
|
|
260
|
-
* `is_logged_in` indicates if the user is logged in (this seems to be a duplicate of a
|
|
261
|
-
property with a similar name in the parent `user` object)
|
|
262
|
-
* `terms`: a map of term ids that indicate if they've been accepted by the user.
|
|
263
|
-
* `referer` (yep, missing the double "rr"..): If this is missing, a call to hassession will
|
|
264
|
-
return a `401` with a `UserException` that says `No session found`.
|
|
304
|
+
## API Documentation
|
|
265
305
|
|
|
266
|
-
|
|
306
|
+
Public API documentation is generated from TypeScript source comments with TypeDoc.
|
|
267
307
|
|
|
268
|
-
|
|
308
|
+
```sh
|
|
309
|
+
npm run docs:build
|
|
310
|
+
npm run docs:open
|
|
311
|
+
```
|
|
269
312
|
|
|
270
|
-
|
|
271
|
-
The suggested version is based on the commit messages in accordance with the [Conventional Commits](https://www.conventionalcommits.org/) specification — `fix:` bumps the patch version, `feat:` bumps the minor version, and `feat!:` or a `BREAKING CHANGE:` footer bumps the major version.
|
|
272
|
-
Other prefixes (`chore:`, `docs:`, `test:`, `refactor:`, `ci:`, `build:`, `style:`) do not trigger a release and are hidden from the changelog.
|
|
313
|
+
During documentation work, use:
|
|
273
314
|
|
|
274
|
-
|
|
275
|
-
|
|
315
|
+
```sh
|
|
316
|
+
npm run docs:watch
|
|
317
|
+
```
|
|
276
318
|
|
|
319
|
+
Generated docs are written to `docs/` and are not committed.
|
|
277
320
|
|
|
278
|
-
##
|
|
321
|
+
## Example Project
|
|
279
322
|
|
|
280
|
-
|
|
323
|
+
An example integration is available in the
|
|
324
|
+
[sdk-example repository](https://schibsted.ghe.com/user-identity/sdk-example), with a live example
|
|
325
|
+
at [pro.sdk-example.com](https://pro.sdk-example.com).
|
|
281
326
|
|
|
282
|
-
|
|
283
|
-
|
|
327
|
+
## Publishing
|
|
328
|
+
|
|
329
|
+
Versioning and changelog updates are handled by
|
|
330
|
+
[Release Please](https://github.com/googleapis/release-please). The release configuration lives in
|
|
331
|
+
[`release-please-config.json`](./release-please-config.json), and publishing to
|
|
332
|
+
[npmjs.org](https://www.npmjs.com/package/@schibsted/account-sdk-browser) is handled by the
|
|
333
|
+
[npm-publish workflow](./.github/workflows/npm-publish.yml) when a GitHub Release is published.
|
|
334
|
+
|
|
335
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/) for changes that should be picked
|
|
336
|
+
up by release automation.
|
|
337
|
+
|
|
338
|
+
## License
|
|
339
|
+
|
|
340
|
+
Copyright (c) 2026 Schibsted Products & Technology AS
|
|
284
341
|
|
|
285
|
-
|
|
286
|
-
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
287
|
-
implied. See the License for the specific language governing permissions and limitations under the
|
|
288
|
-
License.
|
|
342
|
+
Licensed under the [MIT License](./LICENSE.md).
|
package/dist/account-sdk.d.ts
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import { Account } from './account.js';
|
|
2
2
|
import { AccountConfig } from './types/account.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates and registers the single Account SDK instance for the current browser window.
|
|
5
|
+
*
|
|
6
|
+
* The created instance is stored on `window.schAccount` and the SDK emits
|
|
7
|
+
* `schAccount:ready` with the instance in `event.detail.instance`.
|
|
8
|
+
*
|
|
9
|
+
* @param config - Client, redirect, environment, and Session Service configuration.
|
|
10
|
+
* @throws {SDKError} If the SDK cannot run in the current browser context, if an Account instance
|
|
11
|
+
* has already been initialized, or if configuration validation fails.
|
|
12
|
+
* @group Core API
|
|
13
|
+
*/
|
|
3
14
|
export declare function createAccountSdk(config: AccountConfig): Account;
|
|
15
|
+
/**
|
|
16
|
+
* Resolves the Account SDK instance registered by `createAccountSdk()`.
|
|
17
|
+
*
|
|
18
|
+
* If the instance already exists, the promise resolves immediately. Otherwise it waits for
|
|
19
|
+
* `schAccount:ready` and rejects if initialization does not happen within the SDK timeout.
|
|
20
|
+
* @group Core API
|
|
21
|
+
*/
|
|
4
22
|
export declare function getAccountSdk(): Promise<Account>;
|