@authyon/auth 0.1.3
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 +158 -0
- package/dist/index.cjs +501 -0
- package/dist/index.d.cts +403 -0
- package/dist/index.d.ts +403 -0
- package/dist/index.js +468 -0
- package/package.json +37 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Organization membership (the Authyon API calls this a "tenant" on the
|
|
3
|
+
* wire — the SDK exposes it as "organization").
|
|
4
|
+
*/
|
|
5
|
+
interface Organization {
|
|
6
|
+
id: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
name?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
roles?: string[];
|
|
11
|
+
}
|
|
12
|
+
/** POST /auth/tenants — creates an organization owned by the signed-in user. */
|
|
13
|
+
interface CreateOrganizationParams {
|
|
14
|
+
name?: string;
|
|
15
|
+
slug?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
}
|
|
18
|
+
interface OrganizationMember {
|
|
19
|
+
userId: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
roles?: string[];
|
|
22
|
+
}
|
|
23
|
+
/** POST /auth/tenants/{tenantId}/members — invites a member by e-mail. */
|
|
24
|
+
interface InviteMemberParams {
|
|
25
|
+
email: string;
|
|
26
|
+
roles: string[];
|
|
27
|
+
}
|
|
28
|
+
/** Pagination options accepted by list endpoints. */
|
|
29
|
+
interface PageParams {
|
|
30
|
+
skip?: number;
|
|
31
|
+
take?: number;
|
|
32
|
+
}
|
|
33
|
+
/** Authenticated user profile. */
|
|
34
|
+
interface User {
|
|
35
|
+
id: string;
|
|
36
|
+
email: string;
|
|
37
|
+
username?: string;
|
|
38
|
+
organizations?: Organization[];
|
|
39
|
+
activeOrganization?: Organization | null;
|
|
40
|
+
permissions?: string[];
|
|
41
|
+
}
|
|
42
|
+
/** Token pair issued by login / refresh / tenant switch. */
|
|
43
|
+
interface Session {
|
|
44
|
+
accessToken: string;
|
|
45
|
+
refreshToken: string;
|
|
46
|
+
/** Access-token lifetime in seconds (typically 1800). */
|
|
47
|
+
expiresIn: number;
|
|
48
|
+
/** Epoch ms when the access token expires (computed client-side). */
|
|
49
|
+
expiresAt: number;
|
|
50
|
+
user?: User;
|
|
51
|
+
}
|
|
52
|
+
type TwoFactorMethod = "authenticator" | "email" | "webauthn" | string;
|
|
53
|
+
/** Returned by `login()` when the account has 2FA enabled. */
|
|
54
|
+
interface TwoFactorChallenge {
|
|
55
|
+
twoFactorRequired: true;
|
|
56
|
+
challengeToken: string;
|
|
57
|
+
methods: TwoFactorMethod[];
|
|
58
|
+
emailHint?: string;
|
|
59
|
+
}
|
|
60
|
+
type LoginResult = {
|
|
61
|
+
twoFactorRequired: false;
|
|
62
|
+
session: Session;
|
|
63
|
+
} | TwoFactorChallenge;
|
|
64
|
+
interface RegisterParams {
|
|
65
|
+
email: string;
|
|
66
|
+
username?: string;
|
|
67
|
+
password: string;
|
|
68
|
+
}
|
|
69
|
+
interface LoginParams {
|
|
70
|
+
/** Provide `email` or `username`. */
|
|
71
|
+
email?: string;
|
|
72
|
+
username?: string;
|
|
73
|
+
password: string;
|
|
74
|
+
/** Optional organization to scope the session to (sent as `tenantSlug`). */
|
|
75
|
+
organizationSlug?: string;
|
|
76
|
+
}
|
|
77
|
+
/** A completed WebAuthn ceremony, handed back to the server to finish login/registration. */
|
|
78
|
+
interface WebAuthnAssertion {
|
|
79
|
+
ceremonyToken: string;
|
|
80
|
+
/** JSON-serialized `PublicKeyCredential` returned by `navigator.credentials.get()`. */
|
|
81
|
+
assertionJson: string;
|
|
82
|
+
}
|
|
83
|
+
/** POST /auth/2fa/verify — redeems a challenge from `login()`. */
|
|
84
|
+
interface TwoFactorVerifyParams {
|
|
85
|
+
challengeToken: string;
|
|
86
|
+
method: TwoFactorMethod;
|
|
87
|
+
/** TOTP / email / recovery code. Omit when `method` is `"webauthn"`. */
|
|
88
|
+
code?: string;
|
|
89
|
+
/** Required when `method` is `"webauthn"`. */
|
|
90
|
+
webAuthnAssertion?: WebAuthnAssertion;
|
|
91
|
+
}
|
|
92
|
+
interface TwoFactorStatus {
|
|
93
|
+
methods: TwoFactorMethod[];
|
|
94
|
+
recoveryCodesRemaining?: number;
|
|
95
|
+
}
|
|
96
|
+
interface AuthenticatorSetup {
|
|
97
|
+
secret: string;
|
|
98
|
+
qrSvg: string;
|
|
99
|
+
otpauthUri: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Options handed back by a WebAuthn "start" endpoint: a ceremony token to
|
|
103
|
+
* correlate the "finish" call, plus the WebAuthn options object to pass into
|
|
104
|
+
* `navigator.credentials.get()` / `.create()` (after `JSON.parse`, per the
|
|
105
|
+
* WebAuthn spec — challenge/user.id are base64url strings on the wire).
|
|
106
|
+
*
|
|
107
|
+
* ⚠️ The exact shape of `options` is not published in the OpenAPI schema (no
|
|
108
|
+
* response bodies are documented for any endpoint at the time this SDK was
|
|
109
|
+
* written) — treat it as opaque input to the WebAuthn API.
|
|
110
|
+
*/
|
|
111
|
+
interface WebAuthnCeremonyStart {
|
|
112
|
+
ceremonyToken: string;
|
|
113
|
+
options: unknown;
|
|
114
|
+
}
|
|
115
|
+
interface WebAuthnCredential {
|
|
116
|
+
id: string;
|
|
117
|
+
nickname?: string;
|
|
118
|
+
createdAt?: string;
|
|
119
|
+
}
|
|
120
|
+
interface SsoProvider {
|
|
121
|
+
name: string;
|
|
122
|
+
slug: string;
|
|
123
|
+
/** URL to redirect the browser to in order to start this provider's flow. */
|
|
124
|
+
startUrl: string;
|
|
125
|
+
}
|
|
126
|
+
interface Activity {
|
|
127
|
+
id: string;
|
|
128
|
+
type: string;
|
|
129
|
+
createdAt: string;
|
|
130
|
+
ip?: string;
|
|
131
|
+
device?: string;
|
|
132
|
+
}
|
|
133
|
+
/** A role available within an organization (tenant). */
|
|
134
|
+
interface Role {
|
|
135
|
+
id: string;
|
|
136
|
+
name: string;
|
|
137
|
+
description?: string;
|
|
138
|
+
permissions?: string[];
|
|
139
|
+
}
|
|
140
|
+
interface SessionInfo {
|
|
141
|
+
id: string;
|
|
142
|
+
createdAt?: string;
|
|
143
|
+
lastUsedAt?: string;
|
|
144
|
+
ip?: string;
|
|
145
|
+
device?: string;
|
|
146
|
+
current?: boolean;
|
|
147
|
+
}
|
|
148
|
+
interface IntrospectResult {
|
|
149
|
+
active: boolean;
|
|
150
|
+
sub?: string;
|
|
151
|
+
client_id?: string;
|
|
152
|
+
scope?: string;
|
|
153
|
+
exp?: number;
|
|
154
|
+
token_type?: string;
|
|
155
|
+
}
|
|
156
|
+
interface ValidateResult {
|
|
157
|
+
user: User;
|
|
158
|
+
organization?: Organization | null;
|
|
159
|
+
}
|
|
160
|
+
type AuthEvent = {
|
|
161
|
+
type: "signed_in";
|
|
162
|
+
session: Session;
|
|
163
|
+
} | {
|
|
164
|
+
type: "refreshed";
|
|
165
|
+
session: Session;
|
|
166
|
+
} | {
|
|
167
|
+
type: "signed_out";
|
|
168
|
+
};
|
|
169
|
+
type AuthStateListener = (event: AuthEvent) => void;
|
|
170
|
+
/** Pluggable persistence for the token pair. */
|
|
171
|
+
interface TokenStorage {
|
|
172
|
+
get(): Session | null;
|
|
173
|
+
set(session: Session): void;
|
|
174
|
+
clear(): void;
|
|
175
|
+
}
|
|
176
|
+
interface AuthyonClientOptions {
|
|
177
|
+
/** Publishable environment key (`pk_live_...` / `pk_test_...`). */
|
|
178
|
+
envKey: string;
|
|
179
|
+
/** API origin. Defaults to `https://api.authyon.com`. */
|
|
180
|
+
baseUrl?: string;
|
|
181
|
+
/** Where tokens are persisted. Defaults to localStorage when available, memory otherwise. */
|
|
182
|
+
storage?: TokenStorage;
|
|
183
|
+
/**
|
|
184
|
+
* Automatically refresh the access token shortly before it expires and
|
|
185
|
+
* retry once on 401. Defaults to `true`.
|
|
186
|
+
*/
|
|
187
|
+
autoRefresh?: boolean;
|
|
188
|
+
/** Custom fetch implementation (useful for tests / non-browser runtimes). */
|
|
189
|
+
fetch?: typeof fetch;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
declare class AuthyonClient {
|
|
193
|
+
private readonly envKey;
|
|
194
|
+
private readonly baseUrl;
|
|
195
|
+
private readonly storage;
|
|
196
|
+
private readonly autoRefresh;
|
|
197
|
+
private readonly fetchImpl;
|
|
198
|
+
private readonly listeners;
|
|
199
|
+
private refreshInFlight;
|
|
200
|
+
constructor(options: AuthyonClientOptions);
|
|
201
|
+
/** Current persisted session, or null when signed out. */
|
|
202
|
+
getSession(): Session | null;
|
|
203
|
+
isAuthenticated(): boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Returns a valid access token, refreshing it transparently when it is
|
|
206
|
+
* expired or about to expire. Returns null when signed out.
|
|
207
|
+
*/
|
|
208
|
+
getAccessToken(): Promise<string | null>;
|
|
209
|
+
/** Subscribe to sign-in / refresh / sign-out events. Returns an unsubscribe fn. */
|
|
210
|
+
onAuthStateChange(listener: AuthStateListener): () => void;
|
|
211
|
+
private emit;
|
|
212
|
+
private setSession;
|
|
213
|
+
private clearSession;
|
|
214
|
+
private request;
|
|
215
|
+
private toError;
|
|
216
|
+
/** POST /auth/register — creates a new user (rate-limited to 20/hour per IP). */
|
|
217
|
+
register(params: RegisterParams): Promise<{
|
|
218
|
+
id: string;
|
|
219
|
+
}>;
|
|
220
|
+
/**
|
|
221
|
+
* POST /auth/login — authenticates and stores the session, or returns a
|
|
222
|
+
* 2FA challenge to complete via `verifyTwoFactor()`.
|
|
223
|
+
*/
|
|
224
|
+
login(params: LoginParams): Promise<LoginResult>;
|
|
225
|
+
/** POST /auth/2fa/verify — redeems a 2FA challenge from `login()` and stores the session. */
|
|
226
|
+
verifyTwoFactor(params: TwoFactorVerifyParams): Promise<Session>;
|
|
227
|
+
/** POST /auth/refresh — rotates the single-use refresh token (single-flight). */
|
|
228
|
+
refresh(): Promise<Session>;
|
|
229
|
+
/**
|
|
230
|
+
* POST /auth/logout — revokes the current refresh token and clears local
|
|
231
|
+
* state. Pass `{ everywhere: true }` to revoke every session for the user.
|
|
232
|
+
*/
|
|
233
|
+
logout(options?: {
|
|
234
|
+
everywhere?: boolean;
|
|
235
|
+
}): Promise<void>;
|
|
236
|
+
readonly webauthn: {
|
|
237
|
+
/** POST /auth/webauthn/login/start — begins a passkey sign-in. */
|
|
238
|
+
loginStart: (email?: string) => Promise<WebAuthnCeremonyStart>;
|
|
239
|
+
/**
|
|
240
|
+
* POST /auth/webauthn/login/finish — completes the passkey ceremony and
|
|
241
|
+
* stores the session.
|
|
242
|
+
*/
|
|
243
|
+
loginFinish: (assertion: WebAuthnAssertion) => Promise<Session>;
|
|
244
|
+
};
|
|
245
|
+
readonly sso: {
|
|
246
|
+
/** GET /auth/sso/providers — providers enabled for this environment. */
|
|
247
|
+
providers: () => Promise<SsoProvider[]>;
|
|
248
|
+
/**
|
|
249
|
+
* Builds the URL to redirect the browser to in order to start a
|
|
250
|
+
* provider's sign-in flow (`GET /auth/sso/{provider}/start`). Navigate
|
|
251
|
+
* to it directly — e.g. `window.location.href = client.sso.startUrl(...)`.
|
|
252
|
+
*/
|
|
253
|
+
startUrl: (provider: string, params: {
|
|
254
|
+
redirectUri: string;
|
|
255
|
+
state?: string;
|
|
256
|
+
mode?: string;
|
|
257
|
+
}) => string;
|
|
258
|
+
/**
|
|
259
|
+
* POST /auth/sso/exchange — swaps the one-time code from the provider
|
|
260
|
+
* callback for tokens and stores the session.
|
|
261
|
+
*/
|
|
262
|
+
exchange: (code: string) => Promise<Session>;
|
|
263
|
+
};
|
|
264
|
+
readonly user: {
|
|
265
|
+
/** GET /auth/me — fresh profile of the current user. */
|
|
266
|
+
me: () => Promise<User>;
|
|
267
|
+
/** GET /auth/sessions — active refresh-token sessions with device/IP data. */
|
|
268
|
+
sessions: () => Promise<SessionInfo[]>;
|
|
269
|
+
/** GET /auth/me/activities — recent account activity for the current user. */
|
|
270
|
+
activities: (params?: PageParams) => Promise<Activity[]>;
|
|
271
|
+
/**
|
|
272
|
+
* Revokes a single session by id (e.g. one entry from `sessions()`),
|
|
273
|
+
* signing that device out without affecting the current one.
|
|
274
|
+
*
|
|
275
|
+
* ⚠️ Not directly confirmed against the published API reference at the
|
|
276
|
+
* time this SDK was written — `DELETE /auth/sessions/{id}` follows the
|
|
277
|
+
* REST convention the rest of the documented API uses, but verify it
|
|
278
|
+
* against the Authyon dashboard/API reference before relying on it. If
|
|
279
|
+
* the endpoint differs, override via a raw call to your own backend.
|
|
280
|
+
*/
|
|
281
|
+
revokeSession: (sessionId: string) => Promise<void>;
|
|
282
|
+
/** POST /auth/password-reset/request — always resolves (no account enumeration). */
|
|
283
|
+
requestPasswordReset: (email: string) => Promise<void>;
|
|
284
|
+
/** POST /auth/password-reset/confirm — sets a new password and revokes all refresh tokens. */
|
|
285
|
+
confirmPasswordReset: (token: string, newPassword: string) => Promise<void>;
|
|
286
|
+
};
|
|
287
|
+
readonly organization: {
|
|
288
|
+
/** GET /auth/tenants — all organization memberships. */
|
|
289
|
+
list: () => Promise<Organization[]>;
|
|
290
|
+
/**
|
|
291
|
+
* POST /auth/tenants — creates an organization owned by the signed-in
|
|
292
|
+
* user (only available when self-service organization creation is
|
|
293
|
+
* enabled for the environment).
|
|
294
|
+
*/
|
|
295
|
+
create: (params?: CreateOrganizationParams) => Promise<Organization>;
|
|
296
|
+
/** GET /auth/tenants/{organizationId} — fetch one of the user's organizations by id. */
|
|
297
|
+
get: (organizationId: string) => Promise<Organization>;
|
|
298
|
+
/**
|
|
299
|
+
* PATCH /auth/tenants/{organizationId} — renames the organization.
|
|
300
|
+
* Requires the `tenants:manage` custom permission on it.
|
|
301
|
+
*/
|
|
302
|
+
rename: (organizationId: string, name: string) => Promise<Organization>;
|
|
303
|
+
/** POST /auth/switch-tenant — issues a fresh token scoped to the new organization. */
|
|
304
|
+
switch: (organizationSlug: string) => Promise<Session>;
|
|
305
|
+
/** The organization the current session is scoped to, from the cached session — no network call. */
|
|
306
|
+
current: () => Organization | null;
|
|
307
|
+
members: {
|
|
308
|
+
/** GET /auth/tenants/{organizationId}/members — list an organization's members. */
|
|
309
|
+
list: (organizationId: string, params?: PageParams) => Promise<OrganizationMember[]>;
|
|
310
|
+
/** POST /auth/tenants/{organizationId}/members — invite a member by e-mail. */
|
|
311
|
+
invite: (organizationId: string, params: InviteMemberParams) => Promise<void>;
|
|
312
|
+
/** DELETE /auth/tenants/{organizationId}/members/{userId} — remove a member. */
|
|
313
|
+
remove: (organizationId: string, userId: string) => Promise<void>;
|
|
314
|
+
};
|
|
315
|
+
roles: {
|
|
316
|
+
/** GET /auth/tenants/{organizationId}/roles — roles available in the organization. */
|
|
317
|
+
list: (organizationId: string) => Promise<Role[]>;
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
readonly twoFactor: {
|
|
321
|
+
/** GET /auth/2fa/status — enrolled methods and recovery code count. */
|
|
322
|
+
status: () => Promise<TwoFactorStatus>;
|
|
323
|
+
/** POST /auth/2fa/resend-email — resends the code for an in-flight login challenge. */
|
|
324
|
+
resendEmail: (challengeToken: string) => Promise<void>;
|
|
325
|
+
/** POST /auth/2fa/authenticator/setup — returns secret, QR SVG and otpauth URI. */
|
|
326
|
+
setupAuthenticator: () => Promise<AuthenticatorSetup>;
|
|
327
|
+
/** POST /auth/2fa/authenticator/confirm — returns 10 single-use recovery codes. */
|
|
328
|
+
confirmAuthenticator: (code: string) => Promise<{
|
|
329
|
+
recoveryCodes: string[];
|
|
330
|
+
}>;
|
|
331
|
+
/**
|
|
332
|
+
* POST /auth/2fa/email/enable — two-step opt-in for email-based OTP.
|
|
333
|
+
* Call without `code` to receive one by e-mail, then call again with
|
|
334
|
+
* that code to confirm enrolment.
|
|
335
|
+
*/
|
|
336
|
+
enableEmail: (code?: string) => Promise<void>;
|
|
337
|
+
/** POST /auth/2fa/disable — turns off a specific 2FA method (requires current password). */
|
|
338
|
+
disable: (method: TwoFactorMethod, currentPassword: string) => Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* POST /auth/2fa/recovery-codes/regenerate — rotates the 10 single-use
|
|
341
|
+
* recovery codes (requires current password).
|
|
342
|
+
*/
|
|
343
|
+
regenerateRecoveryCodes: (currentPassword: string) => Promise<{
|
|
344
|
+
recoveryCodes: string[];
|
|
345
|
+
}>;
|
|
346
|
+
webauthn: {
|
|
347
|
+
/** POST /auth/2fa/webauthn/register/start — begins passkey enrolment for 2FA. */
|
|
348
|
+
registerStart: () => Promise<WebAuthnCeremonyStart>;
|
|
349
|
+
/** POST /auth/2fa/webauthn/register/finish — finishes passkey enrolment. */
|
|
350
|
+
registerFinish: (ceremonyToken: string, attestationJson: string, nickname?: string) => Promise<WebAuthnCredential>;
|
|
351
|
+
/** GET /auth/2fa/webauthn/credentials — the caller's registered passkeys. */
|
|
352
|
+
credentials: () => Promise<WebAuthnCredential[]>;
|
|
353
|
+
/** PATCH /auth/2fa/webauthn/credentials/{id} — renames a passkey. */
|
|
354
|
+
renameCredential: (id: string, nickname: string) => Promise<WebAuthnCredential>;
|
|
355
|
+
/** DELETE /auth/2fa/webauthn/credentials/{id} — removes a passkey (requires current password). */
|
|
356
|
+
removeCredential: (id: string, currentPassword: string) => Promise<void>;
|
|
357
|
+
/**
|
|
358
|
+
* POST /auth/2fa/webauthn/assertion/start — fetches WebAuthn assertion
|
|
359
|
+
* options for an in-flight login challenge (2FA method `"webauthn"`).
|
|
360
|
+
*/
|
|
361
|
+
assertionStart: (challengeToken: string) => Promise<WebAuthnCeremonyStart>;
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
/** POST /auth/introspect — lightweight token introspection. */
|
|
365
|
+
introspect(token?: string): Promise<IntrospectResult>;
|
|
366
|
+
/** POST /auth/validate — recommended: cross-checks DB state, returns user + organization. */
|
|
367
|
+
validate(token?: string): Promise<ValidateResult>;
|
|
368
|
+
}
|
|
369
|
+
/** Convenience factory: `const authyon = createClient({ envKey: "pk_live_..." })`. */
|
|
370
|
+
declare function createClient(options: AuthyonClientOptions): AuthyonClient;
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Error thrown for any non-2xx Authyon API response.
|
|
374
|
+
*
|
|
375
|
+
* The API uses RFC 7807 problem+json: `{ title, status, detail, code }`.
|
|
376
|
+
* Match on the machine-readable `code` (e.g. `user.email_taken`), never on `title`.
|
|
377
|
+
*/
|
|
378
|
+
declare class AuthyonError extends Error {
|
|
379
|
+
readonly status: number;
|
|
380
|
+
readonly code: string;
|
|
381
|
+
readonly title: string;
|
|
382
|
+
readonly detail?: string;
|
|
383
|
+
constructor(status: number, body: Partial<{
|
|
384
|
+
title: string;
|
|
385
|
+
detail: string;
|
|
386
|
+
code: string;
|
|
387
|
+
}>);
|
|
388
|
+
is(code: string): boolean;
|
|
389
|
+
}
|
|
390
|
+
/** Well-known error codes documented by Authyon. */
|
|
391
|
+
declare const ErrorCodes: {
|
|
392
|
+
readonly EmailTaken: "user.email_taken";
|
|
393
|
+
readonly PasswordWeak: "user.password_weak";
|
|
394
|
+
readonly PasswordPwned: "user.password_pwned";
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
/** Keeps the session in memory only (lost on page reload). */
|
|
398
|
+
declare function memoryStorage(): TokenStorage;
|
|
399
|
+
/** Persists the session in `localStorage` under a namespaced key. */
|
|
400
|
+
declare function localStorageAdapter(key?: string): TokenStorage;
|
|
401
|
+
declare function defaultStorage(): TokenStorage;
|
|
402
|
+
|
|
403
|
+
export { type Activity, type AuthEvent, type AuthStateListener, type AuthenticatorSetup, AuthyonClient, type AuthyonClientOptions, AuthyonError, type CreateOrganizationParams, ErrorCodes, type IntrospectResult, type InviteMemberParams, type LoginParams, type LoginResult, type Organization, type OrganizationMember, type PageParams, type RegisterParams, type Role, type Session, type SessionInfo, type SsoProvider, type TokenStorage, type TwoFactorChallenge, type TwoFactorMethod, type TwoFactorStatus, type TwoFactorVerifyParams, type User, type ValidateResult, type WebAuthnAssertion, type WebAuthnCeremonyStart, type WebAuthnCredential, createClient, defaultStorage, localStorageAdapter, memoryStorage };
|