authula 0.2.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/LICENSE +201 -0
- package/README.md +627 -0
- package/dist/fetch-B4O1awi2.js +124 -0
- package/dist/fetch-B4O1awi2.js.map +1 -0
- package/dist/fetch-q98rEoAp.cjs +159 -0
- package/dist/fetch-q98rEoAp.cjs.map +1 -0
- package/dist/index.cjs +60 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.cjs +388 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.d.cts +417 -0
- package/dist/plugins/index.d.ts +417 -0
- package/dist/plugins/index.js +377 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/sdk-BWoai6MP.d.ts +163 -0
- package/dist/sdk-DV73pbRH.d.cts +163 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
|
|
2
|
+
<p align="center">
|
|
3
|
+
<img src="./project-logo.png" width="200" />
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
This Node.js SDK provides seamless integration with an Authula server for both client-side and server-side applications and is framework agnostic.
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Framework Agnostic**: Works with Next.js/React, Vue.js and more
|
|
15
|
+
- **Full TypeScript Support**: Complete TypeScript definitions with strict typing
|
|
16
|
+
- **SSR Safe**: Supports proper cookie handling for SSR apps
|
|
17
|
+
- **CSRF Protection**: Automatic CSRF token handling for mutating requests
|
|
18
|
+
- **Multiple Auth Methods**: Email/password, OAuth2, JWT-based authentication
|
|
19
|
+
- **Plugin Architecture**: Extensible plugin system for custom authentication flows
|
|
20
|
+
- **Automatic Token Refresh**: Built-in bearer token refresh mechanism
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install authula
|
|
26
|
+
# or
|
|
27
|
+
yarn add authula
|
|
28
|
+
# or
|
|
29
|
+
pnpm add authula
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### Basic Setup
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { createClient } from "authula";
|
|
38
|
+
import { EmailPasswordPlugin } from "authula/plugins";
|
|
39
|
+
|
|
40
|
+
// Create a client instance
|
|
41
|
+
const authulaClient = createClient({
|
|
42
|
+
// Your Authula server URL
|
|
43
|
+
url: "http://localhost:8080/auth",
|
|
44
|
+
plugins: [new EmailPasswordPlugin()],
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Now you can use the client to perform authentication operations
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Using with Cookies (SSR Compatible)
|
|
51
|
+
|
|
52
|
+
For server-side rendering or applications that need to handle cookies properly:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { cookies } from "next/headers";
|
|
56
|
+
|
|
57
|
+
import { createClient } from "authula";
|
|
58
|
+
import { EmailPasswordPlugin, CSRFPlugin } from "authula/plugins";
|
|
59
|
+
|
|
60
|
+
const authulaClient = createClient({
|
|
61
|
+
url: "http://localhost:8080/auth",
|
|
62
|
+
cookies: cookies, // Provide cookie store for SSR
|
|
63
|
+
plugins: [
|
|
64
|
+
new EmailPasswordPlugin(),
|
|
65
|
+
new CSRFPlugin({
|
|
66
|
+
cookieName: "authula_csrf_token",
|
|
67
|
+
headerName: "X-AUTHULA-CSRF-TOKEN",
|
|
68
|
+
}),
|
|
69
|
+
],
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Core Client Methods
|
|
74
|
+
|
|
75
|
+
The client provides built-in methods for essential authentication operations:
|
|
76
|
+
|
|
77
|
+
### Get Current User
|
|
78
|
+
|
|
79
|
+
Retrieve information about the currently authenticated user:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const { user, session } = await authulaClient.getMe();
|
|
83
|
+
|
|
84
|
+
console.log(user.email);
|
|
85
|
+
console.log(session.id);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Sign Out
|
|
89
|
+
|
|
90
|
+
Sign out the current user or all sessions:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Sign out current session
|
|
94
|
+
await authulaClient.signOut({});
|
|
95
|
+
|
|
96
|
+
// Sign out all sessions
|
|
97
|
+
await authulaClient.signOut({
|
|
98
|
+
signOutAll: true,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Sign out a specific session
|
|
102
|
+
await authulaClient.signOut({
|
|
103
|
+
sessionId: "session-id",
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Get Plugin Instance
|
|
108
|
+
|
|
109
|
+
Access a plugin instance programmatically:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const emailPasswordPlugin = authulaClient.getPlugin("emailPassword");
|
|
113
|
+
|
|
114
|
+
// Use the plugin
|
|
115
|
+
if (emailPasswordPlugin) {
|
|
116
|
+
// Plugin methods are now available
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Available Plugins
|
|
121
|
+
|
|
122
|
+
### Access Control Plugin
|
|
123
|
+
|
|
124
|
+
Provides role-based access control (RBAC) management for users, including roles, permissions, and their assignments.
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { AccessControlPlugin } from "authula/plugins";
|
|
128
|
+
|
|
129
|
+
const authulaClient = createClient({
|
|
130
|
+
url: "http://localhost:8080/auth",
|
|
131
|
+
plugins: [new AccessControlPlugin()],
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Role Management
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Create a new role
|
|
139
|
+
await authulaClient.accessControl.createRole({
|
|
140
|
+
name: "Admin",
|
|
141
|
+
description: "Administrator role",
|
|
142
|
+
isSystem: false,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Get all roles
|
|
146
|
+
const allRoles = await authulaClient.accessControl.getAllRoles();
|
|
147
|
+
|
|
148
|
+
// Get a specific role
|
|
149
|
+
const role = await authulaClient.accessControl.getRoleById("role-id");
|
|
150
|
+
|
|
151
|
+
// Update a role
|
|
152
|
+
await authulaClient.accessControl.updateRole("role-id", {
|
|
153
|
+
name: "Updated name",
|
|
154
|
+
description: "Updated description",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Delete a role
|
|
158
|
+
await authulaClient.accessControl.deleteRole("role-id");
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Permission Management
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// Create a new permission
|
|
165
|
+
await authulaClient.accessControl.createPermission({
|
|
166
|
+
key: "users.create",
|
|
167
|
+
description: "Create new users",
|
|
168
|
+
isSystem: false,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Get all permissions
|
|
172
|
+
const allPermissions = await authulaClient.accessControl.getAllPermissions();
|
|
173
|
+
|
|
174
|
+
// Update a permission
|
|
175
|
+
await authulaClient.accessControl.updatePermission("permission-id", {
|
|
176
|
+
description: "Updated permission description",
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Delete a permission
|
|
180
|
+
await authulaClient.accessControl.deletePermission("permission-id");
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Role-Permission Management
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Add a permission to a role
|
|
187
|
+
await authulaClient.accessControl.addRolePermission("role-id", {
|
|
188
|
+
permissionId: "permission-id",
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Get all permissions for a role
|
|
192
|
+
const rolePermissions = await authulaClient.accessControl.getRolePermissions(
|
|
193
|
+
"role-id",
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// Replace all permissions for a role
|
|
197
|
+
await authulaClient.accessControl.replaceRolePermissions("role-id", {
|
|
198
|
+
permissionIds: ["permission-id-1", "permission-id-2", "permission-id-3"],
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Remove a permission from a role
|
|
202
|
+
await authulaClient.accessControl.removeRolePermission(
|
|
203
|
+
"role-id",
|
|
204
|
+
"permission-id",
|
|
205
|
+
);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### User Role Management
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
// Get all roles assigned to a user
|
|
212
|
+
const userRoles = await authulaClient.accessControl.getUserRoles("user-id");
|
|
213
|
+
|
|
214
|
+
// Assign a role to a user
|
|
215
|
+
await authulaClient.accessControl.assignUserRole("user-id", {
|
|
216
|
+
roleId: "role-id",
|
|
217
|
+
expiresAt: new Date("2025-12-31"), // Optional: role expiration date
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Replace all roles for a user
|
|
221
|
+
await authulaClient.accessControl.replaceUserRoles("user-id", {
|
|
222
|
+
roleIds: ["role-id-1", "role-id-2"],
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// Remove a role from a user
|
|
226
|
+
await authulaClient.accessControl.removeUserRole("user-id", "role-id");
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### User Permission Management
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Get all effective permissions for a user (from all assigned roles)
|
|
233
|
+
const userPermissions = await authulaClient.accessControl.getUserEffectivePermissions("user-id");
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
### Admin Plugin
|
|
239
|
+
|
|
240
|
+
Provides the ability to manage users, accounts, sessions, and impersonations.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { AdminPlugin } from "authula/plugins";
|
|
244
|
+
|
|
245
|
+
const authulaClient = createClient({
|
|
246
|
+
url: "http://localhost:8080/auth",
|
|
247
|
+
plugins: [new AdminPlugin()],
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
#### User Management
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
await authulaClient.admin.createUser({
|
|
255
|
+
name: "John Doe",
|
|
256
|
+
email: "user@example.com",
|
|
257
|
+
// other fields...
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
// Get all users with pagination
|
|
261
|
+
const users = await authulaClient.admin.getAllUsers(100);
|
|
262
|
+
|
|
263
|
+
// Get a specific user by ID
|
|
264
|
+
const user = await authulaClient.admin.getUserById("user-id");
|
|
265
|
+
|
|
266
|
+
// Update user information
|
|
267
|
+
await authulaClient.admin.updateUser("user-id", { name: "Jane" });
|
|
268
|
+
|
|
269
|
+
// Delete a user
|
|
270
|
+
await authulaClient.admin.deleteUser("user-id");
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
#### Account Management
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// Create a new account for a user
|
|
277
|
+
await authulaClient.admin.createAccount("user-id", { /* account data */ });
|
|
278
|
+
|
|
279
|
+
// Get all accounts for a user
|
|
280
|
+
await authulaClient.admin.getUserAccounts("user-id");
|
|
281
|
+
|
|
282
|
+
// Get a specific account by ID
|
|
283
|
+
await authulaClient.admin.getAccountById("account-id");
|
|
284
|
+
|
|
285
|
+
// Update account information
|
|
286
|
+
await authulaClient.admin.updateAccount("account-id", { /* data */ });
|
|
287
|
+
|
|
288
|
+
// Delete an account
|
|
289
|
+
await authulaClient.admin.deleteAccount("account-id");
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### User State Management
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
// Get user state
|
|
296
|
+
await authulaClient.admin.getUserState("user-id");
|
|
297
|
+
|
|
298
|
+
// Create or update user state
|
|
299
|
+
await authulaClient.admin.createUserState("user-id", { /* state data */ });
|
|
300
|
+
|
|
301
|
+
// Update user state
|
|
302
|
+
await authulaClient.admin.updateUserState("user-id", { /* state data */ });
|
|
303
|
+
|
|
304
|
+
// Delete user state
|
|
305
|
+
await authulaClient.admin.deleteUserState("user-id");
|
|
306
|
+
|
|
307
|
+
// Get all banned user states
|
|
308
|
+
await authulaClient.admin.getBannedUserStates();
|
|
309
|
+
|
|
310
|
+
// Ban a user
|
|
311
|
+
await authulaClient.admin.banUser("user-id", { reason: "reason..." });
|
|
312
|
+
|
|
313
|
+
// Unban a user
|
|
314
|
+
await authulaClient.admin.unbanUser("user-id");
|
|
315
|
+
|
|
316
|
+
// Get all active sessions for a user
|
|
317
|
+
await authulaClient.admin.getUserAdminSessions("user-id");
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Session State Management
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
// Get session state
|
|
324
|
+
await authulaClient.admin.getSessionState("session-id");
|
|
325
|
+
|
|
326
|
+
// Create or update session state
|
|
327
|
+
await authulaClient.admin.createSessionState("session-id", { /* data */ });
|
|
328
|
+
|
|
329
|
+
// Update session state
|
|
330
|
+
await authulaClient.admin.updateSessionState("session-id", { /* data */ });
|
|
331
|
+
|
|
332
|
+
// Delete session state
|
|
333
|
+
await authulaClient.admin.deleteSessionState("session-id");
|
|
334
|
+
|
|
335
|
+
// Get all revoked session states
|
|
336
|
+
await authulaClient.admin.getRevokedSessionStates();
|
|
337
|
+
|
|
338
|
+
// Revoke a session
|
|
339
|
+
await authulaClient.admin.revokeSession("session-id", { reason: "reason..." });
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Impersonations
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
// Get all active impersonations
|
|
346
|
+
await authulaClient.admin.getAllImpersonations();
|
|
347
|
+
|
|
348
|
+
// Get a specific impersonation by ID
|
|
349
|
+
await authulaClient.admin.getImpersonationById("impersonation-id");
|
|
350
|
+
|
|
351
|
+
// Start impersonating a user
|
|
352
|
+
await authulaClient.admin.startImpersonation({ user_id: "user-id", /* data */ });
|
|
353
|
+
|
|
354
|
+
// Stop impersonation
|
|
355
|
+
await authulaClient.admin.stopImpersonation("impersonation-id");
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
### Email Password Plugin
|
|
361
|
+
|
|
362
|
+
Handles traditional email/password authentication flows.
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
import { EmailPasswordPlugin } from "authula/plugins";
|
|
366
|
+
|
|
367
|
+
const authulaClient = createClient({
|
|
368
|
+
url: "http://localhost:8080/auth",
|
|
369
|
+
plugins: [new EmailPasswordPlugin()],
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// Sign up
|
|
373
|
+
await authulaClient.emailPassword.signUp({
|
|
374
|
+
name: "John Doe",
|
|
375
|
+
email: "john@example.com",
|
|
376
|
+
password: "securePassword123",
|
|
377
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Sign in
|
|
381
|
+
const response = await authulaClient.emailPassword.signIn({
|
|
382
|
+
email: "john@example.com",
|
|
383
|
+
password: "securePassword123",
|
|
384
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// Send email verification
|
|
388
|
+
await authulaClient.emailPassword.sendEmailVerification({
|
|
389
|
+
email: "john@example.com",
|
|
390
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// Request password reset
|
|
394
|
+
await authulaClient.emailPassword.requestPasswordReset({
|
|
395
|
+
email: "john@example.com",
|
|
396
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Change password
|
|
400
|
+
await authulaClient.emailPassword.changePassword({
|
|
401
|
+
token: "reset-token",
|
|
402
|
+
password: "newSecurePassword123",
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// Request email change
|
|
406
|
+
await authulaClient.emailPassword.requestEmailChange({
|
|
407
|
+
email: "john.doe@example.com",
|
|
408
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
### OAuth2 Plugin
|
|
415
|
+
|
|
416
|
+
Handles OAuth2 authentication with popular providers.
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
import { OAuth2Plugin } from "authula/plugins";
|
|
420
|
+
|
|
421
|
+
const authulaClient = createClient({
|
|
422
|
+
url: "http://localhost:8080/auth",
|
|
423
|
+
plugins: [new OAuth2Plugin()],
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Redirect user to OAuth2 provider
|
|
427
|
+
const response = await authulaClient.oauth2.signIn({
|
|
428
|
+
provider: "google", // or "github", "discord"
|
|
429
|
+
redirect_to: "http://localhost:3000/callback",
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Redirect user to the authUrl
|
|
433
|
+
window.location.href = response.auth_url;
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
### CSRF Plugin
|
|
439
|
+
|
|
440
|
+
Provides automatic CSRF protection for mutating requests.
|
|
441
|
+
|
|
442
|
+
```typescript
|
|
443
|
+
import { CSRFPlugin } from "authula/plugins";
|
|
444
|
+
|
|
445
|
+
const authulaClient = createClient({
|
|
446
|
+
url: "http://localhost:8080/auth",
|
|
447
|
+
cookies: ..., // Provide cookie store for SSR if needed, else omit for SPA/Mobile apps
|
|
448
|
+
plugins: [
|
|
449
|
+
new CSRFPlugin({
|
|
450
|
+
cookieName: "csrf_token", // Name of the CSRF token cookie
|
|
451
|
+
headerName: "X-CSRF-TOKEN" // Header name to send the token
|
|
452
|
+
})
|
|
453
|
+
]
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
// CSRF tokens will be automatically added to mutating requests (POST, PUT, PATCH, DELETE)
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
### JWT Plugin
|
|
462
|
+
|
|
463
|
+
Handles JWT token operations including refresh.
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
import { JWTPlugin } from "authula/plugins";
|
|
467
|
+
|
|
468
|
+
const authulaClient = createClient({
|
|
469
|
+
url: "http://localhost:8080/auth",
|
|
470
|
+
plugins: [new JWTPlugin()],
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// Refresh JWT tokens
|
|
474
|
+
const tokens = await authulaClient.jwt.refreshToken({
|
|
475
|
+
refresh_token: "your-refresh-token",
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// Get JWKS keys
|
|
479
|
+
const jwksKeys = await authulaClient.jwt.getJWKSKeys();
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
### Bearer Plugin
|
|
485
|
+
|
|
486
|
+
Provides automatic bearer token handling and refresh.
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
import { BearerPlugin, JWTPlugin } from "authula/plugins";
|
|
490
|
+
|
|
491
|
+
const authulaClient = createClient({
|
|
492
|
+
url: "http://localhost:8080/auth",
|
|
493
|
+
plugins: [
|
|
494
|
+
new JWTPlugin(),
|
|
495
|
+
new BearerPlugin({
|
|
496
|
+
headerName: "Authorization", // Can be omitted as default is Authorization
|
|
497
|
+
}),
|
|
498
|
+
],
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// The Bearer plugin will automatically:
|
|
502
|
+
// 1. Add Authorization: Bearer <token> header to requests
|
|
503
|
+
// 2. Handle token refresh when receiving 401 responses
|
|
504
|
+
// 3. Store tokens in localStorage (access_token and refresh_token)
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
### Magic Link Plugin
|
|
510
|
+
|
|
511
|
+
Provides flows for passwordless authentication.
|
|
512
|
+
|
|
513
|
+
```typescript
|
|
514
|
+
import { MagicLinkPlugin } from "authula/plugins";
|
|
515
|
+
|
|
516
|
+
const authulaClient = createClient({
|
|
517
|
+
url: "http://localhost:8080/auth",
|
|
518
|
+
plugins: [new MagicLinkPlugin()],
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
// Send magic link via email
|
|
522
|
+
await authulaClient.magicLink.signIn({
|
|
523
|
+
email: "john.doe@example.com",
|
|
524
|
+
name: "John Doe", // Optional name
|
|
525
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Verify magic link token
|
|
529
|
+
await authulaClient.magicLink.verify({
|
|
530
|
+
token: "magic-link-token",
|
|
531
|
+
callbackUrl: "http://localhost:3000/callback", // Optional callback URL
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// Exchange token from verify endpoint for session
|
|
535
|
+
await authulaClient.magicLink.exchange({
|
|
536
|
+
token: "magic-link-token",
|
|
537
|
+
});
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
## Advanced Configuration
|
|
541
|
+
|
|
542
|
+
### Fetch Options
|
|
543
|
+
|
|
544
|
+
Configure fetch behavior with timeout and other options:
|
|
545
|
+
|
|
546
|
+
```typescript
|
|
547
|
+
const authulaClient = createClient({
|
|
548
|
+
url: "http://localhost:8080/auth",
|
|
549
|
+
fetchOptions: {
|
|
550
|
+
abortTimeout: 30, // Timeout in seconds
|
|
551
|
+
},
|
|
552
|
+
plugins: [
|
|
553
|
+
// your plugins
|
|
554
|
+
],
|
|
555
|
+
});
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Custom Hooks
|
|
559
|
+
|
|
560
|
+
Add custom before/after fetch hooks for advanced customization:
|
|
561
|
+
|
|
562
|
+
```typescript
|
|
563
|
+
const authulaClient = createClient({
|
|
564
|
+
url: "http://localhost:8080/auth",
|
|
565
|
+
plugins: [new EmailPasswordPlugin()],
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
// Register a before fetch hook
|
|
569
|
+
authulaClient.registerBeforeFetch(async (ctx) => {
|
|
570
|
+
console.log(`Making request to: ${ctx.url}`);
|
|
571
|
+
// Modify context if needed
|
|
572
|
+
ctx.init.headers = {
|
|
573
|
+
...ctx.init.headers,
|
|
574
|
+
"X-Custom-Header": "value",
|
|
575
|
+
};
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
// Register an after fetch hook
|
|
579
|
+
authulaClient.registerAfterFetch(async (ctx, response) => {
|
|
580
|
+
console.log(`Received response: ${response.status}`);
|
|
581
|
+
if (response.status >= 400) {
|
|
582
|
+
// Handle error
|
|
583
|
+
}
|
|
584
|
+
});
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
## API Reference
|
|
588
|
+
|
|
589
|
+
### Client Configuration
|
|
590
|
+
|
|
591
|
+
```typescript
|
|
592
|
+
{
|
|
593
|
+
// Base URL of your Authula server
|
|
594
|
+
url: string,
|
|
595
|
+
// Optional fetch configuration
|
|
596
|
+
fetchOptions?: {
|
|
597
|
+
// Request timeout in seconds
|
|
598
|
+
abortTimeout?: number
|
|
599
|
+
},
|
|
600
|
+
// Cookie provider for SSR compatibility
|
|
601
|
+
cookies?: () => CookieStore
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## Error Handling
|
|
606
|
+
|
|
607
|
+
All methods return promises that can be caught for error handling:
|
|
608
|
+
|
|
609
|
+
```typescript
|
|
610
|
+
try {
|
|
611
|
+
const response = await authulaClient.emailPassword.signIn({
|
|
612
|
+
email: "user@example.com",
|
|
613
|
+
password: "password",
|
|
614
|
+
});
|
|
615
|
+
console.log("Signed in successfully", response);
|
|
616
|
+
} catch (error) {
|
|
617
|
+
console.error("Sign in failed:", error);
|
|
618
|
+
}
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
## Contributing
|
|
622
|
+
|
|
623
|
+
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
|
|
624
|
+
|
|
625
|
+
## License
|
|
626
|
+
|
|
627
|
+
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
|