@authyon/auth 0.2.0-beta.0 → 0.2.0-beta.2
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/LICENSE +21 -0
- package/README.md +177 -14
- package/dist/ability-g6nBpOQM.d.cts +617 -0
- package/dist/ability-g6nBpOQM.d.ts +617 -0
- package/dist/chunk-EHZEUM47.js +323 -0
- package/dist/index.cjs +748 -60
- package/dist/index.d.cts +57 -466
- package/dist/index.d.ts +57 -466
- package/dist/index.js +431 -58
- package/dist/react/index.cjs +428 -0
- package/dist/react/index.d.cts +47 -0
- package/dist/react/index.d.ts +47 -0
- package/dist/react/index.js +120 -0
- package/package.json +71 -37
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
interface HttpAdapterRequest {
|
|
2
|
+
url: string;
|
|
3
|
+
method: string;
|
|
4
|
+
headers: Record<string, string>;
|
|
5
|
+
body?: BodyInit | null;
|
|
6
|
+
signal: AbortSignal;
|
|
7
|
+
}
|
|
8
|
+
/** Transport contract accepted by both Authyon clients. */
|
|
9
|
+
interface HttpAdapter {
|
|
10
|
+
request(request: HttpAdapterRequest): Promise<Response>;
|
|
11
|
+
}
|
|
12
|
+
type HttpLogEvent = {
|
|
13
|
+
type: "request";
|
|
14
|
+
method: string;
|
|
15
|
+
url: string;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
} | {
|
|
18
|
+
type: "response";
|
|
19
|
+
method: string;
|
|
20
|
+
url: string;
|
|
21
|
+
status: number;
|
|
22
|
+
durationMs: number;
|
|
23
|
+
requestId?: string;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
} | {
|
|
26
|
+
type: "error";
|
|
27
|
+
method: string;
|
|
28
|
+
url: string;
|
|
29
|
+
errorName: string;
|
|
30
|
+
durationMs: number;
|
|
31
|
+
timestamp: number;
|
|
32
|
+
};
|
|
33
|
+
/** Receives sanitized HTTP lifecycle events. Headers, bodies and query values are never exposed. */
|
|
34
|
+
type HttpLogger = (event: HttpLogEvent) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Mutable logging configuration. Change `enabled` at runtime to enable or disable logging
|
|
37
|
+
* without recreating the Authyon client.
|
|
38
|
+
*/
|
|
39
|
+
interface HttpLoggerOptions {
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
logger?: HttpLogger;
|
|
42
|
+
}
|
|
43
|
+
/** Default adapter backed by the platform's Fetch API. */
|
|
44
|
+
declare class FetchHttpAdapter implements HttpAdapter {
|
|
45
|
+
private readonly fetchImpl;
|
|
46
|
+
constructor(fetchImpl?: typeof fetch);
|
|
47
|
+
request(request: HttpAdapterRequest): Promise<Response>;
|
|
48
|
+
}
|
|
49
|
+
/** Adds safe, configurable lifecycle logging to any HTTP adapter. */
|
|
50
|
+
declare class LoggingHttpAdapter implements HttpAdapter {
|
|
51
|
+
private readonly adapter;
|
|
52
|
+
private readonly options;
|
|
53
|
+
constructor(adapter: HttpAdapter, options: HttpLoggerOptions);
|
|
54
|
+
request(request: HttpAdapterRequest): Promise<Response>;
|
|
55
|
+
private log;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface PaginationOptions {
|
|
59
|
+
skip?: number;
|
|
60
|
+
take?: number;
|
|
61
|
+
}
|
|
62
|
+
interface Paged<T> {
|
|
63
|
+
data: T[];
|
|
64
|
+
perPage?: number;
|
|
65
|
+
pageSize: number;
|
|
66
|
+
total: number;
|
|
67
|
+
pages: number;
|
|
68
|
+
hasNext: boolean;
|
|
69
|
+
hasPrev: boolean;
|
|
70
|
+
}
|
|
71
|
+
interface IntrospectResult {
|
|
72
|
+
active: boolean;
|
|
73
|
+
sub?: string;
|
|
74
|
+
username?: string | null;
|
|
75
|
+
email?: string | null;
|
|
76
|
+
roles?: string[] | null;
|
|
77
|
+
permissions?: string[];
|
|
78
|
+
client_id?: string;
|
|
79
|
+
scope?: string;
|
|
80
|
+
exp?: number;
|
|
81
|
+
iat?: number;
|
|
82
|
+
jti?: string;
|
|
83
|
+
token_type?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Organization membership (the Authyon API calls this a "tenant" on the
|
|
88
|
+
* wire — the SDK exposes it as "organization").
|
|
89
|
+
*/
|
|
90
|
+
interface Organization {
|
|
91
|
+
id: string;
|
|
92
|
+
slug: string;
|
|
93
|
+
name?: string;
|
|
94
|
+
description?: string;
|
|
95
|
+
roles?: string[];
|
|
96
|
+
}
|
|
97
|
+
/** POST /auth/tenants — creates an organization owned by the signed-in user. */
|
|
98
|
+
interface CreateOrganizationInput {
|
|
99
|
+
name?: string;
|
|
100
|
+
slug?: string;
|
|
101
|
+
description?: string;
|
|
102
|
+
}
|
|
103
|
+
/** GET /auth/tenants/{organizationId}/members — confirmed against the live API. */
|
|
104
|
+
interface OrganizationMember {
|
|
105
|
+
userId: string;
|
|
106
|
+
email?: string;
|
|
107
|
+
username?: string;
|
|
108
|
+
roles?: string[];
|
|
109
|
+
createdAt?: string;
|
|
110
|
+
lastLoginAt?: string | null;
|
|
111
|
+
}
|
|
112
|
+
/** POST /auth/tenants/{tenantId}/members — invites a member by e-mail. */
|
|
113
|
+
interface InviteMemberInput {
|
|
114
|
+
email: string;
|
|
115
|
+
roles: string[];
|
|
116
|
+
}
|
|
117
|
+
/** Authenticated user profile. */
|
|
118
|
+
interface User {
|
|
119
|
+
id: string;
|
|
120
|
+
email: string;
|
|
121
|
+
username?: string;
|
|
122
|
+
emailConfirmed?: boolean;
|
|
123
|
+
firstName?: string | null;
|
|
124
|
+
lastName?: string | null;
|
|
125
|
+
roles?: string[];
|
|
126
|
+
permissions?: string[];
|
|
127
|
+
createdAt?: string;
|
|
128
|
+
lastLoginAt?: string;
|
|
129
|
+
organizations?: Organization[];
|
|
130
|
+
activeOrganization?: Organization | null;
|
|
131
|
+
/** Actions the user must complete before continuing (e.g. confirm e-mail). */
|
|
132
|
+
pendencies?: string[];
|
|
133
|
+
}
|
|
134
|
+
/** Token pair issued by login / refresh / tenant switch. */
|
|
135
|
+
interface Session {
|
|
136
|
+
accessToken: string;
|
|
137
|
+
refreshToken: string;
|
|
138
|
+
/** Access-token lifetime in seconds (typically 1800). */
|
|
139
|
+
expiresIn: number;
|
|
140
|
+
/** Epoch ms when the access token expires (computed client-side). */
|
|
141
|
+
expiresAt: number;
|
|
142
|
+
user?: User;
|
|
143
|
+
}
|
|
144
|
+
type TwoFactorMethod = "authenticator" | "email" | "webauthn" | string;
|
|
145
|
+
/** Returned by `login()` when the account has 2FA enabled. */
|
|
146
|
+
interface TwoFactorChallenge {
|
|
147
|
+
twoFactorRequired: true;
|
|
148
|
+
challengeToken: string;
|
|
149
|
+
methods: TwoFactorMethod[];
|
|
150
|
+
emailHint?: string;
|
|
151
|
+
}
|
|
152
|
+
type LoginResult = {
|
|
153
|
+
twoFactorRequired: false;
|
|
154
|
+
session: Session;
|
|
155
|
+
} | TwoFactorChallenge;
|
|
156
|
+
interface RegisterInput {
|
|
157
|
+
email: string;
|
|
158
|
+
username?: string;
|
|
159
|
+
password: string;
|
|
160
|
+
}
|
|
161
|
+
interface LoginInput {
|
|
162
|
+
/** Provide `email` or `username`. */
|
|
163
|
+
email?: string;
|
|
164
|
+
username?: string;
|
|
165
|
+
password: string;
|
|
166
|
+
/** Optional organization to scope the session to (sent as `tenantSlug`). */
|
|
167
|
+
organizationSlug?: string;
|
|
168
|
+
}
|
|
169
|
+
/** A completed WebAuthn ceremony, handed back to the server to finish login/registration. */
|
|
170
|
+
interface WebAuthnAssertion {
|
|
171
|
+
ceremonyToken: string;
|
|
172
|
+
/** JSON-serialized `PublicKeyCredential` returned by `navigator.credentials.get()`. */
|
|
173
|
+
assertionJson: string;
|
|
174
|
+
}
|
|
175
|
+
/** POST /auth/2fa/verify — redeems a challenge from `login()`. */
|
|
176
|
+
interface VerifyTwoFactorInput {
|
|
177
|
+
challengeToken: string;
|
|
178
|
+
method: TwoFactorMethod;
|
|
179
|
+
/** TOTP / email / recovery code. Omit when `method` is `"webauthn"`. */
|
|
180
|
+
code?: string;
|
|
181
|
+
/** Required when `method` is `"webauthn"`. */
|
|
182
|
+
webAuthnAssertion?: WebAuthnAssertion;
|
|
183
|
+
}
|
|
184
|
+
/** GET /auth/2fa/status — per-method enrolment flags, confirmed against the live API. */
|
|
185
|
+
interface TwoFactorStatus {
|
|
186
|
+
authenticatorEnabled: boolean;
|
|
187
|
+
authenticatorConfirmedAt?: string | null;
|
|
188
|
+
emailEnabled: boolean;
|
|
189
|
+
emailEnabledAt?: string | null;
|
|
190
|
+
/** Partially redacted (e.g. `"n**********@h***.com"`). */
|
|
191
|
+
emailHint?: string | null;
|
|
192
|
+
webAuthnEnabled: boolean;
|
|
193
|
+
webAuthnCredentialCount: number;
|
|
194
|
+
webAuthnCredentials: WebAuthnCredential[];
|
|
195
|
+
remainingRecoveryCodes: number;
|
|
196
|
+
}
|
|
197
|
+
interface AuthenticatorSetup {
|
|
198
|
+
secret: string;
|
|
199
|
+
qrSvg: string;
|
|
200
|
+
otpauthUri: string;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Options handed back by a WebAuthn "start" endpoint: a ceremony token to
|
|
204
|
+
* correlate the "finish" call, plus the WebAuthn options object to pass into
|
|
205
|
+
* `navigator.credentials.get()` / `.create()` (after `JSON.parse`, per the
|
|
206
|
+
* WebAuthn spec — challenge/user.id are base64url strings on the wire).
|
|
207
|
+
*
|
|
208
|
+
* ⚠️ The exact shape of `options` is not published in the OpenAPI schema (no
|
|
209
|
+
* response bodies are documented for any endpoint at the time this SDK was
|
|
210
|
+
* written) — treat it as opaque input to the WebAuthn API.
|
|
211
|
+
*/
|
|
212
|
+
interface WebAuthnCeremonyStart {
|
|
213
|
+
ceremonyToken: string;
|
|
214
|
+
options: unknown;
|
|
215
|
+
}
|
|
216
|
+
interface WebAuthnCredential {
|
|
217
|
+
id: string;
|
|
218
|
+
nickname?: string;
|
|
219
|
+
createdAt?: string;
|
|
220
|
+
}
|
|
221
|
+
interface SsoProvider {
|
|
222
|
+
name: string;
|
|
223
|
+
slug: string;
|
|
224
|
+
/** URL to redirect the browser to in order to start this provider's flow. */
|
|
225
|
+
startUrl: string;
|
|
226
|
+
}
|
|
227
|
+
/** GET /auth/me/activities — one audit-trail entry, confirmed against the live API. */
|
|
228
|
+
interface Activity {
|
|
229
|
+
id: string;
|
|
230
|
+
eventType: string;
|
|
231
|
+
occurredAt: string;
|
|
232
|
+
environmentId?: string;
|
|
233
|
+
ip?: string;
|
|
234
|
+
userAgent?: string;
|
|
235
|
+
/** JSON-encoded string — `JSON.parse` it for the event-specific payload. */
|
|
236
|
+
payloadJson?: string;
|
|
237
|
+
}
|
|
238
|
+
/** A role available within an organization (tenant). */
|
|
239
|
+
interface Role {
|
|
240
|
+
id: string;
|
|
241
|
+
name: string;
|
|
242
|
+
description?: string;
|
|
243
|
+
permissions?: string[];
|
|
244
|
+
}
|
|
245
|
+
/** GET /auth/sessions — confirmed against the live API. */
|
|
246
|
+
interface SessionInfo {
|
|
247
|
+
id: string;
|
|
248
|
+
createdAt: string;
|
|
249
|
+
expiresAt: string;
|
|
250
|
+
revokedAt?: string | null;
|
|
251
|
+
createdFromIp?: string;
|
|
252
|
+
isActive: boolean;
|
|
253
|
+
userAgent?: string;
|
|
254
|
+
lastUsedAt?: string | null;
|
|
255
|
+
lastUsedFromIp?: string | null;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* POST /auth/validate — confirmed against the live API. The wire shape is
|
|
259
|
+
* `{ valid, reason, profile }`, not `{ user, organization }` as the
|
|
260
|
+
* OpenAPI schema (which didn't document response bodies) suggested.
|
|
261
|
+
* `profile` is `null` for machine tokens (there's no user behind them) and
|
|
262
|
+
* for tokens that fail validation.
|
|
263
|
+
*/
|
|
264
|
+
interface ValidateResult {
|
|
265
|
+
valid: boolean;
|
|
266
|
+
reason?: string | null;
|
|
267
|
+
user: User | null;
|
|
268
|
+
}
|
|
269
|
+
type AuthEvent = {
|
|
270
|
+
type: "signed_in";
|
|
271
|
+
session: Session;
|
|
272
|
+
} | {
|
|
273
|
+
type: "refreshed";
|
|
274
|
+
session: Session;
|
|
275
|
+
} | {
|
|
276
|
+
type: "session_validated";
|
|
277
|
+
session: Session;
|
|
278
|
+
} | {
|
|
279
|
+
type: "signed_out";
|
|
280
|
+
};
|
|
281
|
+
type AuthStateListener = (event: AuthEvent) => void;
|
|
282
|
+
/** Pluggable persistence for the token pair. */
|
|
283
|
+
interface TokenStorage {
|
|
284
|
+
get(): Session | null;
|
|
285
|
+
set(session: Session): void;
|
|
286
|
+
clear(): void;
|
|
287
|
+
}
|
|
288
|
+
type AuthState = "signed_out" | "authenticated" | "expired";
|
|
289
|
+
interface AuthyonClientOptions {
|
|
290
|
+
/** Publishable environment key (`pk_live_...` / `pk_test_...`). */
|
|
291
|
+
envKey: string;
|
|
292
|
+
/** API origin. Defaults to `https://api.authyon.com`; HTTPS is required outside loopback. */
|
|
293
|
+
baseUrl?: string;
|
|
294
|
+
/** Allow an HTTP `baseUrl`. Intended only for explicitly trusted local development. */
|
|
295
|
+
allowInsecureHttp?: boolean;
|
|
296
|
+
/** Where tokens are persisted. Defaults to memory; persistent storage is explicit opt-in. */
|
|
297
|
+
storage?: TokenStorage;
|
|
298
|
+
/**
|
|
299
|
+
* Automatically refresh the access token shortly before it expires and
|
|
300
|
+
* retry once on 401. Defaults to `true`.
|
|
301
|
+
*/
|
|
302
|
+
autoRefresh?: boolean;
|
|
303
|
+
/** Maximum duration of each HTTP request. Defaults to 15 seconds; set to `0` to disable. */
|
|
304
|
+
timeoutMs?: number;
|
|
305
|
+
/** Custom HTTP adapter for tracing, mocks or an alternative HTTP stack. */
|
|
306
|
+
httpAdapter?: HttpAdapter;
|
|
307
|
+
/** Safe HTTP lifecycle logging. Disabled unless this option is provided with `enabled: true`. */
|
|
308
|
+
httpLogger?: HttpLoggerOptions;
|
|
309
|
+
/** @deprecated Prefer `httpAdapter: new FetchHttpAdapter(customFetch)`. */
|
|
310
|
+
fetch?: typeof fetch;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
declare class AuthyonClient {
|
|
314
|
+
private readonly envKey;
|
|
315
|
+
private readonly baseUrl;
|
|
316
|
+
private readonly storage;
|
|
317
|
+
private readonly autoRefresh;
|
|
318
|
+
private readonly transport;
|
|
319
|
+
private readonly http;
|
|
320
|
+
private readonly listeners;
|
|
321
|
+
private refreshInFlight;
|
|
322
|
+
constructor(options: AuthyonClientOptions);
|
|
323
|
+
/** Current persisted session, or null when signed out. */
|
|
324
|
+
getSession(): Session | null;
|
|
325
|
+
isAuthenticated(): boolean;
|
|
326
|
+
/** Synchronous snapshot of the locally available authentication state. */
|
|
327
|
+
getAuthState(): "signed_out" | "authenticated" | "expired";
|
|
328
|
+
/**
|
|
329
|
+
* Returns a valid access token, refreshing it transparently when it is
|
|
330
|
+
* expired or about to expire. Returns null when signed out.
|
|
331
|
+
*/
|
|
332
|
+
getAccessToken(): Promise<string | null>;
|
|
333
|
+
/**
|
|
334
|
+
* Refreshes when needed, validates the server-side session through `GET /auth/me`,
|
|
335
|
+
* and stores the fresh user profile. Returns null when the session is no longer valid.
|
|
336
|
+
*/
|
|
337
|
+
validateSession(): Promise<Session | null>;
|
|
338
|
+
/** Subscribe to sign-in / refresh / sign-out events. Returns an unsubscribe fn. */
|
|
339
|
+
onAuthStateChange(listener: AuthStateListener): () => void;
|
|
340
|
+
private emit;
|
|
341
|
+
private setSession;
|
|
342
|
+
private clearSession;
|
|
343
|
+
/**
|
|
344
|
+
* `/auth/login` and the other endpoints that mint a session don't return
|
|
345
|
+
* a `user` object on the wire — only `tokens` (plus `twoFactor`, when a
|
|
346
|
+
* challenge is required). Fetch the profile right after so callers get a
|
|
347
|
+
* fully-populated `session.user` without an extra manual round trip.
|
|
348
|
+
* Best-effort: keeps the session usable even if this fetch fails.
|
|
349
|
+
*/
|
|
350
|
+
private hydrateUser;
|
|
351
|
+
private request;
|
|
352
|
+
/** POST /auth/register — creates a new user (rate-limited to 20/hour per IP). */
|
|
353
|
+
register(params: RegisterInput): Promise<{
|
|
354
|
+
id: string;
|
|
355
|
+
}>;
|
|
356
|
+
/**
|
|
357
|
+
* POST /auth/login — authenticates and stores the session, or returns a
|
|
358
|
+
* 2FA challenge to complete via `verifyTwoFactor()`.
|
|
359
|
+
*/
|
|
360
|
+
login(params: LoginInput): Promise<LoginResult>;
|
|
361
|
+
/** POST /auth/2fa/verify — redeems a 2FA challenge from `login()` and stores the session. */
|
|
362
|
+
verifyTwoFactor(params: VerifyTwoFactorInput): Promise<Session>;
|
|
363
|
+
/** POST /auth/refresh — rotates the single-use refresh token (single-flight). */
|
|
364
|
+
refresh(): Promise<Session>;
|
|
365
|
+
/**
|
|
366
|
+
* POST /auth/logout — revokes the current refresh token and clears local
|
|
367
|
+
* state. Pass `{ everywhere: true }` to revoke every session for the user.
|
|
368
|
+
*/
|
|
369
|
+
logout(options?: {
|
|
370
|
+
everywhere?: boolean;
|
|
371
|
+
}): Promise<void>;
|
|
372
|
+
readonly webauthn: {
|
|
373
|
+
/** POST /auth/webauthn/login/start — begins a passkey sign-in. */
|
|
374
|
+
loginStart: (email?: string) => Promise<WebAuthnCeremonyStart>;
|
|
375
|
+
/**
|
|
376
|
+
* POST /auth/webauthn/login/finish — completes the passkey ceremony and
|
|
377
|
+
* stores the session.
|
|
378
|
+
*/
|
|
379
|
+
loginFinish: (assertion: WebAuthnAssertion) => Promise<Session>;
|
|
380
|
+
};
|
|
381
|
+
readonly sso: {
|
|
382
|
+
/** GET /auth/sso/providers — providers enabled for this environment. */
|
|
383
|
+
providers: () => Promise<SsoProvider[]>;
|
|
384
|
+
/**
|
|
385
|
+
* Builds the URL to redirect the browser to in order to start a
|
|
386
|
+
* provider's sign-in flow (`GET /auth/sso/{provider}/start`). Navigate
|
|
387
|
+
* to it directly — e.g. `window.location.href = client.sso.startUrl(...)`.
|
|
388
|
+
*/
|
|
389
|
+
startUrl: (provider: string, params: {
|
|
390
|
+
redirectUri: string;
|
|
391
|
+
state?: string;
|
|
392
|
+
mode?: string;
|
|
393
|
+
}) => string;
|
|
394
|
+
/**
|
|
395
|
+
* POST /auth/sso/exchange — swaps the one-time code from the provider
|
|
396
|
+
* callback for tokens and stores the session.
|
|
397
|
+
*/
|
|
398
|
+
exchange: (code: string) => Promise<Session>;
|
|
399
|
+
};
|
|
400
|
+
readonly user: {
|
|
401
|
+
/** GET /auth/me — fresh profile of the current user. */
|
|
402
|
+
me: () => Promise<User>;
|
|
403
|
+
/** GET /auth/sessions — active refresh-token sessions with device/IP data. */
|
|
404
|
+
sessions: () => Promise<SessionInfo[]>;
|
|
405
|
+
/** GET /auth/me/activities — paginated recent account activity for the current user. */
|
|
406
|
+
activities: (params?: PaginationOptions) => Promise<Paged<Activity>>;
|
|
407
|
+
/**
|
|
408
|
+
* Revokes a single session by id (e.g. one entry from `sessions()`),
|
|
409
|
+
* signing that device out without affecting the current one.
|
|
410
|
+
*
|
|
411
|
+
* ⚠️ Not directly confirmed against the published API reference at the
|
|
412
|
+
* time this SDK was written — `DELETE /auth/sessions/{id}` follows the
|
|
413
|
+
* REST convention the rest of the documented API uses, but verify it
|
|
414
|
+
* against the Authyon dashboard/API reference before relying on it. If
|
|
415
|
+
* the endpoint differs, override via a raw call to your own backend.
|
|
416
|
+
*/
|
|
417
|
+
revokeSession: (sessionId: string) => Promise<void>;
|
|
418
|
+
/** POST /auth/password-reset/request — always resolves (no account enumeration). */
|
|
419
|
+
requestPasswordReset: (email: string) => Promise<void>;
|
|
420
|
+
/** POST /auth/password-reset/confirm — sets a new password and revokes all refresh tokens. */
|
|
421
|
+
confirmPasswordReset: (token: string, newPassword: string) => Promise<void>;
|
|
422
|
+
};
|
|
423
|
+
readonly organization: {
|
|
424
|
+
/** GET /auth/tenants — all organization memberships. */
|
|
425
|
+
list: () => Promise<Organization[]>;
|
|
426
|
+
/**
|
|
427
|
+
* POST /auth/tenants — creates an organization owned by the signed-in
|
|
428
|
+
* user (only available when self-service organization creation is
|
|
429
|
+
* enabled for the environment).
|
|
430
|
+
*/
|
|
431
|
+
create: (params?: CreateOrganizationInput) => Promise<Organization>;
|
|
432
|
+
/** GET /auth/tenants/{organizationId} — fetch one of the user's organizations by id. */
|
|
433
|
+
get: (organizationId: string) => Promise<Organization>;
|
|
434
|
+
/**
|
|
435
|
+
* PATCH /auth/tenants/{organizationId} — renames the organization.
|
|
436
|
+
* Requires the `tenants:manage` custom permission on it.
|
|
437
|
+
*/
|
|
438
|
+
rename: (organizationId: string, name: string) => Promise<Organization>;
|
|
439
|
+
/** POST /auth/switch-tenant — issues a fresh token scoped to the new organization. */
|
|
440
|
+
switch: (organizationSlug: string) => Promise<Session>;
|
|
441
|
+
/** The organization the current session is scoped to, from the cached session — no network call. */
|
|
442
|
+
current: () => Organization | null;
|
|
443
|
+
members: {
|
|
444
|
+
/**
|
|
445
|
+
* GET /auth/tenants/{organizationId}/members — paginated list of an
|
|
446
|
+
* organization's members. Consistent with the confirmed-live
|
|
447
|
+
* `Paged<T>` envelope every other `skip`/`take` endpoint returns
|
|
448
|
+
* (`user.activities()`, `@authyon/server`'s `environment.users.list()`).
|
|
449
|
+
*/
|
|
450
|
+
list: (organizationId: string, params?: PaginationOptions) => Promise<Paged<OrganizationMember>>;
|
|
451
|
+
/** POST /auth/tenants/{organizationId}/members — invite a member by e-mail. */
|
|
452
|
+
invite: (organizationId: string, params: InviteMemberInput) => Promise<void>;
|
|
453
|
+
/** DELETE /auth/tenants/{organizationId}/members/{userId} — remove a member. */
|
|
454
|
+
remove: (organizationId: string, userId: string) => Promise<void>;
|
|
455
|
+
};
|
|
456
|
+
roles: {
|
|
457
|
+
/** GET /auth/tenants/{organizationId}/roles — roles available in the organization. */
|
|
458
|
+
list: (organizationId: string) => Promise<Role[]>;
|
|
459
|
+
};
|
|
460
|
+
};
|
|
461
|
+
readonly twoFactor: {
|
|
462
|
+
/** GET /auth/2fa/status — enrolled methods and recovery code count. */
|
|
463
|
+
status: () => Promise<TwoFactorStatus>;
|
|
464
|
+
/** POST /auth/2fa/resend-email — resends the code for an in-flight login challenge. */
|
|
465
|
+
resendEmail: (challengeToken: string) => Promise<void>;
|
|
466
|
+
/** POST /auth/2fa/authenticator/setup — returns secret, QR SVG and otpauth URI. */
|
|
467
|
+
setupAuthenticator: () => Promise<AuthenticatorSetup>;
|
|
468
|
+
/** POST /auth/2fa/authenticator/confirm — returns 10 single-use recovery codes. */
|
|
469
|
+
confirmAuthenticator: (code: string) => Promise<{
|
|
470
|
+
recoveryCodes: string[];
|
|
471
|
+
}>;
|
|
472
|
+
/**
|
|
473
|
+
* POST /auth/2fa/email/enable — two-step opt-in for email-based OTP.
|
|
474
|
+
* Call without `code` to receive one by e-mail, then call again with
|
|
475
|
+
* that code to confirm enrolment.
|
|
476
|
+
*/
|
|
477
|
+
enableEmail: (code?: string) => Promise<void>;
|
|
478
|
+
/** POST /auth/2fa/disable — turns off a specific 2FA method (requires current password). */
|
|
479
|
+
disable: (method: TwoFactorMethod, currentPassword: string) => Promise<void>;
|
|
480
|
+
/**
|
|
481
|
+
* POST /auth/2fa/recovery-codes/regenerate — rotates the 10 single-use
|
|
482
|
+
* recovery codes (requires current password).
|
|
483
|
+
*/
|
|
484
|
+
regenerateRecoveryCodes: (currentPassword: string) => Promise<{
|
|
485
|
+
recoveryCodes: string[];
|
|
486
|
+
}>;
|
|
487
|
+
webauthn: {
|
|
488
|
+
/** POST /auth/2fa/webauthn/register/start — begins passkey enrolment for 2FA. */
|
|
489
|
+
registerStart: () => Promise<WebAuthnCeremonyStart>;
|
|
490
|
+
/** POST /auth/2fa/webauthn/register/finish — finishes passkey enrolment. */
|
|
491
|
+
registerFinish: (ceremonyToken: string, attestationJson: string, nickname?: string) => Promise<WebAuthnCredential>;
|
|
492
|
+
/** GET /auth/2fa/webauthn/credentials — the caller's registered passkeys. */
|
|
493
|
+
credentials: () => Promise<WebAuthnCredential[]>;
|
|
494
|
+
/** PATCH /auth/2fa/webauthn/credentials/{id} — renames a passkey. */
|
|
495
|
+
renameCredential: (id: string, nickname: string) => Promise<WebAuthnCredential>;
|
|
496
|
+
/** DELETE /auth/2fa/webauthn/credentials/{id} — removes a passkey (requires current password). */
|
|
497
|
+
removeCredential: (id: string, currentPassword: string) => Promise<void>;
|
|
498
|
+
/**
|
|
499
|
+
* POST /auth/2fa/webauthn/assertion/start — fetches WebAuthn assertion
|
|
500
|
+
* options for an in-flight login challenge (2FA method `"webauthn"`).
|
|
501
|
+
*/
|
|
502
|
+
assertionStart: (challengeToken: string) => Promise<WebAuthnCeremonyStart>;
|
|
503
|
+
};
|
|
504
|
+
};
|
|
505
|
+
/**
|
|
506
|
+
* POST /auth/introspect — lightweight token introspection (RFC 7662).
|
|
507
|
+
*
|
|
508
|
+
* ⚠️ Confirmed live: this endpoint requires the CALLER to also
|
|
509
|
+
* authenticate, with an environment or tenant client-credentials bearer
|
|
510
|
+
* token — the end user's own access token doesn't satisfy that (401).
|
|
511
|
+
* A browser app has no client secret to present, so this will fail from
|
|
512
|
+
* `@authyon/auth` in practice; call it from your backend via
|
|
513
|
+
* `@authyon/server` instead.
|
|
514
|
+
*
|
|
515
|
+
* @deprecated Use `@authyon/server.introspect()` from a trusted backend.
|
|
516
|
+
*/
|
|
517
|
+
introspect(token?: string): Promise<IntrospectResult>;
|
|
518
|
+
/**
|
|
519
|
+
* POST /auth/validate — recommended: cross-checks DB state, catches
|
|
520
|
+
* revocation immediately. Same caller-authentication requirement (and
|
|
521
|
+
* the same practical limitation from the browser) as `introspect()`.
|
|
522
|
+
*
|
|
523
|
+
* @deprecated Use `@authyon/server.validate()` from a trusted backend.
|
|
524
|
+
*/
|
|
525
|
+
validate(token?: string): Promise<ValidateResult>;
|
|
526
|
+
}
|
|
527
|
+
/** Convenience factory: `const authyon = createClient({ envKey: "pk_live_..." })`. */
|
|
528
|
+
declare function createClient(options: AuthyonClientOptions): AuthyonClient;
|
|
529
|
+
|
|
530
|
+
type SessionStatus = "validating" | "authenticated" | "unauthenticated" | "error";
|
|
531
|
+
interface SessionSnapshot {
|
|
532
|
+
status: SessionStatus;
|
|
533
|
+
session: Session | null;
|
|
534
|
+
user: User | null;
|
|
535
|
+
error: unknown | null;
|
|
536
|
+
}
|
|
537
|
+
interface SessionControllerOptions {
|
|
538
|
+
/** Refresh before expiration. Defaults to 30 seconds. */
|
|
539
|
+
refreshAheadMs?: number;
|
|
540
|
+
}
|
|
541
|
+
type SessionSnapshotListener = () => void;
|
|
542
|
+
/** Framework-agnostic session lifecycle used by the React/Next.js integration. */
|
|
543
|
+
declare class AuthyonSessionController {
|
|
544
|
+
readonly client: AuthyonClient;
|
|
545
|
+
private snapshot;
|
|
546
|
+
private readonly listeners;
|
|
547
|
+
private unsubscribeAuth?;
|
|
548
|
+
private refreshTimer?;
|
|
549
|
+
private validation?;
|
|
550
|
+
private readonly refreshAheadMs;
|
|
551
|
+
constructor(client: AuthyonClient, options?: SessionControllerOptions);
|
|
552
|
+
getSnapshot: () => SessionSnapshot;
|
|
553
|
+
getServerSnapshot: () => SessionSnapshot;
|
|
554
|
+
subscribe: (listener: SessionSnapshotListener) => (() => void);
|
|
555
|
+
start(): () => void;
|
|
556
|
+
stop(): void;
|
|
557
|
+
validate(): Promise<SessionSnapshot>;
|
|
558
|
+
refreshNow(): Promise<SessionSnapshot>;
|
|
559
|
+
private acceptSession;
|
|
560
|
+
private scheduleRefresh;
|
|
561
|
+
private cancelRefresh;
|
|
562
|
+
private setSnapshot;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
type AbilitySubject = string | Record<string, unknown>;
|
|
566
|
+
type AbilityConditions = Record<string, unknown>;
|
|
567
|
+
interface AbilityRule {
|
|
568
|
+
action: string | string[];
|
|
569
|
+
subject: string | string[];
|
|
570
|
+
inverted?: boolean;
|
|
571
|
+
conditions?: AbilityConditions;
|
|
572
|
+
fields?: string[];
|
|
573
|
+
reason?: string;
|
|
574
|
+
}
|
|
575
|
+
interface AuthyonPermissionSource {
|
|
576
|
+
permissions?: readonly string[] | null;
|
|
577
|
+
roles?: readonly string[] | null;
|
|
578
|
+
/** OAuth scopes are also accepted and interpreted as Authyon permissions. */
|
|
579
|
+
scope?: string | null;
|
|
580
|
+
}
|
|
581
|
+
interface AuthyonAbilityOptions {
|
|
582
|
+
rules?: readonly AbilityRule[];
|
|
583
|
+
/** Rules added when the source contains a matching Authyon role. */
|
|
584
|
+
roleRules?: Readonly<Record<string, readonly AbilityRule[]>>;
|
|
585
|
+
roles?: readonly string[] | null;
|
|
586
|
+
detectSubjectType?: (subject: Record<string, unknown>) => string;
|
|
587
|
+
}
|
|
588
|
+
type AbilityEvent = "updated";
|
|
589
|
+
type AbilityListener = (rules: readonly AbilityRule[]) => void;
|
|
590
|
+
/** Isomorphic, deny-by-default authorization engine backed by Authyon permissions. */
|
|
591
|
+
declare class AuthyonAbility {
|
|
592
|
+
private readonly detectSubjectType;
|
|
593
|
+
private currentRules;
|
|
594
|
+
private readonly listeners;
|
|
595
|
+
constructor(rules?: readonly AbilityRule[], detectSubjectType?: (subject: Record<string, unknown>) => string);
|
|
596
|
+
get rules(): readonly AbilityRule[];
|
|
597
|
+
can(action: string, subject: AbilitySubject, field?: string): boolean;
|
|
598
|
+
cannot(action: string, subject: AbilitySubject, field?: string): boolean;
|
|
599
|
+
rulesFor(action: string, subject: string): readonly AbilityRule[];
|
|
600
|
+
update(rules: readonly AbilityRule[]): void;
|
|
601
|
+
on(event: AbilityEvent, listener: AbilityListener): () => void;
|
|
602
|
+
}
|
|
603
|
+
/** Fluent rule builder with CASL-like `can` and `cannot` methods. */
|
|
604
|
+
declare class AuthyonAbilityBuilder {
|
|
605
|
+
readonly rules: AbilityRule[];
|
|
606
|
+
can(action: string | string[], subject: string | string[], conditions?: AbilityConditions, fields?: string[]): this;
|
|
607
|
+
cannot(action: string | string[], subject: string | string[], conditions?: AbilityConditions, fields?: string[], reason?: string): this;
|
|
608
|
+
build(options?: Pick<AuthyonAbilityOptions, "detectSubjectType">): AuthyonAbility;
|
|
609
|
+
}
|
|
610
|
+
/** Creates an ability from Authyon permissions, OAuth scope and optional role rules. */
|
|
611
|
+
declare function createAuthyonAbility(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AuthyonAbility;
|
|
612
|
+
/** Checks an Authyon permission string using the same wildcard rules as an ability. */
|
|
613
|
+
declare function hasPermission(source: AuthyonPermissionSource | readonly string[], requiredPermission: string): boolean;
|
|
614
|
+
/** Converts Authyon's `subject:action` permission strings to authorization rules. */
|
|
615
|
+
declare function createAuthyonRules(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AbilityRule[];
|
|
616
|
+
|
|
617
|
+
export { createAuthyonRules as $, AuthyonClient as A, type SessionControllerOptions as B, type CreateOrganizationInput as C, type SessionInfo as D, type SessionSnapshot as E, FetchHttpAdapter as F, type SessionSnapshotListener as G, type HttpAdapter as H, type IntrospectResult as I, type SessionStatus as J, type SsoProvider as K, LoggingHttpAdapter as L, type TwoFactorChallenge as M, type TwoFactorMethod as N, type Organization as O, type Paged as P, type TwoFactorStatus as Q, type RegisterInput as R, type Session as S, type TokenStorage as T, type User as U, type ValidateResult as V, type VerifyTwoFactorInput as W, type WebAuthnAssertion as X, type WebAuthnCeremonyStart as Y, type WebAuthnCredential as Z, createAuthyonAbility as _, type HttpLoggerOptions as a, createClient as a0, hasPermission as a1, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type Activity as g, type AuthEvent as h, type AuthState as i, type AuthStateListener as j, type AuthenticatorSetup as k, AuthyonAbility as l, AuthyonAbilityBuilder as m, type AuthyonAbilityOptions as n, type AuthyonClientOptions as o, type AuthyonPermissionSource as p, AuthyonSessionController as q, type HttpAdapterRequest as r, type HttpLogEvent as s, type HttpLogger as t, type InviteMemberInput as u, type LoginInput as v, type LoginResult as w, type OrganizationMember as x, type PaginationOptions as y, type Role as z };
|