@cboxdk/id-js 0.15.1 → 0.18.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/README.md +455 -4
- package/dist/chunk-2E25IPBA.js +155 -0
- package/dist/chunk-2E25IPBA.js.map +1 -0
- package/dist/{chunk-3V6OKRWF.js → chunk-CXGKOJRJ.js} +374 -90
- package/dist/chunk-CXGKOJRJ.js.map +1 -0
- package/dist/chunk-QQW63PGU.js +25 -0
- package/dist/chunk-QQW63PGU.js.map +1 -0
- package/dist/chunk-SEUD4TE4.js +61 -0
- package/dist/chunk-SEUD4TE4.js.map +1 -0
- package/dist/{client-CecDIu_N.d.cts → client-BSZASrMo.d.ts} +109 -136
- package/dist/{client-CecDIu_N.d.ts → client-BxUHm5hX.d.cts} +109 -136
- package/dist/errors-D61xljZE.d.cts +87 -0
- package/dist/errors-D61xljZE.d.ts +87 -0
- package/dist/index.cjs +440 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -90
- package/dist/index.d.ts +40 -90
- package/dist/index.js +64 -25
- package/dist/index.js.map +1 -1
- package/dist/management.cjs +4372 -0
- package/dist/management.cjs.map +1 -0
- package/dist/management.d.cts +10923 -0
- package/dist/management.d.ts +10923 -0
- package/dist/management.js +4335 -0
- package/dist/management.js.map +1 -0
- package/dist/nextjs.cjs +517 -42
- package/dist/nextjs.cjs.map +1 -1
- package/dist/nextjs.d.cts +29 -8
- package/dist/nextjs.d.ts +29 -8
- package/dist/nextjs.js +42 -12
- package/dist/nextjs.js.map +1 -1
- package/dist/server.cjs +220 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +105 -0
- package/dist/server.d.ts +105 -0
- package/dist/server.js +5 -0
- package/dist/server.js.map +1 -0
- package/dist/types-BYZldock.d.cts +316 -0
- package/dist/types-BYZldock.d.ts +316 -0
- package/package.json +14 -2
- package/dist/chunk-3V6OKRWF.js.map +0 -1
|
@@ -1,130 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
interface CboxIdConfig {
|
|
3
|
-
/**
|
|
4
|
-
* Base URL (issuer) of the Cbox ID instance, e.g. `https://id.acme.com`. Every
|
|
5
|
-
* endpoint is discovered from `{issuer}/.well-known/openid-configuration`, so this
|
|
6
|
-
* is usually the only endpoint you configure.
|
|
7
|
-
*/
|
|
8
|
-
issuer: string;
|
|
9
|
-
/** Your registered OAuth client id. */
|
|
10
|
-
clientId: string;
|
|
11
|
-
/**
|
|
12
|
-
* Your client secret. Required for confidential (server-side) apps, machine
|
|
13
|
-
* tokens and introspection. Omit for public clients (SPA/native) that only do
|
|
14
|
-
* PKCE login.
|
|
15
|
-
*/
|
|
16
|
-
clientSecret?: string;
|
|
17
|
-
/** Your callback URL — must exactly match one registered on the client. */
|
|
18
|
-
redirectUri: string;
|
|
19
|
-
/** Scopes requested at login. Defaults to `['openid', 'profile', 'email']`. */
|
|
20
|
-
scopes?: string[];
|
|
21
|
-
/**
|
|
22
|
-
* Path of the instance's hosted account page that {@link CboxIdClient.profileUrl}
|
|
23
|
-
* points at. Defaults to `/settings`.
|
|
24
|
-
*/
|
|
25
|
-
accountPath?: string;
|
|
26
|
-
/** Timeout (ms) for back-channel HTTP calls. Defaults to `10000`. */
|
|
27
|
-
timeoutMs?: number;
|
|
28
|
-
/** How long (ms) the discovery document is cached. Defaults to `3600000` (1h). */
|
|
29
|
-
cacheTtlMs?: number;
|
|
30
|
-
/**
|
|
31
|
-
* Leeway (seconds) when checking the id_token's `auth_time` against the `maxAge` you
|
|
32
|
-
* requested at login. Defaults to `60`.
|
|
33
|
-
*
|
|
34
|
-
* Some slack is required, not optional: `maxAge` bounds the age of the
|
|
35
|
-
* AUTHENTICATION, but `auth_time` is read after a browser redirect and a token
|
|
36
|
-
* exchange, so even a just-completed re-authentication is already several seconds
|
|
37
|
-
* old — and the RP's clock and the instance's need not agree. Sixty seconds absorbs
|
|
38
|
-
* that while still catching what this check exists for: a session hours or days old
|
|
39
|
-
* being passed off as fresh.
|
|
40
|
-
*/
|
|
41
|
-
authTimeToleranceSeconds?: number;
|
|
42
|
-
}
|
|
43
|
-
/** The OIDC discovery document fields this SDK uses. */
|
|
44
|
-
interface DiscoveryDocument {
|
|
45
|
-
issuer: string;
|
|
46
|
-
authorization_endpoint: string;
|
|
47
|
-
token_endpoint: string;
|
|
48
|
-
jwks_uri: string;
|
|
49
|
-
userinfo_endpoint?: string;
|
|
50
|
-
introspection_endpoint?: string;
|
|
51
|
-
revocation_endpoint?: string;
|
|
52
|
-
end_session_endpoint?: string;
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* RFC 7009 `token_type_hint`: which token store the server should search first.
|
|
56
|
-
* Only a hint — the server must still find the token if the hint is wrong.
|
|
57
|
-
*/
|
|
58
|
-
type TokenTypeHint = 'access_token' | 'refresh_token';
|
|
59
|
-
/**
|
|
60
|
-
* The values {@link CboxIdClient.createAuthorizationRequest} returns. Persist
|
|
61
|
-
* `state`, `codeVerifier` and `nonce` (e.g. in signed, httpOnly cookies) and hand
|
|
62
|
-
* them back to {@link CboxIdClient.authenticate} on the callback.
|
|
63
|
-
*/
|
|
64
|
-
interface AuthorizationRequest {
|
|
65
|
-
/** The URL to redirect the user to. */
|
|
66
|
-
url: string;
|
|
67
|
-
state: string;
|
|
68
|
-
codeVerifier: string;
|
|
69
|
-
nonce: string;
|
|
70
|
-
/**
|
|
71
|
-
* Echoed back when you passed `maxAge`. Persist it with the rest and hand it to
|
|
72
|
-
* {@link CboxIdClient.authenticate}, which then verifies the id_token's `auth_time`
|
|
73
|
-
* against it — a step-up nobody checks is not a step-up.
|
|
74
|
-
*/
|
|
75
|
-
maxAge?: number;
|
|
76
|
-
}
|
|
77
|
-
/** The raw token-endpoint response. */
|
|
78
|
-
interface TokenResponse {
|
|
79
|
-
access_token: string;
|
|
80
|
-
token_type?: string;
|
|
81
|
-
id_token?: string;
|
|
82
|
-
refresh_token?: string;
|
|
83
|
-
expires_in?: number;
|
|
84
|
-
scope?: string;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* The tokens returned by {@link CboxIdClient.refresh}. Cbox ID ROTATES refresh
|
|
88
|
-
* tokens and detects reuse, so `refreshToken` is a NEW value — store it and discard
|
|
89
|
-
* the one you presented; replaying a rotated token revokes the whole family.
|
|
90
|
-
*/
|
|
91
|
-
interface RefreshedTokens {
|
|
92
|
-
accessToken: string;
|
|
93
|
-
refreshToken: string;
|
|
94
|
-
idToken: string | null;
|
|
95
|
-
expiresIn: number;
|
|
96
|
-
scope: string | null;
|
|
97
|
-
}
|
|
98
|
-
/** One organization a user belongs to, from the `organizations` claim when present. */
|
|
99
|
-
interface CboxOrganization {
|
|
100
|
-
id: string;
|
|
101
|
-
name: string;
|
|
102
|
-
/** The member's role in this organization, when the claim carries it. */
|
|
103
|
-
role?: string | null;
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* The authenticated Cbox ID user. `id` is the stable opaque subject (`sub`) you key
|
|
107
|
-
* your local account on. `claims` is the full verified id_token + userinfo claim
|
|
108
|
-
* set; the named fields are conveniences over it.
|
|
109
|
-
*/
|
|
110
|
-
interface CboxUser {
|
|
111
|
-
id: string;
|
|
112
|
-
email: string | null;
|
|
113
|
-
name: string | null;
|
|
114
|
-
/** The active organization's id (`org` claim). */
|
|
115
|
-
organizationId: string | null;
|
|
116
|
-
/**
|
|
117
|
-
* The organizations this user belongs to, when the instance emits an
|
|
118
|
-
* `organizations` claim. Undefined when the claim is absent (single-org apps, or
|
|
119
|
-
* an instance that doesn't include it). Pass straight to `<OrganizationSwitcher>`.
|
|
120
|
-
*/
|
|
121
|
-
organizations?: CboxOrganization[];
|
|
122
|
-
claims: Record<string, unknown>;
|
|
123
|
-
accessToken: string;
|
|
124
|
-
refreshToken: string | null;
|
|
125
|
-
idToken: string | null;
|
|
126
|
-
expiresIn: number;
|
|
127
|
-
}
|
|
1
|
+
import { a as CboxIdConfig, A as AuthorizationRequestOptions, b as AuthorizationRequest, C as CboxUser, D as DeviceAuthorization, R as RefreshedTokens, T as TokenTypeHint } from './types-BYZldock.cjs';
|
|
128
2
|
|
|
129
3
|
/** A stored vault secret's metadata (never its plaintext). */
|
|
130
4
|
interface VaultSecretRef {
|
|
@@ -204,6 +78,34 @@ interface VerifyWebhookOptions {
|
|
|
204
78
|
}
|
|
205
79
|
/** Returns `true` only when the signature is present, fresh and valid. Never throws. */
|
|
206
80
|
declare function verifyWebhook(options: VerifyWebhookOptions): Promise<boolean>;
|
|
81
|
+
/** Headers as a `Headers` object or a plain record (Node's `IncomingHttpHeaders`, a framework's map). */
|
|
82
|
+
type WebhookHeaders = Headers | Record<string, string | readonly string[] | undefined>;
|
|
83
|
+
interface VerifyStandardWebhookOptions {
|
|
84
|
+
/** The RAW request body — the exact bytes received, not a re-encoded copy. */
|
|
85
|
+
payload: string;
|
|
86
|
+
/** The request headers; `webhook-id`, `webhook-timestamp` and `webhook-signature` are read. */
|
|
87
|
+
headers: WebhookHeaders;
|
|
88
|
+
/**
|
|
89
|
+
* The endpoint's secret: a `whsec_…` secret, or the 64-hex secret of an endpoint that
|
|
90
|
+
* moved from the `cbox` scheme (Cbox ID uses it as `whsec_` + base64 of the hex string,
|
|
91
|
+
* which keys the HMAC with the same bytes).
|
|
92
|
+
*/
|
|
93
|
+
secret: string;
|
|
94
|
+
/** Freshness window in seconds. Defaults to 300 (5 minutes). */
|
|
95
|
+
toleranceSeconds?: number;
|
|
96
|
+
/** Injectable clock (unix seconds), for tests. Defaults to `Date.now()`. */
|
|
97
|
+
now?: number;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Verify a delivery from an endpoint on the `standard_webhooks` signature scheme
|
|
101
|
+
* ([Standard Webhooks](https://www.standardwebhooks.com/)): `webhook-signature` carries one or
|
|
102
|
+
* more space-separated `v1,<base64 HMAC-SHA256 of "{webhook-id}.{webhook-timestamp}.{body}">`,
|
|
103
|
+
* and the timestamp must be within the freshness window. Use {@link verifyWebhook} for the
|
|
104
|
+
* default `cbox` scheme (`X-Cbox-Signature`).
|
|
105
|
+
*
|
|
106
|
+
* Returns `true` only when a signature is present, fresh and valid. Never throws.
|
|
107
|
+
*/
|
|
108
|
+
declare function verifyStandardWebhook(options: VerifyStandardWebhookOptions): Promise<boolean>;
|
|
207
109
|
|
|
208
110
|
/** Query parameters as they arrive on your callback route. */
|
|
209
111
|
interface CallbackParams {
|
|
@@ -219,6 +121,16 @@ interface StoredAuthState {
|
|
|
219
121
|
nonce: string;
|
|
220
122
|
/** The `maxAge` this login demanded, if any. See {@link AuthorizationRequest.maxAge}. */
|
|
221
123
|
maxAge?: number;
|
|
124
|
+
/**
|
|
125
|
+
* The organization this sign-in was bound to, if any. See
|
|
126
|
+
* {@link AuthorizationRequest.organization}.
|
|
127
|
+
*
|
|
128
|
+
* Checked, not trusted: a binding nobody verifies is a binding in name only. An
|
|
129
|
+
* instance that predates the `organization` parameter ignores it and returns tokens for
|
|
130
|
+
* whichever organization the session already had — and an app that switched to "Globex"
|
|
131
|
+
* would then show Globex's name over Acme's data.
|
|
132
|
+
*/
|
|
133
|
+
organization?: string;
|
|
222
134
|
/**
|
|
223
135
|
* The scopes THIS authorization asked for, when you overrode the configured set.
|
|
224
136
|
*
|
|
@@ -256,14 +168,22 @@ declare class CboxIdClient {
|
|
|
256
168
|
* `nonce` — persist those (signed, httpOnly cookies are ideal) and hand them back
|
|
257
169
|
* to {@link authenticate} on the callback.
|
|
258
170
|
*/
|
|
259
|
-
createAuthorizationRequest(options?:
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
171
|
+
createAuthorizationRequest(options?: AuthorizationRequestOptions): Promise<AuthorizationRequest>;
|
|
172
|
+
/**
|
|
173
|
+
* Switch the signed-in person to another organization: a new authorization bound to
|
|
174
|
+
* `organizationId`. Persist and redirect exactly as for
|
|
175
|
+
* {@link createAuthorizationRequest} — it is one, with `organization` set.
|
|
176
|
+
*
|
|
177
|
+
* Cbox ID already holds the person's session, so this is normally a redirect there and
|
|
178
|
+
* straight back with no sign-in form. The tokens that come back carry the new `org`,
|
|
179
|
+
* `org_role`, `roles` and `permissions`; replace your session with them rather than
|
|
180
|
+
* patching the old one, because every one of those can differ between organizations.
|
|
181
|
+
*
|
|
182
|
+
* A person who is not (or is no longer) an active member of that organization comes
|
|
183
|
+
* back with `error=access_denied`, which {@link authenticate} throws as an
|
|
184
|
+
* `AuthenticationError` with `error === 'access_denied'`.
|
|
185
|
+
*/
|
|
186
|
+
switchOrganization(organizationId: string, options?: Omit<AuthorizationRequestOptions, 'organization' | 'organizationHint'>): Promise<AuthorizationRequest>;
|
|
267
187
|
/**
|
|
268
188
|
* Complete login on your callback route: verify state, exchange the code with the
|
|
269
189
|
* PKCE verifier, verify the id_token, and return the authenticated user.
|
|
@@ -276,6 +196,45 @@ declare class CboxIdClient {
|
|
|
276
196
|
stored: StoredAuthState;
|
|
277
197
|
redirectUri?: string;
|
|
278
198
|
}): Promise<CboxUser>;
|
|
199
|
+
/**
|
|
200
|
+
* Turn a token response into the verified {@link CboxUser} every flow returns.
|
|
201
|
+
*
|
|
202
|
+
* Shared by the browser flow and the device flow rather than written twice: the checks
|
|
203
|
+
* in here — the UserInfo subject matching the id_token's, the merge that lets UserInfo
|
|
204
|
+
* enrich but never overwrite signed claims — are the ones that decide whether an
|
|
205
|
+
* identity is trustworthy. A second copy is a second place for one of them to be
|
|
206
|
+
* quietly missing, and the flow it was missing from would look exactly as correct.
|
|
207
|
+
*/
|
|
208
|
+
private identityFrom;
|
|
209
|
+
/**
|
|
210
|
+
* Start the device authorization grant (RFC 8628) — the flow for a program with no
|
|
211
|
+
* browser of its own: a CLI, a CI job, a container, a TV.
|
|
212
|
+
*
|
|
213
|
+
* Print `userCode` and `verificationUri`, then call
|
|
214
|
+
* {@link CboxIdClient.pollDeviceToken}. If the machine has a desktop you may also open
|
|
215
|
+
* `verificationUriComplete`, which fills the code in — but print the code anyway: the
|
|
216
|
+
* machine running your program is often not the one the person is looking at.
|
|
217
|
+
*
|
|
218
|
+
* The scopes are bounded by what the app is REGISTERED for. A device request naming one
|
|
219
|
+
* outside that ceiling is refused with `invalid_scope` rather than quietly reduced,
|
|
220
|
+
* because no browser is in front of it to notice a smaller grant.
|
|
221
|
+
*
|
|
222
|
+
* @throws ConfigurationError when the instance advertises no device endpoint.
|
|
223
|
+
*/
|
|
224
|
+
requestDeviceAuthorization(scopes?: string[]): Promise<DeviceAuthorization>;
|
|
225
|
+
/**
|
|
226
|
+
* Poll until the person approves, and return them.
|
|
227
|
+
*
|
|
228
|
+
* Blocks. It honours the server's `interval`, backs off permanently by five seconds on
|
|
229
|
+
* `slow_down` (RFC 8628 §3.5), and stops on the three answers that are final: they
|
|
230
|
+
* declined, the code expired, or tokens arrived. Pass an `AbortSignal` to give up
|
|
231
|
+
* early — a CLI should let Ctrl-C work.
|
|
232
|
+
*
|
|
233
|
+
* @throws AuthenticationError when the person declines or the code expires.
|
|
234
|
+
*/
|
|
235
|
+
pollDeviceToken(authorization: DeviceAuthorization, options?: {
|
|
236
|
+
signal?: AbortSignal;
|
|
237
|
+
}): Promise<CboxUser>;
|
|
279
238
|
/**
|
|
280
239
|
* Exchange a refresh token for a fresh access token (OAuth 2.0 `refresh_token`
|
|
281
240
|
* grant). Cbox ID rotates refresh tokens and detects reuse, so ALWAYS persist the
|
|
@@ -291,6 +250,20 @@ declare class CboxIdClient {
|
|
|
291
250
|
* ID session; `returnTo` is passed so the page can link back to your app.
|
|
292
251
|
*/
|
|
293
252
|
profileUrl(returnTo?: string): string;
|
|
253
|
+
/**
|
|
254
|
+
* The hosted page where a person creates and revokes API keys for your API — Cbox ID's
|
|
255
|
+
* `/account/api-keys`, preselected to this app (or `clientId`). Keys made there are
|
|
256
|
+
* checked with `ApiKeyVerifier` from `@cboxdk/id-js/server`.
|
|
257
|
+
*
|
|
258
|
+
* `returnTo` becomes a link back to your app, honoured only for an origin the app
|
|
259
|
+
* registered. `organization` picks which of the person's organizations the keys act in;
|
|
260
|
+
* omitted, the page uses the one they are in.
|
|
261
|
+
*/
|
|
262
|
+
apiKeysUrl(options?: {
|
|
263
|
+
clientId?: string;
|
|
264
|
+
returnTo?: string;
|
|
265
|
+
organization?: string;
|
|
266
|
+
}): string;
|
|
294
267
|
/**
|
|
295
268
|
* The RP-initiated logout URL, or null when the instance advertises none.
|
|
296
269
|
*
|
|
@@ -365,4 +338,4 @@ declare class CboxIdClient {
|
|
|
365
338
|
private fetchWithTimeout;
|
|
366
339
|
}
|
|
367
340
|
|
|
368
|
-
export {
|
|
341
|
+
export { CboxIdClient as C, type StoreSecretInput as S, VaultClient as V, type WebhookHeaders as W, type CallbackParams as a, type StoredAuthState as b, type VaultLease as c, type VaultSecretRef as d, type VerifyStandardWebhookOptions as e, type VerifyWebhookOptions as f, verifyWebhook as g, verifyStandardWebhook as v };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for every error this SDK throws, so callers can `catch (e) { if (e
|
|
3
|
+
* instanceof CboxIdError) ... }` in one branch.
|
|
4
|
+
*/
|
|
5
|
+
declare class CboxIdError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/** The client is misconfigured (a required option is missing or empty). */
|
|
9
|
+
declare class ConfigurationError extends CboxIdError {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The login `state` did not match what was stored — the callback is forged or
|
|
13
|
+
* stale. Treat as a fresh start, not an error to surface to the user.
|
|
14
|
+
*/
|
|
15
|
+
declare class InvalidStateError extends CboxIdError {
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Login could not be completed: the provider returned an error, the callback was
|
|
19
|
+
* missing a code, or a token / id_token failed verification.
|
|
20
|
+
*
|
|
21
|
+
* `error` carries the RFC 6749 §5.2 code the authorization server sent, when it sent one.
|
|
22
|
+
* It used to be discarded at every back-channel boundary, leaving a single message string
|
|
23
|
+
* for outcomes that need opposite responses: `invalid_grant` on a refresh means the
|
|
24
|
+
* session is over and the person has to sign in again, while `temporarily_unavailable`
|
|
25
|
+
* means try the same token in a moment. A caller reduced to matching on prose either
|
|
26
|
+
* retries what can never succeed, or signs out somebody who did not need to be.
|
|
27
|
+
*/
|
|
28
|
+
declare class AuthenticationError extends CboxIdError {
|
|
29
|
+
/** RFC 6749 §5.2 error code, when the server sent a parseable one. */
|
|
30
|
+
readonly error?: string | undefined;
|
|
31
|
+
/** The server's `error_description`, verbatim. Not end-user copy. */
|
|
32
|
+
readonly errorDescription?: string | undefined;
|
|
33
|
+
/** HTTP status, for the cases where the body says nothing useful. */
|
|
34
|
+
readonly status?: number | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Seconds to wait, off the `Retry-After` header — set only on a 429.
|
|
37
|
+
*
|
|
38
|
+
* The distinction it carries is the one a caller most needs and could least infer:
|
|
39
|
+
* a 429 is the ONLY back-channel failure where the same request will succeed
|
|
40
|
+
* unchanged if you simply wait. Every other one needs a different request, or a new
|
|
41
|
+
* sign-in. Without this the SDK reported "token refresh failed" and a caller with a
|
|
42
|
+
* retry loop hammered a limiter that was already telling it exactly how long to stop.
|
|
43
|
+
*/
|
|
44
|
+
readonly retryAfter?: number | undefined;
|
|
45
|
+
constructor(message: string,
|
|
46
|
+
/** RFC 6749 §5.2 error code, when the server sent a parseable one. */
|
|
47
|
+
error?: string | undefined,
|
|
48
|
+
/** The server's `error_description`, verbatim. Not end-user copy. */
|
|
49
|
+
errorDescription?: string | undefined,
|
|
50
|
+
/** HTTP status, for the cases where the body says nothing useful. */
|
|
51
|
+
status?: number | undefined,
|
|
52
|
+
/**
|
|
53
|
+
* Seconds to wait, off the `Retry-After` header — set only on a 429.
|
|
54
|
+
*
|
|
55
|
+
* The distinction it carries is the one a caller most needs and could least infer:
|
|
56
|
+
* a 429 is the ONLY back-channel failure where the same request will succeed
|
|
57
|
+
* unchanged if you simply wait. Every other one needs a different request, or a new
|
|
58
|
+
* sign-in. Without this the SDK reported "token refresh failed" and a caller with a
|
|
59
|
+
* retry loop hammered a limiter that was already telling it exactly how long to stop.
|
|
60
|
+
*/
|
|
61
|
+
retryAfter?: number | undefined);
|
|
62
|
+
/** Whether waiting `retryAfter` seconds and repeating the same request is worth it. */
|
|
63
|
+
get isRateLimited(): boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The Frontend API refused, or could not be reached.
|
|
67
|
+
*
|
|
68
|
+
* Carries a `code` because the four ways this goes wrong need four different responses
|
|
69
|
+
* from the caller, and telling them apart from a message string is the kind of thing
|
|
70
|
+
* that works until somebody rewords the message:
|
|
71
|
+
*
|
|
72
|
+
* - `origin_not_allowed` — the overwhelmingly likely cause of a refusal, and a
|
|
73
|
+
* configuration problem the developer fixes once in the console.
|
|
74
|
+
* - `rate_limited` — back off; `retryAfter` says for how long, when the server said.
|
|
75
|
+
* - `unavailable` — the network, or a 5xx. Transient by assumption; already retried.
|
|
76
|
+
* - `malformed` — a 200 whose body is not the document we expect, which means something
|
|
77
|
+
* between the page and us is rewriting responses (a proxy, an extension, a captive
|
|
78
|
+
* portal). Worth distinguishing, because retrying it never helps.
|
|
79
|
+
*/
|
|
80
|
+
declare class FrontendApiError extends CboxIdError {
|
|
81
|
+
readonly code: 'origin_not_allowed' | 'rate_limited' | 'unavailable' | 'malformed';
|
|
82
|
+
readonly status?: number | undefined;
|
|
83
|
+
readonly retryAfter?: number | undefined;
|
|
84
|
+
constructor(message: string, code: 'origin_not_allowed' | 'rate_limited' | 'unavailable' | 'malformed', status?: number | undefined, retryAfter?: number | undefined);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { AuthenticationError as A, CboxIdError as C, FrontendApiError as F, InvalidStateError as I, ConfigurationError as a };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for every error this SDK throws, so callers can `catch (e) { if (e
|
|
3
|
+
* instanceof CboxIdError) ... }` in one branch.
|
|
4
|
+
*/
|
|
5
|
+
declare class CboxIdError extends Error {
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/** The client is misconfigured (a required option is missing or empty). */
|
|
9
|
+
declare class ConfigurationError extends CboxIdError {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The login `state` did not match what was stored — the callback is forged or
|
|
13
|
+
* stale. Treat as a fresh start, not an error to surface to the user.
|
|
14
|
+
*/
|
|
15
|
+
declare class InvalidStateError extends CboxIdError {
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Login could not be completed: the provider returned an error, the callback was
|
|
19
|
+
* missing a code, or a token / id_token failed verification.
|
|
20
|
+
*
|
|
21
|
+
* `error` carries the RFC 6749 §5.2 code the authorization server sent, when it sent one.
|
|
22
|
+
* It used to be discarded at every back-channel boundary, leaving a single message string
|
|
23
|
+
* for outcomes that need opposite responses: `invalid_grant` on a refresh means the
|
|
24
|
+
* session is over and the person has to sign in again, while `temporarily_unavailable`
|
|
25
|
+
* means try the same token in a moment. A caller reduced to matching on prose either
|
|
26
|
+
* retries what can never succeed, or signs out somebody who did not need to be.
|
|
27
|
+
*/
|
|
28
|
+
declare class AuthenticationError extends CboxIdError {
|
|
29
|
+
/** RFC 6749 §5.2 error code, when the server sent a parseable one. */
|
|
30
|
+
readonly error?: string | undefined;
|
|
31
|
+
/** The server's `error_description`, verbatim. Not end-user copy. */
|
|
32
|
+
readonly errorDescription?: string | undefined;
|
|
33
|
+
/** HTTP status, for the cases where the body says nothing useful. */
|
|
34
|
+
readonly status?: number | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Seconds to wait, off the `Retry-After` header — set only on a 429.
|
|
37
|
+
*
|
|
38
|
+
* The distinction it carries is the one a caller most needs and could least infer:
|
|
39
|
+
* a 429 is the ONLY back-channel failure where the same request will succeed
|
|
40
|
+
* unchanged if you simply wait. Every other one needs a different request, or a new
|
|
41
|
+
* sign-in. Without this the SDK reported "token refresh failed" and a caller with a
|
|
42
|
+
* retry loop hammered a limiter that was already telling it exactly how long to stop.
|
|
43
|
+
*/
|
|
44
|
+
readonly retryAfter?: number | undefined;
|
|
45
|
+
constructor(message: string,
|
|
46
|
+
/** RFC 6749 §5.2 error code, when the server sent a parseable one. */
|
|
47
|
+
error?: string | undefined,
|
|
48
|
+
/** The server's `error_description`, verbatim. Not end-user copy. */
|
|
49
|
+
errorDescription?: string | undefined,
|
|
50
|
+
/** HTTP status, for the cases where the body says nothing useful. */
|
|
51
|
+
status?: number | undefined,
|
|
52
|
+
/**
|
|
53
|
+
* Seconds to wait, off the `Retry-After` header — set only on a 429.
|
|
54
|
+
*
|
|
55
|
+
* The distinction it carries is the one a caller most needs and could least infer:
|
|
56
|
+
* a 429 is the ONLY back-channel failure where the same request will succeed
|
|
57
|
+
* unchanged if you simply wait. Every other one needs a different request, or a new
|
|
58
|
+
* sign-in. Without this the SDK reported "token refresh failed" and a caller with a
|
|
59
|
+
* retry loop hammered a limiter that was already telling it exactly how long to stop.
|
|
60
|
+
*/
|
|
61
|
+
retryAfter?: number | undefined);
|
|
62
|
+
/** Whether waiting `retryAfter` seconds and repeating the same request is worth it. */
|
|
63
|
+
get isRateLimited(): boolean;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The Frontend API refused, or could not be reached.
|
|
67
|
+
*
|
|
68
|
+
* Carries a `code` because the four ways this goes wrong need four different responses
|
|
69
|
+
* from the caller, and telling them apart from a message string is the kind of thing
|
|
70
|
+
* that works until somebody rewords the message:
|
|
71
|
+
*
|
|
72
|
+
* - `origin_not_allowed` — the overwhelmingly likely cause of a refusal, and a
|
|
73
|
+
* configuration problem the developer fixes once in the console.
|
|
74
|
+
* - `rate_limited` — back off; `retryAfter` says for how long, when the server said.
|
|
75
|
+
* - `unavailable` — the network, or a 5xx. Transient by assumption; already retried.
|
|
76
|
+
* - `malformed` — a 200 whose body is not the document we expect, which means something
|
|
77
|
+
* between the page and us is rewriting responses (a proxy, an extension, a captive
|
|
78
|
+
* portal). Worth distinguishing, because retrying it never helps.
|
|
79
|
+
*/
|
|
80
|
+
declare class FrontendApiError extends CboxIdError {
|
|
81
|
+
readonly code: 'origin_not_allowed' | 'rate_limited' | 'unavailable' | 'malformed';
|
|
82
|
+
readonly status?: number | undefined;
|
|
83
|
+
readonly retryAfter?: number | undefined;
|
|
84
|
+
constructor(message: string, code: 'origin_not_allowed' | 'rate_limited' | 'unavailable' | 'malformed', status?: number | undefined, retryAfter?: number | undefined);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { AuthenticationError as A, CboxIdError as C, FrontendApiError as F, InvalidStateError as I, ConfigurationError as a };
|