@cboxdk/id-js 0.15.1 → 0.17.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 +237 -2
- package/dist/chunk-ASOQN47M.js +81 -0
- package/dist/chunk-ASOQN47M.js.map +1 -0
- package/dist/{chunk-3V6OKRWF.js → chunk-G3CD7X4U.js} +321 -90
- package/dist/chunk-G3CD7X4U.js.map +1 -0
- package/dist/chunk-WYTGLCMF.js +154 -0
- package/dist/chunk-WYTGLCMF.js.map +1 -0
- package/dist/{client-CecDIu_N.d.cts → client-CEXddiCR.d.cts} +81 -136
- package/dist/{client-CecDIu_N.d.ts → client-CdwdigzG.d.ts} +81 -136
- package/dist/index.cjs +384 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -4
- package/dist/index.d.ts +39 -4
- package/dist/index.js +63 -25
- package/dist/index.js.map +1 -1
- 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 +41 -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 +4 -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 +6 -1
- package/dist/chunk-3V6OKRWF.js.map +0 -1
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { O as OrganizationRole } from './types-BYZldock.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A customer API key Cbox ID vouches for: live, bound to YOUR app, and held by an active
|
|
5
|
+
* member of `org`.
|
|
6
|
+
*
|
|
7
|
+
* The field names are the endpoint's own, so the claim helpers read it like a token —
|
|
8
|
+
* `hasPermission(answer, 'invoices:create')`, `organization(answer)?.role`. (A type
|
|
9
|
+
* alias rather than an interface for that reason: only an alias is assignable to the
|
|
10
|
+
* helpers' record type.)
|
|
11
|
+
*/
|
|
12
|
+
type ActiveApiKey = {
|
|
13
|
+
active: true;
|
|
14
|
+
/** The key's id — log this, never the key. */
|
|
15
|
+
key_id: string;
|
|
16
|
+
/** The person who holds the key (their subject id). */
|
|
17
|
+
sub: string;
|
|
18
|
+
/** The organization the key acts in. */
|
|
19
|
+
org: string;
|
|
20
|
+
/** The holder's membership tier in `org`; null for a tier this SDK does not know. */
|
|
21
|
+
org_role: OrganizationRole | null;
|
|
22
|
+
/**
|
|
23
|
+
* What the key may do, already re-capped by Cbox ID: the key's own list intersected
|
|
24
|
+
* with what the holder holds for your app right now. A demoted holder's key loses the
|
|
25
|
+
* permission on the next verification, not at the next reissue.
|
|
26
|
+
*/
|
|
27
|
+
permissions: string[];
|
|
28
|
+
/** Your app's client id — always, or the answer is refused. */
|
|
29
|
+
client_id: string;
|
|
30
|
+
/** ISO 8601 UTC expiry, or null for a key that does not expire. */
|
|
31
|
+
expires_at: string | null;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Every refusal: unknown, malformed, revoked, expired, another app's key, a holder who
|
|
35
|
+
* left. Cbox ID never says which, so the endpoint cannot be used to probe keys — and
|
|
36
|
+
* neither does this.
|
|
37
|
+
*/
|
|
38
|
+
interface InactiveApiKey {
|
|
39
|
+
active: false;
|
|
40
|
+
}
|
|
41
|
+
/** What {@link ApiKeyVerifier.verifyApiKey} returns. Narrow on `active`. */
|
|
42
|
+
type ApiKeyVerification = ActiveApiKey | InactiveApiKey;
|
|
43
|
+
/** Configuration for an {@link ApiKeyVerifier}. */
|
|
44
|
+
interface ApiKeyVerifierConfig {
|
|
45
|
+
/** Base URL (issuer) of the Cbox ID instance. */
|
|
46
|
+
issuer: string;
|
|
47
|
+
/** Your app's OAuth client id — the app the keys were issued for. */
|
|
48
|
+
clientId: string;
|
|
49
|
+
/** Your app's client secret. Verification is a confidential-client call. */
|
|
50
|
+
clientSecret: string;
|
|
51
|
+
/** Timeout (ms) for the verification request. Defaults to `10000`. */
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
/**
|
|
54
|
+
* Cache an ACTIVE answer for this long (ms), so a burst of requests with one key costs
|
|
55
|
+
* one round-trip. Off (`0`) by default and at most {@link MAX_API_KEY_CACHE_TTL_MS}:
|
|
56
|
+
* while an answer is cached, a revoked key keeps working, and a demoted holder keeps
|
|
57
|
+
* the permissions they lost. Never cached past the key's `expires_at`. Refusals are
|
|
58
|
+
* never cached, so a key issued a moment ago works on its first request.
|
|
59
|
+
*/
|
|
60
|
+
cacheTtlMs?: number;
|
|
61
|
+
}
|
|
62
|
+
/** The longest {@link ApiKeyVerifierConfig.cacheTtlMs} allowed: one minute. */
|
|
63
|
+
declare const MAX_API_KEY_CACHE_TTL_MS = 60000;
|
|
64
|
+
/**
|
|
65
|
+
* Verifies customer API keys presented to your API: `POST {issuer}/oauth/api-keys/verify`,
|
|
66
|
+
* authenticated with your app's own client credentials.
|
|
67
|
+
*
|
|
68
|
+
* SERVER-SIDE ONLY. It holds your client secret, so it lives in the
|
|
69
|
+
* `@cboxdk/id-js/server` entry and the Next.js adapter, never in the main entry that a
|
|
70
|
+
* browser bundle pulls in — and it refuses to be constructed in a browser at all.
|
|
71
|
+
*
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { ApiKeyVerifier } from '@cboxdk/id-js/server';
|
|
74
|
+
* import { hasPermission } from '@cboxdk/id-js';
|
|
75
|
+
*
|
|
76
|
+
* const keys = new ApiKeyVerifier({ issuer, clientId, clientSecret, cacheTtlMs: 10_000 });
|
|
77
|
+
*
|
|
78
|
+
* const answer = await keys.verifyApiKey(request.headers.get('x-api-key') ?? '');
|
|
79
|
+
* if (!answer.active) return unauthorized();
|
|
80
|
+
* if (!hasPermission(answer, 'invoices:create')) return forbidden();
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
declare class ApiKeyVerifier {
|
|
84
|
+
private readonly config;
|
|
85
|
+
private readonly endpoint;
|
|
86
|
+
private readonly timeoutMs;
|
|
87
|
+
private readonly cacheTtlMs;
|
|
88
|
+
private readonly cache;
|
|
89
|
+
constructor(config: ApiKeyVerifierConfig);
|
|
90
|
+
/**
|
|
91
|
+
* Ask Cbox ID whether `key` is good for this app, and what it may do.
|
|
92
|
+
*
|
|
93
|
+
* Resolves `{ active: false }` for every kind of bad key, without a request for an empty
|
|
94
|
+
* one. Throws `AuthenticationError` when the call itself fails (wrong client
|
|
95
|
+
* credentials, an unreachable instance) or when the answer cannot be trusted — one that
|
|
96
|
+
* names another app's `client_id`, or does not have the promised shape. Both mean "do
|
|
97
|
+
* not let this request in"; the difference is that a throw is something to look at.
|
|
98
|
+
*/
|
|
99
|
+
verifyApiKey(key: string): Promise<ApiKeyVerification>;
|
|
100
|
+
private request;
|
|
101
|
+
private parse;
|
|
102
|
+
private remember;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { type ActiveApiKey, type ApiKeyVerification, ApiKeyVerifier, type ApiKeyVerifierConfig, type InactiveApiKey, MAX_API_KEY_CACHE_TTL_MS };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"server.js"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The membership tier a person holds in the organization a token is bound to — the
|
|
3
|
+
* `org_role` claim. Coarse on purpose: it says who may administer the organization
|
|
4
|
+
* itself (invite, bill, delete). What they may do inside YOUR app is `roles` /
|
|
5
|
+
* `permissions`, which your app declares and Cbox ID assigns.
|
|
6
|
+
*/
|
|
7
|
+
type OrganizationRole = 'owner' | 'admin' | 'developer' | 'member' | 'viewer';
|
|
8
|
+
/** The organization a token is bound to: the `org`, `org_name` and `org_role` claims. */
|
|
9
|
+
interface CboxActiveOrganization {
|
|
10
|
+
/** The stable organization id (`org`). */
|
|
11
|
+
id: string;
|
|
12
|
+
/** Its display name (`org_name`), when the instance sent one. */
|
|
13
|
+
name: string | null;
|
|
14
|
+
/**
|
|
15
|
+
* The person's membership tier in it (`org_role`). Null when the claim is absent, or
|
|
16
|
+
* carries a tier this SDK version does not know — an unrecognised tier is never
|
|
17
|
+
* guessed upward into one that grants something.
|
|
18
|
+
*/
|
|
19
|
+
role: OrganizationRole | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Who is actually driving a delegated session — the RFC 8693 §4.1 `act` claim. Cbox ID
|
|
23
|
+
* sets it on the tokens of a SUPPORT SESSION: a staff member acting as one of your users,
|
|
24
|
+
* with a stated reason, for at most an hour, with no refresh token.
|
|
25
|
+
*
|
|
26
|
+
* `sub` is the actor's subject id. It is null when an `act` claim is present but not in
|
|
27
|
+
* the shape RFC 8693 describes — the token is still acted, and saying so matters more
|
|
28
|
+
* than knowing by whom (see {@link isSupportSession}).
|
|
29
|
+
*/
|
|
30
|
+
interface CboxActor {
|
|
31
|
+
sub: string | null;
|
|
32
|
+
/** The prior actor, when delegation was chained (RFC 8693 §4.1 nested `act`). */
|
|
33
|
+
actor: CboxActor | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Anything the helpers below can read claims from: a {@link CboxUser} from sign-in, or a
|
|
37
|
+
* claim set you verified yourself — an access token's payload on a resource server, say.
|
|
38
|
+
*/
|
|
39
|
+
type ClaimSource = CboxUser | Readonly<Record<string, unknown>>;
|
|
40
|
+
/**
|
|
41
|
+
* The organization this session is bound to, or null when it is bound to none.
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* const org = organization(user);
|
|
45
|
+
* if (org?.role === 'owner') showBilling();
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
declare function organization(source: ClaimSource): CboxActiveOrganization | null;
|
|
49
|
+
/**
|
|
50
|
+
* The actor behind a support session (`act`), or null for an ordinary session in which
|
|
51
|
+
* the person is acting as themselves.
|
|
52
|
+
*/
|
|
53
|
+
declare function actor(source: ClaimSource): CboxActor | null;
|
|
54
|
+
/**
|
|
55
|
+
* Whether somebody other than the signed-in person is driving this session — a staff
|
|
56
|
+
* member in a support session (the token carries `act`).
|
|
57
|
+
*
|
|
58
|
+
* FAIL-CLOSED. Any `act` claim at all counts, including one whose shape this SDK cannot
|
|
59
|
+
* read: the check exists so an app can show a banner and refuse the things a helper
|
|
60
|
+
* should never do on somebody's behalf (change their password, move their money), and a
|
|
61
|
+
* malformed claim is not evidence that nobody else is at the keyboard.
|
|
62
|
+
*/
|
|
63
|
+
declare function isSupportSession(source: ClaimSource): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* The Cbox ID sign-in session this token came from — the ID Token's `sid` claim — or null
|
|
66
|
+
* when the instance sent none.
|
|
67
|
+
*
|
|
68
|
+
* Store it with your own session: an OIDC Back-Channel Logout token names the session it
|
|
69
|
+
* ends by this value, and matching on it is how you end the right one (rather than every
|
|
70
|
+
* session the person has) when they sign out of Cbox ID elsewhere.
|
|
71
|
+
*/
|
|
72
|
+
declare function sessionId(source: ClaimSource): string | null;
|
|
73
|
+
/** The app roles this session holds — the `roles` claim; empty when there are none. */
|
|
74
|
+
declare function roles(source: ClaimSource): string[];
|
|
75
|
+
/**
|
|
76
|
+
* The permissions this session holds — the `permissions` claim, already expanded from
|
|
77
|
+
* `roles` by Cbox ID; empty when there are none.
|
|
78
|
+
*/
|
|
79
|
+
declare function permissions(source: ClaimSource): string[];
|
|
80
|
+
/** Whether the session holds `role`. Exact match; no wildcards. */
|
|
81
|
+
declare function hasRole(source: ClaimSource, role: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Whether the session holds `permission` (`feature:action`). Exact match; no wildcards
|
|
84
|
+
* — a claim of `invoices:*` does not grant `invoices:delete`, because nothing on the
|
|
85
|
+
* issuing side ever mints one.
|
|
86
|
+
*/
|
|
87
|
+
declare function hasPermission(source: ClaimSource, permission: string): boolean;
|
|
88
|
+
|
|
89
|
+
/** Configuration for a {@link CboxIdClient}. */
|
|
90
|
+
interface CboxIdConfig {
|
|
91
|
+
/**
|
|
92
|
+
* Base URL (issuer) of the Cbox ID instance, e.g. `https://id.acme.com`. Every
|
|
93
|
+
* endpoint is discovered from `{issuer}/.well-known/openid-configuration`, so this
|
|
94
|
+
* is usually the only endpoint you configure.
|
|
95
|
+
*/
|
|
96
|
+
issuer: string;
|
|
97
|
+
/** Your registered OAuth client id. */
|
|
98
|
+
clientId: string;
|
|
99
|
+
/**
|
|
100
|
+
* Your client secret. Required for confidential (server-side) apps, machine
|
|
101
|
+
* tokens and introspection. Omit for public clients (SPA/native) that only do
|
|
102
|
+
* PKCE login.
|
|
103
|
+
*/
|
|
104
|
+
clientSecret?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Your callback URL — must exactly match one registered on the client.
|
|
107
|
+
*
|
|
108
|
+
* OPTIONAL, because not every flow has one. The device grant (RFC 8628) exists
|
|
109
|
+
* precisely for programs with no browser to be returned to, so a CLI has none to give;
|
|
110
|
+
* requiring it here made every CLI invent `'http://localhost'` and note that it is
|
|
111
|
+
* unused. It is required by {@link CboxIdClient.createAuthorizationRequest} and
|
|
112
|
+
* {@link CboxIdClient.authenticate}, which is where its absence actually breaks
|
|
113
|
+
* something.
|
|
114
|
+
*/
|
|
115
|
+
redirectUri?: string;
|
|
116
|
+
/** Scopes requested at login. Defaults to `['openid', 'profile', 'email']`. */
|
|
117
|
+
scopes?: string[];
|
|
118
|
+
/**
|
|
119
|
+
* Path of the instance's hosted account page that {@link CboxIdClient.profileUrl}
|
|
120
|
+
* points at. Defaults to `/account`, the person's own account area. (`/settings` is
|
|
121
|
+
* the organization's settings page, for its administrators.)
|
|
122
|
+
*/
|
|
123
|
+
accountPath?: string;
|
|
124
|
+
/** Timeout (ms) for back-channel HTTP calls. Defaults to `10000`. */
|
|
125
|
+
timeoutMs?: number;
|
|
126
|
+
/** How long (ms) the discovery document is cached. Defaults to `3600000` (1h). */
|
|
127
|
+
cacheTtlMs?: number;
|
|
128
|
+
/**
|
|
129
|
+
* Leeway (seconds) when checking the id_token's `auth_time` against the `maxAge` you
|
|
130
|
+
* requested at login. Defaults to `60`.
|
|
131
|
+
*
|
|
132
|
+
* Some slack is required, not optional: `maxAge` bounds the age of the
|
|
133
|
+
* AUTHENTICATION, but `auth_time` is read after a browser redirect and a token
|
|
134
|
+
* exchange, so even a just-completed re-authentication is already several seconds
|
|
135
|
+
* old — and the RP's clock and the instance's need not agree. Sixty seconds absorbs
|
|
136
|
+
* that while still catching what this check exists for: a session hours or days old
|
|
137
|
+
* being passed off as fresh.
|
|
138
|
+
*/
|
|
139
|
+
authTimeToleranceSeconds?: number;
|
|
140
|
+
}
|
|
141
|
+
/** The OIDC discovery document fields this SDK uses. */
|
|
142
|
+
interface DiscoveryDocument {
|
|
143
|
+
issuer: string;
|
|
144
|
+
authorization_endpoint: string;
|
|
145
|
+
token_endpoint: string;
|
|
146
|
+
jwks_uri: string;
|
|
147
|
+
userinfo_endpoint?: string;
|
|
148
|
+
introspection_endpoint?: string;
|
|
149
|
+
revocation_endpoint?: string;
|
|
150
|
+
end_session_endpoint?: string;
|
|
151
|
+
device_authorization_endpoint?: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* A pending device authorization (RFC 8628) — what a CLI shows the person while it waits.
|
|
155
|
+
*/
|
|
156
|
+
interface DeviceAuthorization {
|
|
157
|
+
/** The secret this program polls with. Never show it to the person. */
|
|
158
|
+
deviceCode: string;
|
|
159
|
+
/** The short code the person types on the verification page. */
|
|
160
|
+
userCode: string;
|
|
161
|
+
/** Where the person goes to approve. Print this. */
|
|
162
|
+
verificationUri: string;
|
|
163
|
+
/** The same page with the code filled in — for a clickable link or a QR code. */
|
|
164
|
+
verificationUriComplete: string | null;
|
|
165
|
+
/** Seconds until the code stops being valid. */
|
|
166
|
+
expiresIn: number;
|
|
167
|
+
/** The minimum seconds between polls. Never poll faster; the server will say so. */
|
|
168
|
+
interval: number;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* RFC 7009 `token_type_hint`: which token store the server should search first.
|
|
172
|
+
* Only a hint — the server must still find the token if the hint is wrong.
|
|
173
|
+
*/
|
|
174
|
+
type TokenTypeHint = 'access_token' | 'refresh_token';
|
|
175
|
+
/**
|
|
176
|
+
* An OIDC `prompt` value Cbox ID understands. The first four are OIDC Core §3.1.2.1; the
|
|
177
|
+
* last two are Cbox ID's organization steps:
|
|
178
|
+
*
|
|
179
|
+
* - `select_organization` — always show the hosted organization picker, even to someone
|
|
180
|
+
* in a single organization.
|
|
181
|
+
* - `create_organization` — the hosted "create a team" step: the person creates an
|
|
182
|
+
* organization, becomes its owner, and the sign-in continues bound to it.
|
|
183
|
+
*/
|
|
184
|
+
type AuthorizationPrompt = 'none' | 'login' | 'consent' | 'select_account' | 'select_organization' | 'create_organization';
|
|
185
|
+
/** Options for {@link CboxIdClient.createAuthorizationRequest}. */
|
|
186
|
+
interface AuthorizationRequestOptions {
|
|
187
|
+
/** Scopes for this sign-in; defaults to the configured set. */
|
|
188
|
+
scopes?: string[];
|
|
189
|
+
/** Overrides the configured callback for this sign-in. */
|
|
190
|
+
redirectUri?: string;
|
|
191
|
+
/** Your own `state`; a random one is generated when omitted. */
|
|
192
|
+
state?: string;
|
|
193
|
+
/**
|
|
194
|
+
* One prompt, or several (sent space-separated). `none` cannot be combined with
|
|
195
|
+
* anything else — OIDC Core §3.1.2.1 makes that an error at the server, so it is
|
|
196
|
+
* refused here, where the stack trace still points at your code.
|
|
197
|
+
*/
|
|
198
|
+
prompt?: AuthorizationPrompt | readonly AuthorizationPrompt[];
|
|
199
|
+
/** Prefills the email on the sign-in page (`login_hint`). */
|
|
200
|
+
loginHint?: string;
|
|
201
|
+
/** Demand an authentication no older than this many seconds (`max_age`). */
|
|
202
|
+
maxAge?: number;
|
|
203
|
+
/**
|
|
204
|
+
* Bind this sign-in to one organization (`organization`). The person must hold an
|
|
205
|
+
* active membership in it; if they do not, the callback carries
|
|
206
|
+
* `error=access_denied` and {@link CboxIdClient.authenticate} throws an
|
|
207
|
+
* `AuthenticationError` whose `error` is `'access_denied'`.
|
|
208
|
+
*
|
|
209
|
+
* This is how an app switches organization: a new authorization bound to the other
|
|
210
|
+
* one. See {@link CboxIdClient.switchOrganization}.
|
|
211
|
+
*/
|
|
212
|
+
organization?: string;
|
|
213
|
+
/**
|
|
214
|
+
* Preselect an organization in the hosted picker (`organization_hint`) without binding
|
|
215
|
+
* to it — the person can still choose another. Pair it with
|
|
216
|
+
* `prompt: 'select_organization'` to always show the picker with your guess on top.
|
|
217
|
+
*/
|
|
218
|
+
organizationHint?: string;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* The values {@link CboxIdClient.createAuthorizationRequest} returns. Persist
|
|
222
|
+
* `state`, `codeVerifier` and `nonce` (e.g. in signed, httpOnly cookies) and hand
|
|
223
|
+
* them back to {@link CboxIdClient.authenticate} on the callback.
|
|
224
|
+
*/
|
|
225
|
+
interface AuthorizationRequest {
|
|
226
|
+
/** The URL to redirect the user to. */
|
|
227
|
+
url: string;
|
|
228
|
+
state: string;
|
|
229
|
+
codeVerifier: string;
|
|
230
|
+
nonce: string;
|
|
231
|
+
/**
|
|
232
|
+
* Echoed back when you passed `maxAge`. Persist it with the rest and hand it to
|
|
233
|
+
* {@link CboxIdClient.authenticate}, which then verifies the id_token's `auth_time`
|
|
234
|
+
* against it — a step-up nobody checks is not a step-up.
|
|
235
|
+
*/
|
|
236
|
+
maxAge?: number;
|
|
237
|
+
/**
|
|
238
|
+
* Echoed back when you passed `organization`. Persist it and hand it to
|
|
239
|
+
* {@link CboxIdClient.authenticate}, which then refuses tokens bound to any other
|
|
240
|
+
* organization — see {@link StoredAuthState.organization}.
|
|
241
|
+
*/
|
|
242
|
+
organization?: string;
|
|
243
|
+
}
|
|
244
|
+
/** The raw token-endpoint response. */
|
|
245
|
+
interface TokenResponse {
|
|
246
|
+
access_token: string;
|
|
247
|
+
token_type?: string;
|
|
248
|
+
id_token?: string;
|
|
249
|
+
refresh_token?: string;
|
|
250
|
+
expires_in?: number;
|
|
251
|
+
scope?: string;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The tokens returned by {@link CboxIdClient.refresh}. Cbox ID ROTATES refresh
|
|
255
|
+
* tokens and detects reuse, so `refreshToken` is a NEW value — store it and discard
|
|
256
|
+
* the one you presented; replaying a rotated token revokes the whole family.
|
|
257
|
+
*/
|
|
258
|
+
interface RefreshedTokens {
|
|
259
|
+
accessToken: string;
|
|
260
|
+
refreshToken: string;
|
|
261
|
+
idToken: string | null;
|
|
262
|
+
expiresIn: number;
|
|
263
|
+
scope: string | null;
|
|
264
|
+
}
|
|
265
|
+
/** One organization a user belongs to, from the `organizations` claim when present. */
|
|
266
|
+
interface CboxOrganization {
|
|
267
|
+
id: string;
|
|
268
|
+
name: string;
|
|
269
|
+
/** The member's role in this organization, when the claim carries it. */
|
|
270
|
+
role?: string | null;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* The authenticated Cbox ID user. `id` is the stable opaque subject (`sub`) you key
|
|
274
|
+
* your local account on. `claims` is the full verified id_token + userinfo claim
|
|
275
|
+
* set; the named fields are conveniences over it.
|
|
276
|
+
*/
|
|
277
|
+
interface CboxUser {
|
|
278
|
+
id: string;
|
|
279
|
+
email: string | null;
|
|
280
|
+
name: string | null;
|
|
281
|
+
/** The active organization's id (`org` claim). Same as `organization?.id`. */
|
|
282
|
+
organizationId: string | null;
|
|
283
|
+
/**
|
|
284
|
+
* The organization this session is bound to — id, name and the person's membership
|
|
285
|
+
* tier in it (`org`, `org_name`, `org_role`) — or null when it is bound to none.
|
|
286
|
+
*/
|
|
287
|
+
organization: CboxActiveOrganization | null;
|
|
288
|
+
/** App roles held in this session (`roles` claim); empty when there are none. */
|
|
289
|
+
roles: string[];
|
|
290
|
+
/** Permissions held in this session (`permissions` claim); empty when there are none. */
|
|
291
|
+
permissions: string[];
|
|
292
|
+
/**
|
|
293
|
+
* Set when this is a SUPPORT SESSION — a staff member acting as this person (the RFC
|
|
294
|
+
* 8693 `act` claim). Null for an ordinary sign-in. Show it: see `isSupportSession()`.
|
|
295
|
+
*/
|
|
296
|
+
actor: CboxActor | null;
|
|
297
|
+
/**
|
|
298
|
+
* The Cbox ID sign-in session (the ID Token's `sid`), or null when none was sent. Keep
|
|
299
|
+
* it with your session to match a back-channel logout to it. See `sessionId()`.
|
|
300
|
+
*/
|
|
301
|
+
sessionId: string | null;
|
|
302
|
+
/**
|
|
303
|
+
* The organizations this user belongs to — the UserInfo `organizations` claim, which
|
|
304
|
+
* Cbox ID only sends when you requested the `organizations` scope (it lists every
|
|
305
|
+
* organization the person is in, so a plain `profile` sign-in does not get it).
|
|
306
|
+
* Undefined when the claim is absent. Pass straight to `<OrganizationSwitcher>`.
|
|
307
|
+
*/
|
|
308
|
+
organizations?: CboxOrganization[];
|
|
309
|
+
claims: Record<string, unknown>;
|
|
310
|
+
accessToken: string;
|
|
311
|
+
refreshToken: string | null;
|
|
312
|
+
idToken: string | null;
|
|
313
|
+
expiresIn: number;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export { type AuthorizationRequestOptions as A, type CboxUser as C, type DeviceAuthorization as D, type OrganizationRole as O, type RefreshedTokens as R, type TokenTypeHint as T, type CboxIdConfig as a, type AuthorizationRequest as b, type AuthorizationPrompt as c, type CboxActiveOrganization as d, type CboxActor as e, type CboxOrganization as f, type ClaimSource as g, type DiscoveryDocument as h, type TokenResponse as i, actor as j, hasPermission as k, hasRole as l, isSupportSession as m, organization as o, permissions as p, roles as r, sessionId as s };
|