@authon/js 0.3.0 → 0.3.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/README.md CHANGED
@@ -2,459 +2,292 @@
2
2
 
3
3
  # @authon/js
4
4
 
5
+ > Drop-in browser authentication SDK — self-hosted Clerk alternative, Auth0 alternative, open-source auth
6
+
5
7
  [![npm version](https://img.shields.io/npm/v/@authon/js?color=6d28d9)](https://www.npmjs.com/package/@authon/js)
6
8
  [![License](https://img.shields.io/badge/license-MIT-blue)](../../LICENSE)
7
9
 
8
- Core JavaScript SDK for [Authon](https://authon.dev). Works in any browser environment — no framework required.
10
+ ## Prerequisites
11
+
12
+ Before installing the SDK, create an Authon project and get your API keys:
13
+
14
+ 1. **Create a project** at [Authon Dashboard](https://authon.dev/dashboard/overview)
15
+ - Click "Create Project" and enter your app name
16
+ - Select the authentication methods you want (Email/Password, OAuth providers, etc.)
17
+
18
+ 2. **Get your API keys** from Project Settings → API Keys
19
+ - **Publishable Key** (`pk_live_...` or `pk_test_...`) — safe to use in client-side code
20
+ - **Secret Key** (`sk_live_...` or `sk_test_...`) — server-side only, never expose to clients
9
21
 
10
- Includes a built-in ShadowDOM sign-in modal, OAuth popup/redirect flows, passwordless auth, passkeys (WebAuthn), Web3 wallet login, TOTP-based MFA, and session management.
22
+ 3. **Configure OAuth providers** (optional) in Project Settings OAuth
23
+ - Add Google, Apple, GitHub, etc. with their respective Client ID and Secret
24
+ - Set the redirect URL to `https://api.authon.dev/v1/auth/oauth/redirect`
11
25
 
12
- ## Installation
26
+ > **Test vs Live keys:** Use `pk_test_...` during development. Switch to `pk_live_...` before deploying to production. Test keys use a sandbox environment with no rate limits.
27
+
28
+ ## Install
13
29
 
14
30
  ```bash
15
31
  npm install @authon/js
16
- # or
17
- pnpm add @authon/js
18
32
  ```
19
33
 
20
- ## Initialization
21
-
22
- ```ts
23
- import { Authon } from '@authon/js';
24
-
25
- const authon = new Authon('pk_live_...');
34
+ ## Quick Start
35
+
36
+ ```html
37
+ <!-- index.html -->
38
+ <!DOCTYPE html>
39
+ <html>
40
+ <head><title>My App</title></head>
41
+ <body>
42
+ <button id="sign-in-btn">Sign In</button>
43
+ <div id="user-info"></div>
44
+
45
+ <script type="module">
46
+ import { Authon } from '@authon/js';
47
+
48
+ const authon = new Authon('pk_live_YOUR_PUBLISHABLE_KEY', {
49
+ apiUrl: 'https://your-authon-server.com',
50
+ });
51
+
52
+ document.getElementById('sign-in-btn').addEventListener('click', () => {
53
+ authon.openSignIn();
54
+ });
55
+
56
+ authon.on('signedIn', (user) => {
57
+ document.getElementById('user-info').textContent = `Hello, ${user.email}`;
58
+ document.getElementById('sign-in-btn').style.display = 'none';
59
+ });
60
+ </script>
61
+ </body>
62
+ </html>
26
63
  ```
27
64
 
28
- With options:
65
+ ## Common Tasks
66
+
67
+ ### Add Google OAuth Login
29
68
 
30
69
  ```ts
31
- const authon = new Authon('pk_live_...', {
32
- apiUrl: 'https://api.authon.dev', // default
33
- mode: 'popup', // 'popup' | 'embedded'
34
- theme: 'auto', // 'light' | 'dark' | 'auto'
35
- locale: 'en',
36
- containerId: 'auth-container', // element ID for embedded mode
37
- appearance: { // override project branding
38
- brandName: 'My App',
39
- primaryColorStart: '#7c3aed',
40
- primaryColorEnd: '#4f46e5',
41
- borderRadius: 12,
42
- },
43
- });
44
- ```
70
+ import { Authon } from '@authon/js';
45
71
 
46
- ### Configuration Options
72
+ const authon = new Authon('pk_live_YOUR_PUBLISHABLE_KEY', {
73
+ apiUrl: 'https://your-authon-server.com',
74
+ });
47
75
 
48
- | Option | Type | Default | Description |
49
- |--------|------|---------|-------------|
50
- | `apiUrl` | `string` | `https://api.authon.dev` | Authon API base URL |
51
- | `mode` | `'popup' \| 'embedded'` | `'popup'` | Modal display mode |
52
- | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | UI theme |
53
- | `locale` | `string` | `'en'` | UI locale |
54
- | `containerId` | `string` | — | Element ID for embedded mode |
55
- | `appearance` | `Partial<BrandingConfig>` | — | Override branding from dashboard |
76
+ // Opens popup, falls back to redirect if blocked
77
+ await authon.signInWithOAuth('google');
56
78
 
57
- ## Built-in Modal
79
+ // Force redirect mode
80
+ await authon.signInWithOAuth('google', { flowMode: 'redirect' });
58
81
 
59
- ```ts
60
- // Open the Authon-hosted sign-in / sign-up modal
61
- await authon.openSignIn();
62
- await authon.openSignUp();
82
+ // Supported providers: google, apple, github, discord, facebook,
83
+ // microsoft, kakao, naver, line, x
63
84
  ```
64
85
 
65
- The modal renders inside a ShadowRoot, preventing CSS conflicts with your app. Branding is fetched from your Authon project settings and can be overridden via `appearance`.
66
-
67
- ## Email / Password
86
+ ### Add Email/Password Auth
68
87
 
69
88
  ```ts
70
- // Sign up a new user
71
- const user = await authon.signUpWithEmail('user@example.com', 'password', {
89
+ import { Authon } from '@authon/js';
90
+
91
+ const authon = new Authon('pk_live_YOUR_PUBLISHABLE_KEY', {
92
+ apiUrl: 'https://your-authon-server.com',
93
+ });
94
+
95
+ // Sign up
96
+ const user = await authon.signUpWithEmail('user@example.com', 'MyP@ssw0rd', {
72
97
  displayName: 'Alice',
73
98
  });
74
99
 
75
100
  // Sign in
76
- const user = await authon.signInWithEmail('user@example.com', 'password');
77
-
78
- // Sign out
79
- await authon.signOut();
101
+ const user = await authon.signInWithEmail('user@example.com', 'MyP@ssw0rd');
80
102
  ```
81
103
 
82
- ## OAuth
104
+ ### Get Current User
83
105
 
84
106
  ```ts
85
- // Sign in with any supported provider
86
- await authon.signInWithOAuth('google');
87
- await authon.signInWithOAuth('apple');
88
- await authon.signInWithOAuth('github');
89
- await authon.signInWithOAuth('discord');
90
- await authon.signInWithOAuth('facebook');
91
- await authon.signInWithOAuth('microsoft');
92
- await authon.signInWithOAuth('kakao');
93
- await authon.signInWithOAuth('naver');
94
- await authon.signInWithOAuth('line');
95
- await authon.signInWithOAuth('x');
96
-
97
- // Override the flow mode per call
98
- await authon.signInWithOAuth('google', { flowMode: 'popup' });
99
- await authon.signInWithOAuth('google', { flowMode: 'redirect' });
100
- await authon.signInWithOAuth('google', { flowMode: 'auto' }); // default
101
- ```
107
+ // Synchronous no network request
108
+ const user = authon.getUser();
109
+ // { id, email, displayName, avatarUrl, emailVerified, ... }
102
110
 
103
- The `auto` mode opens a popup and automatically falls back to a redirect if the popup is blocked.
111
+ const token = authon.getToken();
112
+ // Use token for authenticated API calls
113
+ ```
104
114
 
105
- ## Passwordless
115
+ ### Open Built-in Sign-In Modal
106
116
 
107
117
  ```ts
108
- // Magic linksends a sign-in link to the user's email
109
- await authon.sendMagicLink('user@example.com');
110
-
111
- // Email OTP — sends a one-time code to the user's email
112
- await authon.sendEmailOtp('user@example.com');
118
+ // ShadowDOM modalno CSS conflicts with your app
119
+ await authon.openSignIn();
120
+ await authon.openSignUp();
121
+ ```
113
122
 
114
- // Verify magic link (token comes from URL query param after user clicks link)
115
- const user = await authon.verifyPasswordless({ token: 'token-from-url' });
123
+ ### Handle Sign Out
116
124
 
117
- // Verify email OTP
118
- const user = await authon.verifyPasswordless({
119
- email: 'user@example.com',
120
- code: '123456',
121
- });
125
+ ```ts
126
+ await authon.signOut();
122
127
  ```
123
128
 
124
- ## Passkeys (WebAuthn)
129
+ ### Add Passkey (WebAuthn) Login
125
130
 
126
131
  ```ts
127
- // Register a new passkey user must be signed in
132
+ // Register passkey (user must be signed in)
128
133
  const credential = await authon.registerPasskey('My MacBook');
129
- // credential: { id, name, createdAt, lastUsedAt }
130
134
 
131
- // Authenticate with a passkey (works before sign-in)
135
+ // Sign in with passkey
132
136
  const user = await authon.authenticateWithPasskey();
133
-
134
- // Restrict to passkeys registered for a specific email
135
- const user = await authon.authenticateWithPasskey('user@example.com');
136
-
137
- // List registered passkeys
138
- const passkeys = await authon.listPasskeys();
139
- // [{ id, name, createdAt, lastUsedAt }, ...]
140
-
141
- // Rename a passkey
142
- const updated = await authon.renamePasskey(passkeys[0].id, 'Work Laptop');
143
-
144
- // Revoke (delete) a passkey
145
- await authon.revokePasskey(passkeys[0].id);
146
137
  ```
147
138
 
148
- ## Web3
139
+ ### Add Web3 Wallet Login (MetaMask)
149
140
 
150
141
  ```ts
151
- // Step 1: Request a sign-in nonce for a wallet address
152
- const { message, nonce } = await authon.web3GetNonce(
153
- '0xAbc...123', // wallet address
154
- 'evm', // 'evm' | 'solana'
155
- 'metamask', // wallet type
156
- 1, // chainId (optional, for EVM)
157
- );
158
-
159
- // Step 2: Sign the message with the wallet (MetaMask example)
142
+ const { message } = await authon.web3GetNonce('0xAbc...', 'evm', 'metamask', 1);
160
143
  const signature = await window.ethereum.request({
161
144
  method: 'personal_sign',
162
- params: [message, '0xAbc...123'],
145
+ params: [message, '0xAbc...'],
163
146
  });
164
-
165
- // Step 3: Verify the signature to sign in
166
- const user = await authon.web3Verify(
167
- message,
168
- signature,
169
- '0xAbc...123',
170
- 'evm',
171
- 'metamask',
172
- );
173
-
174
- // Solana (Phantom) example
175
- const { message } = await authon.web3GetNonce(
176
- phantomPublicKey.toString(),
177
- 'solana',
178
- 'phantom',
179
- );
180
- const encodedMessage = new TextEncoder().encode(message);
181
- const { signature } = await window.solana.signMessage(encodedMessage, 'utf8');
182
- const user = await authon.web3Verify(
183
- message,
184
- bs58.encode(signature),
185
- phantomPublicKey.toString(),
186
- 'solana',
187
- 'phantom',
188
- );
189
-
190
- // Link an additional wallet to the signed-in account
191
- const wallet = await authon.linkWallet({
192
- address: '0xDef...456',
193
- chain: 'evm',
194
- walletType: 'walletconnect',
195
- chainId: 1,
196
- message,
197
- signature,
198
- });
199
- // wallet: { id, address, chain, walletType, chainId, createdAt }
200
-
201
- // List linked wallets
202
- const wallets = await authon.listWallets();
203
-
204
- // Unlink a wallet
205
- await authon.unlinkWallet(wallets[0].id);
147
+ const user = await authon.web3Verify(message, signature, '0xAbc...', 'evm', 'metamask');
206
148
  ```
207
149
 
208
- **Supported wallet types:** `'metamask'` | `'pexus'` | `'walletconnect'` | `'coinbase'` | `'phantom'` | `'trust'` | `'other'`
209
-
210
- **Supported chains:** `'evm'` | `'solana'`
211
-
212
- ## Multi-Factor Authentication (MFA)
213
-
214
- Authon supports TOTP-based MFA compatible with Google Authenticator, Authy, and any other authenticator app.
215
-
216
- ### Setup
150
+ ### Add MFA (TOTP)
217
151
 
218
152
  ```ts
219
- import { Authon } from '@authon/js';
153
+ import { Authon, AuthonMfaRequiredError } from '@authon/js';
220
154
 
221
- // User must be signed in before calling setupMfa
155
+ // Setup MFA (user must be signed in)
222
156
  const setup = await authon.setupMfa();
223
- // setup.qrCodeSvg — inline SVG string, render with innerHTML or as <img src>
224
- // setup.qrCodeUri — otpauth:// URI
225
- // setup.secret — raw TOTP secret
226
- // setup.backupCodes — one-time recovery codes (save these!)
227
-
228
- // Render the QR code
229
- document.querySelector('#qr-container').innerHTML = setup.qrCodeSvg;
230
-
231
- // User scans QR code, then enters the 6-digit code to confirm setup
232
- await authon.verifyMfaSetup('123456');
233
- ```
234
-
235
- ### Sign-In With MFA
236
-
237
- When MFA is enabled, `signInWithEmail` throws `AuthonMfaRequiredError`:
238
-
239
- ```ts
240
- import { Authon, AuthonMfaRequiredError } from '@authon/js';
157
+ document.getElementById('qr').innerHTML = setup.qrCodeSvg;
158
+ await authon.verifyMfaSetup('123456'); // code from authenticator app
241
159
 
160
+ // Sign in with MFA
242
161
  try {
243
162
  await authon.signInWithEmail('user@example.com', 'password');
244
163
  } catch (err) {
245
164
  if (err instanceof AuthonMfaRequiredError) {
246
- // Prompt the user for their TOTP code
247
165
  const user = await authon.verifyMfa(err.mfaToken, '123456');
248
166
  }
249
167
  }
250
168
  ```
251
169
 
252
- Alternatively, use the event listener:
170
+ ### Listen to Auth Events
253
171
 
254
172
  ```ts
255
- authon.on('mfaRequired', async (mfaToken) => {
256
- const code = prompt('Enter your authenticator code');
257
- if (code) await authon.verifyMfa(mfaToken, code);
258
- });
173
+ authon.on('signedIn', (user) => console.log('Signed in:', user.email));
174
+ authon.on('signedOut', () => console.log('Signed out'));
175
+ authon.on('error', (err) => console.error(err.message));
176
+ authon.on('mfaRequired', (mfaToken) => { /* show MFA dialog */ });
177
+ authon.on('tokenRefreshed', (token) => { /* update API client */ });
259
178
  ```
260
179
 
261
- ### MFA Management
180
+ ## Environment Variables
262
181
 
263
- ```ts
264
- // Check current MFA status
265
- const status = await authon.getMfaStatus();
266
- // { enabled: true, backupCodesRemaining: 8 }
267
-
268
- // Disable MFA (requires a valid TOTP code or backup code)
269
- await authon.disableMfa('123456');
182
+ | Variable | Required | Description |
183
+ |----------|----------|-------------|
184
+ | `AUTHON_API_URL` | Yes | Your Authon server URL (e.g. `https://your-authon-server.com`) |
185
+ | `AUTHON_PUBLISHABLE_KEY` | Yes | Project publishable key (`pk_live_...` or `pk_test_...`) |
270
186
 
271
- // Regenerate backup codes (requires a valid TOTP code)
272
- const newCodes = await authon.regenerateBackupCodes('123456');
273
- // ['XXXX-XXXX', 'XXXX-XXXX', ...]
274
- ```
187
+ ## API Reference
275
188
 
276
- ## User Profile
189
+ ### Constructor
277
190
 
278
191
  ```ts
279
- // Get the currently signed-in user (synchronous, no network request)
280
- const user = authon.getUser();
281
- // {
282
- // id, projectId, email, displayName, avatarUrl, phone,
283
- // emailVerified, phoneVerified, isBanned,
284
- // publicMetadata, lastSignInAt, signInCount, createdAt, updatedAt
285
- // }
286
-
287
- // Get the current access token (synchronous)
288
- const token = authon.getToken();
289
-
290
- // Update profile fields
291
- const updated = await authon.updateProfile({
292
- displayName: 'Alice Smith',
293
- avatarUrl: 'https://example.com/avatar.png',
294
- phone: '+12025551234',
295
- publicMetadata: { plan: 'pro', referralCode: 'ABC123' },
296
- });
192
+ new Authon(publishableKey: string, config?: AuthonConfig)
297
193
  ```
298
194
 
299
- ## Session Management
300
-
301
- ```ts
302
- // List all active sessions for the signed-in user
303
- const sessions = await authon.listSessions();
304
- // [{ id, ipAddress, userAgent, createdAt, lastActiveAt }, ...]
305
-
306
- // Revoke a specific session (e.g., sign out another device)
307
- await authon.revokeSession(sessions[0].id);
308
- ```
309
-
310
- ## Events
311
-
312
- `on()` returns an unsubscribe function.
313
-
314
- ```ts
315
- // User signed in (after any auth method)
316
- const off = authon.on('signedIn', (user) => {
317
- console.log('Signed in as', user.email);
318
- });
319
-
320
- // User signed out
321
- authon.on('signedOut', () => {
322
- console.log('Signed out');
323
- });
324
-
325
- // Access token was silently refreshed
326
- authon.on('tokenRefreshed', (token) => {
327
- // update token in your API client if needed
328
- });
329
-
330
- // MFA step required after email/password sign-in
331
- authon.on('mfaRequired', (mfaToken) => {
332
- showMfaDialog(mfaToken);
333
- });
334
-
335
- // A new passkey was registered
336
- authon.on('passkeyRegistered', (credential) => {
337
- console.log('Passkey registered:', credential.name);
338
- });
339
-
340
- // A Web3 wallet was linked
341
- authon.on('web3Connected', (wallet) => {
342
- console.log('Wallet linked:', wallet.address, 'on', wallet.chain);
343
- });
344
-
345
- // An error occurred
346
- authon.on('error', (error) => {
347
- console.error('Authon error:', error.message);
348
- });
349
-
350
- // Unsubscribe
351
- off();
352
- ```
353
-
354
- ### Event Reference
355
-
356
- | Event | Payload | Trigger |
357
- |-------|---------|---------|
358
- | `signedIn` | `AuthonUser` | Any successful sign-in |
359
- | `signedOut` | — | `signOut()` called |
360
- | `tokenRefreshed` | `string` | Access token silently refreshed |
361
- | `mfaRequired` | `string` (mfaToken) | MFA required after password sign-in |
362
- | `passkeyRegistered` | `PasskeyCredential` | `registerPasskey()` completed |
363
- | `web3Connected` | `Web3Wallet` | `linkWallet()` completed |
364
- | `error` | `Error` | Any error during auth flows |
365
-
366
- ## Full API Reference
195
+ | Config Option | Type | Default | Description |
196
+ |--------------|------|---------|-------------|
197
+ | `apiUrl` | `string` | `https://api.authon.dev` | API base URL |
198
+ | `mode` | `'popup' \| 'embedded'` | `'popup'` | Modal display mode |
199
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'auto'` | UI theme |
200
+ | `locale` | `string` | `'en'` | UI locale |
201
+ | `containerId` | `string` | -- | Element ID for embedded mode |
202
+ | `appearance` | `Partial<BrandingConfig>` | -- | Override branding |
367
203
 
368
204
  ### Auth Methods
369
205
 
370
- | Method | Returns | Description |
371
- |--------|---------|-------------|
372
- | `openSignIn()` | `Promise<void>` | Open the built-in sign-in modal |
373
- | `openSignUp()` | `Promise<void>` | Open the built-in sign-up modal |
374
- | `signInWithEmail(email, password)` | `Promise<AuthonUser>` | Sign in with email and password |
375
- | `signUpWithEmail(email, password, meta?)` | `Promise<AuthonUser>` | Register a new account |
376
- | `signInWithOAuth(provider, options?)` | `Promise<void>` | Start an OAuth flow |
377
- | `signOut()` | `Promise<void>` | Sign out and clear session |
378
- | `sendMagicLink(email)` | `Promise<void>` | Send a magic link to email |
379
- | `sendEmailOtp(email)` | `Promise<void>` | Send an OTP code to email |
380
- | `verifyPasswordless(options)` | `Promise<AuthonUser>` | Verify magic link token or OTP code |
381
-
382
- ### User & Session
383
-
384
- | Method | Returns | Description |
385
- |--------|---------|-------------|
386
- | `getUser()` | `AuthonUser \| null` | Get current user (synchronous) |
387
- | `getToken()` | `string \| null` | Get current access token (synchronous) |
388
- | `updateProfile(data)` | `Promise<AuthonUser>` | Update displayName, avatarUrl, phone, publicMetadata |
389
- | `listSessions()` | `Promise<SessionInfo[]>` | List all active sessions |
390
- | `revokeSession(sessionId)` | `Promise<void>` | Revoke a session by ID |
391
-
392
- ### MFA
393
-
394
- | Method | Returns | Description |
395
- |--------|---------|-------------|
396
- | `setupMfa()` | `Promise<MfaSetupResponse & { qrCodeSvg: string }>` | Begin MFA setup |
397
- | `verifyMfaSetup(code)` | `Promise<void>` | Confirm setup with TOTP code |
398
- | `verifyMfa(mfaToken, code)` | `Promise<AuthonUser>` | Complete sign-in with TOTP code |
399
- | `getMfaStatus()` | `Promise<MfaStatus>` | Get MFA enabled state and backup code count |
400
- | `disableMfa(code)` | `Promise<void>` | Disable MFA |
401
- | `regenerateBackupCodes(code)` | `Promise<string[]>` | Generate new backup codes |
402
-
403
- ### Passkeys
404
-
405
- | Method | Returns | Description |
406
- |--------|---------|-------------|
407
- | `registerPasskey(name?)` | `Promise<PasskeyCredential>` | Register a new passkey |
408
- | `authenticateWithPasskey(email?)` | `Promise<AuthonUser>` | Sign in with a passkey |
409
- | `listPasskeys()` | `Promise<PasskeyCredential[]>` | List registered passkeys |
410
- | `renamePasskey(id, name)` | `Promise<PasskeyCredential>` | Rename a passkey |
411
- | `revokePasskey(id)` | `Promise<void>` | Delete a passkey |
206
+ | Method | Returns |
207
+ |--------|---------|
208
+ | `openSignIn()` | `Promise<void>` |
209
+ | `openSignUp()` | `Promise<void>` |
210
+ | `signInWithEmail(email, password)` | `Promise<AuthonUser>` |
211
+ | `signUpWithEmail(email, password, meta?)` | `Promise<AuthonUser>` |
212
+ | `signInWithOAuth(provider, options?)` | `Promise<void>` |
213
+ | `signOut()` | `Promise<void>` |
214
+ | `getUser()` | `AuthonUser \| null` |
215
+ | `getToken()` | `string \| null` |
216
+
217
+ ### Passwordless
218
+
219
+ | Method | Returns |
220
+ |--------|---------|
221
+ | `sendMagicLink(email)` | `Promise<void>` |
222
+ | `sendEmailOtp(email)` | `Promise<void>` |
223
+ | `verifyPasswordless({ token?, email?, code? })` | `Promise<AuthonUser>` |
224
+
225
+ ### Passkeys (WebAuthn)
226
+
227
+ | Method | Returns |
228
+ |--------|---------|
229
+ | `registerPasskey(name?)` | `Promise<PasskeyCredential>` |
230
+ | `authenticateWithPasskey(email?)` | `Promise<AuthonUser>` |
231
+ | `listPasskeys()` | `Promise<PasskeyCredential[]>` |
232
+ | `renamePasskey(id, name)` | `Promise<PasskeyCredential>` |
233
+ | `revokePasskey(id)` | `Promise<void>` |
412
234
 
413
235
  ### Web3
414
236
 
415
- | Method | Returns | Description |
416
- |--------|---------|-------------|
417
- | `web3GetNonce(address, chain, walletType, chainId?)` | `Promise<Web3NonceResponse>` | Get sign-in message and nonce |
418
- | `web3Verify(message, signature, address, chain, walletType)` | `Promise<AuthonUser>` | Verify wallet signature and sign in |
419
- | `listWallets()` | `Promise<Web3Wallet[]>` | List linked wallets |
420
- | `linkWallet(params)` | `Promise<Web3Wallet>` | Link an additional wallet |
421
- | `unlinkWallet(walletId)` | `Promise<void>` | Remove a linked wallet |
422
-
423
- ### Lifecycle
424
-
425
- | Method | Returns | Description |
426
- |--------|---------|-------------|
427
- | `on(event, listener)` | `() => void` | Subscribe to an event, returns unsubscribe fn |
428
- | `getProviders()` | `Promise<OAuthProviderType[]>` | List OAuth providers enabled for the project |
429
- | `destroy()` | `void` | Clean up all listeners and resources |
237
+ | Method | Returns |
238
+ |--------|---------|
239
+ | `web3GetNonce(address, chain, walletType, chainId?)` | `Promise<Web3NonceResponse>` |
240
+ | `web3Verify(message, signature, address, chain, walletType)` | `Promise<AuthonUser>` |
241
+ | `listWallets()` | `Promise<Web3Wallet[]>` |
242
+ | `linkWallet(params)` | `Promise<Web3Wallet>` |
243
+ | `unlinkWallet(walletId)` | `Promise<void>` |
430
244
 
431
- ## TypeScript
432
-
433
- The SDK ships with full type declarations. Key types are exported from `@authon/shared`:
434
-
435
- ```ts
436
- import type {
437
- AuthonUser,
438
- AuthTokens,
439
- MfaSetupResponse,
440
- MfaStatus,
441
- PasskeyCredential,
442
- Web3Wallet,
443
- Web3NonceResponse,
444
- SessionInfo,
445
- Web3Chain,
446
- Web3WalletType,
447
- OAuthProviderType,
448
- } from '@authon/shared';
449
-
450
- import type { AuthonConfig, AuthonEventType } from '@authon/js';
451
- import { Authon, AuthonMfaRequiredError } from '@authon/js';
452
- ```
453
-
454
- ## Documentation
245
+ ### MFA
455
246
 
456
- Full documentation: [docs.authon.dev](https://docs.authon.dev)
247
+ | Method | Returns |
248
+ |--------|---------|
249
+ | `setupMfa()` | `Promise<MfaSetupResponse & { qrCodeSvg }>` |
250
+ | `verifyMfaSetup(code)` | `Promise<void>` |
251
+ | `verifyMfa(mfaToken, code)` | `Promise<AuthonUser>` |
252
+ | `getMfaStatus()` | `Promise<MfaStatus>` |
253
+ | `disableMfa(code)` | `Promise<void>` |
254
+ | `regenerateBackupCodes(code)` | `Promise<string[]>` |
255
+
256
+ ### Organizations
257
+
258
+ | Method | Returns |
259
+ |--------|---------|
260
+ | `organizations.list()` | `Promise<OrganizationListResponse>` |
261
+ | `organizations.create(params)` | `Promise<AuthonOrganization>` |
262
+ | `organizations.get(orgId)` | `Promise<AuthonOrganization>` |
263
+ | `organizations.update(orgId, params)` | `Promise<AuthonOrganization>` |
264
+ | `organizations.delete(orgId)` | `Promise<void>` |
265
+ | `organizations.invite(orgId, params)` | `Promise<OrganizationInvitation>` |
266
+
267
+ ### Events
268
+
269
+ | Event | Payload |
270
+ |-------|---------|
271
+ | `signedIn` | `AuthonUser` |
272
+ | `signedOut` | -- |
273
+ | `tokenRefreshed` | `string` |
274
+ | `mfaRequired` | `string` (mfaToken) |
275
+ | `passkeyRegistered` | `PasskeyCredential` |
276
+ | `web3Connected` | `Web3Wallet` |
277
+ | `error` | `Error` |
278
+
279
+ ## Comparison
280
+
281
+ | Feature | Authon | Clerk | Auth.js |
282
+ |---------|--------|-------|---------|
283
+ | Self-hosted | Yes | No | Partial |
284
+ | Pricing | Free | $25/mo+ | Free |
285
+ | OAuth providers | 10+ | 20+ | 80+ |
286
+ | ShadowDOM modal | Yes | No | No |
287
+ | MFA/Passkeys | Yes | Yes | Plugin |
288
+ | Web3 auth | Yes | No | No |
289
+ | Organizations | Yes | Yes | No |
457
290
 
458
291
  ## License
459
292
 
460
- [MIT](../../LICENSE)
293
+ MIT