0
# Authentication System
1
2
Complete user authentication and management system with login, password reset, email verification, and account locking capabilities. Payload provides built-in authentication for collections configured with auth enabled.
3
4
## Capabilities
5
6
### Login Operation
7
8
Authenticates a user with email and password credentials.
9
10
```typescript { .api }
11
/**
12
* Authenticate a user with email and password
13
* @param options - Login options including collection, credentials, and configuration
14
* @returns Promise resolving to login result with user data and token
15
*/
16
function login<T>(options: LoginOptions): Promise<LoginResult & { user: T }>;
17
18
interface LoginOptions {
19
/** The auth-enabled collection slug (e.g., "users", "admins") */
20
collection: string;
21
/** Login credentials */
22
data: {
23
/** User's email address */
24
email: string;
25
/** User's password */
26
password: string;
27
};
28
/** Express request object (for cookie handling) */
29
req?: PayloadRequest;
30
/** Express response object (for cookie handling) */
31
res?: Response;
32
/** How many levels deep to populate user relationships */
33
depth?: number;
34
/** Locale for the operation */
35
locale?: string;
36
/** Fallback locale if content not found in specified locale */
37
fallbackLocale?: string;
38
/** Whether to override access control */
39
overrideAccess?: boolean;
40
/** Whether to include hidden fields */
41
showHiddenFields?: boolean;
42
}
43
44
interface LoginResult {
45
/** JWT token for authenticated requests (if not using cookies) */
46
token?: string;
47
/** The authenticated user document */
48
user: User;
49
/** Token expiration timestamp */
50
exp?: number;
51
}
52
```
53
54
**Usage Examples:**
55
56
```typescript
57
import payload from "payload";
58
59
// Basic login
60
const loginResult = await payload.login({
61
collection: "users",
62
data: {
63
email: "user@example.com",
64
password: "secure-password",
65
},
66
});
67
68
console.log("User:", loginResult.user);
69
console.log("Token:", loginResult.token);
70
71
// Login with populated relationships
72
const loginWithProfile = await payload.login({
73
collection: "users",
74
data: {
75
email: "user@example.com",
76
password: "secure-password",
77
},
78
depth: 1, // Populate user profile relationships
79
});
80
81
// Login in Express route (with cookies)
82
app.post("/api/login", async (req, res) => {
83
try {
84
const result = await payload.login({
85
collection: "users",
86
data: req.body,
87
req,
88
res,
89
});
90
91
res.json(result);
92
} catch (error) {
93
res.status(401).json({ error: error.message });
94
}
95
});
96
```
97
98
### Password Reset Operations
99
100
Forgot password and reset password functionality for user account recovery.
101
102
```typescript { .api }
103
/**
104
* Initiate password reset process by sending reset token to user's email
105
* @param options - Forgot password options
106
* @returns Promise resolving to forgot password result
107
*/
108
function forgotPassword(options: ForgotPasswordOptions): Promise<ForgotPasswordResult>;
109
110
/**
111
* Reset user password using a valid reset token
112
* @param options - Reset password options including token and new password
113
* @returns Promise resolving to reset password result
114
*/
115
function resetPassword(options: ResetPasswordOptions): Promise<ResetPasswordResult>;
116
117
interface ForgotPasswordOptions {
118
/** The auth-enabled collection slug */
119
collection: string;
120
/** User's email address */
121
data: {
122
email: string;
123
};
124
/** Express request object */
125
req?: PayloadRequest;
126
/** How many levels deep to populate user relationships */
127
depth?: number;
128
/** Locale for the operation */
129
locale?: string;
130
/** Fallback locale */
131
fallbackLocale?: string;
132
/** Whether to override access control */
133
overrideAccess?: boolean;
134
/** Whether to include hidden fields */
135
showHiddenFields?: boolean;
136
/** Token expiration time in seconds */
137
expiration?: number;
138
/** Disable sending the email */
139
disableEmail?: boolean;
140
}
141
142
interface ResetPasswordOptions {
143
/** The auth-enabled collection slug */
144
collection: string;
145
/** Reset data including token and new password */
146
data: {
147
/** Reset token from email */
148
token: string;
149
/** New password */
150
password: string;
151
};
152
/** Express request object */
153
req?: PayloadRequest;
154
/** How many levels deep to populate user relationships */
155
depth?: number;
156
/** Locale for the operation */
157
locale?: string;
158
/** Fallback locale */
159
fallbackLocale?: string;
160
/** Whether to override access control */
161
overrideAccess?: boolean;
162
/** Whether to include hidden fields */
163
showHiddenFields?: boolean;
164
}
165
166
interface ForgotPasswordResult {
167
/** Success message */
168
message: string;
169
}
170
171
interface ResetPasswordResult {
172
/** Success message */
173
message: string;
174
/** JWT token for immediate login */
175
token?: string;
176
/** The user document */
177
user?: User;
178
}
179
```
180
181
**Usage Examples:**
182
183
```typescript
184
// Initiate password reset
185
const forgotResult = await payload.forgotPassword({
186
collection: "users",
187
data: {
188
email: "user@example.com",
189
},
190
});
191
192
console.log(forgotResult.message); // "Check your email for a reset link"
193
194
// Reset password with token
195
const resetResult = await payload.resetPassword({
196
collection: "users",
197
data: {
198
token: "reset-token-from-email",
199
password: "new-secure-password",
200
},
201
});
202
203
console.log(resetResult.message); // "Password reset successfully"
204
console.log("Auto-login token:", resetResult.token);
205
```
206
207
### Account Security Operations
208
209
Email verification and account unlocking for enhanced security.
210
211
```typescript { .api }
212
/**
213
* Verify user's email address using verification token
214
* @param options - Email verification options
215
* @returns Promise resolving to verification success status
216
*/
217
function verifyEmail(options: VerifyEmailOptions): Promise<boolean>;
218
219
/**
220
* Unlock a locked user account
221
* @param options - Account unlock options
222
* @returns Promise resolving to unlock success status
223
*/
224
function unlock(options: UnlockOptions): Promise<boolean>;
225
226
interface VerifyEmailOptions {
227
/** The auth-enabled collection slug */
228
collection: string;
229
/** Verification token from email */
230
token: string;
231
/** Express request object */
232
req?: PayloadRequest;
233
/** How many levels deep to populate user relationships */
234
depth?: number;
235
/** Locale for the operation */
236
locale?: string;
237
/** Fallback locale */
238
fallbackLocale?: string;
239
/** Whether to override access control */
240
overrideAccess?: boolean;
241
/** Whether to include hidden fields */
242
showHiddenFields?: boolean;
243
}
244
245
interface UnlockOptions {
246
/** The auth-enabled collection slug */
247
collection: string;
248
/** Unlock data including email */
249
data: {
250
/** User's email address */
251
email: string;
252
};
253
/** Express request object */
254
req?: PayloadRequest;
255
/** How many levels deep to populate user relationships */
256
depth?: number;
257
/** Locale for the operation */
258
locale?: string;
259
/** Fallback locale */
260
fallbackLocale?: string;
261
/** Whether to override access control */
262
overrideAccess?: boolean;
263
/** Whether to include hidden fields */
264
showHiddenFields?: boolean;
265
}
266
```
267
268
**Usage Examples:**
269
270
```typescript
271
// Verify email address
272
const isVerified = await payload.verifyEmail({
273
collection: "users",
274
token: "verification-token-from-email",
275
});
276
277
if (isVerified) {
278
console.log("Email verified successfully");
279
}
280
281
// Unlock account
282
const isUnlocked = await payload.unlock({
283
collection: "users",
284
data: {
285
email: "locked-user@example.com",
286
},
287
});
288
289
if (isUnlocked) {
290
console.log("Account unlocked successfully");
291
}
292
```
293
294
## Authentication Configuration
295
296
### Auth-Enabled Collections
297
298
Collections must be configured with authentication to use these operations.
299
300
```typescript { .api }
301
interface CollectionConfig {
302
slug: string;
303
auth?: AuthConfig | boolean;
304
// ... other collection options
305
}
306
307
interface AuthConfig {
308
/** Token expires in (seconds) */
309
tokenExpiration?: number;
310
/** Maximum login attempts before locking */
311
maxLoginAttempts?: number;
312
/** Account lock duration (seconds) */
313
lockTime?: number;
314
/** Use email verification */
315
verify?: boolean | EmailVerificationConfig;
316
/** Forgot password configuration */
317
forgotPassword?: ForgotPasswordConfig;
318
/** Login rate limiting */
319
useAPIKey?: boolean;
320
/** Disable username (use email only) */
321
disableLocalStrategy?: boolean;
322
/** Custom login strategies */
323
strategies?: AuthStrategy[];
324
/** Cookie settings */
325
cookies?: CookieOptions;
326
}
327
328
interface EmailVerificationConfig {
329
/** Generate token function */
330
generateEmailHTML?: (args: {
331
token: string;
332
user: User;
333
}) => string;
334
/** Generate email subject */
335
generateEmailSubject?: (args: {
336
token: string;
337
user: User;
338
}) => string;
339
}
340
341
interface ForgotPasswordConfig {
342
/** Generate reset email HTML */
343
generateEmailHTML?: (args: {
344
token: string;
345
user: User;
346
}) => string;
347
/** Generate email subject */
348
generateEmailSubject?: (args: {
349
token: string;
350
user: User;
351
}) => string;
352
}
353
```
354
355
## User Types
356
357
```typescript { .api }
358
interface User extends TypeWithID {
359
/** User's email address */
360
email?: string;
361
/** Password reset token */
362
resetPasswordToken?: string;
363
/** Reset token expiration */
364
resetPasswordExpiration?: string;
365
/** Password salt */
366
salt?: string;
367
/** Password hash */
368
hash?: string;
369
/** Failed login attempts count */
370
loginAttempts?: number;
371
/** Account lock expiration timestamp */
372
lockUntil?: number;
373
/** Email verification status */
374
_verified?: boolean;
375
/** Email verification token */
376
_verificationToken?: string;
377
/** API key for API authentication */
378
apiKey?: string;
379
/** Whether account is enabled */
380
enableAPIKey?: boolean;
381
}
382
383
interface PayloadRequest extends Request {
384
/** Authenticated user */
385
user?: User;
386
/** Request locale */
387
locale?: string;
388
/** Fallback locale */
389
fallbackLocale?: string;
390
/** Request payload */
391
payload: Payload;
392
}
393
```
394
395
## Advanced Authentication Configuration
396
397
### Authentication Configuration Options
398
399
Complete authentication configuration for collections with auth enabled.
400
401
```typescript { .api }
402
/**
403
* Authentication configuration for collections
404
*/
405
interface AuthConfig {
406
/** JWT token expiration time in seconds (default: 7200) */
407
tokenExpiration?: number;
408
/** Email verification configuration */
409
verify?: boolean | VerifyConfig;
410
/** Maximum login attempts before account lock */
411
maxLoginAttempts?: number;
412
/** Account lock duration in milliseconds */
413
lockTime?: number;
414
/** Enable API key authentication */
415
useAPIKey?: boolean;
416
/** Population depth for user documents */
417
depth?: number;
418
/** Cookie configuration */
419
cookies?: CookieConfig;
420
/** Forgot password email configuration */
421
forgotPassword?: ForgotPasswordConfig;
422
/** Disable local username/password strategy */
423
disableLocalStrategy?: boolean;
424
/** Custom authentication strategies */
425
strategies?: AuthStrategy[];
426
}
427
428
/**
429
* Email verification configuration
430
*/
431
interface VerifyConfig {
432
/** Function to generate verification email HTML */
433
generateEmailHTML?: (args: {
434
req: PayloadRequest;
435
token: string;
436
user: any;
437
}) => Promise<string> | string;
438
/** Function to generate verification email subject */
439
generateEmailSubject?: (args: {
440
req: PayloadRequest;
441
token: string;
442
user: any;
443
}) => Promise<string> | string;
444
}
445
446
/**
447
* Cookie configuration for auth
448
*/
449
interface CookieConfig {
450
/** Use secure cookies (HTTPS only) */
451
secure?: boolean;
452
/** SameSite cookie attribute */
453
sameSite?: boolean | 'none' | 'strict' | 'lax';
454
/** Cookie domain */
455
domain?: string;
456
}
457
458
/**
459
* Forgot password email configuration
460
*/
461
interface ForgotPasswordConfig {
462
/** Function to generate password reset email HTML */
463
generateEmailHTML?: (args: {
464
req?: PayloadRequest;
465
token?: string;
466
user?: unknown;
467
}) => Promise<string> | string;
468
/** Function to generate password reset email subject */
469
generateEmailSubject?: (args: {
470
req?: PayloadRequest;
471
token?: string;
472
user?: any;
473
}) => Promise<string> | string;
474
}
475
476
/**
477
* Custom authentication strategy
478
*/
479
interface AuthStrategy {
480
/** Strategy name */
481
name?: string;
482
/** Passport strategy instance or factory */
483
strategy: Strategy | ((payload: Payload) => Strategy);
484
}
485
```
486
487
**Authentication Configuration Examples:**
488
489
```typescript
490
// Basic auth configuration
491
const UsersCollection: CollectionConfig = {
492
slug: "users",
493
auth: {
494
tokenExpiration: 7200, // 2 hours
495
verify: true, // Enable email verification
496
maxLoginAttempts: 5,
497
lockTime: 600000, // 10 minutes
498
useAPIKey: true,
499
},
500
fields: [
501
{
502
name: "firstName",
503
type: "text",
504
required: true,
505
},
506
{
507
name: "lastName",
508
type: "text",
509
required: true,
510
},
511
],
512
};
513
514
// Advanced auth with custom emails
515
const AdvancedUsersCollection: CollectionConfig = {
516
slug: "users",
517
auth: {
518
tokenExpiration: 86400, // 24 hours
519
verify: {
520
generateEmailHTML: ({ user, token, req }) => {
521
return `
522
<h1>Welcome ${user.firstName}!</h1>
523
<p>Please verify your email by clicking the link below:</p>
524
<a href="${req.payload.getAdminURL()}/verify/${token}">
525
Verify Email
526
</a>
527
`;
528
},
529
generateEmailSubject: ({ user }) => {
530
return `Welcome ${user.firstName} - Please verify your email`;
531
},
532
},
533
forgotPassword: {
534
generateEmailHTML: ({ user, token, req }) => {
535
return `
536
<h1>Password Reset</h1>
537
<p>Click the link below to reset your password:</p>
538
<a href="${req.payload.getAdminURL()}/reset-password/${token}">
539
Reset Password
540
</a>
541
`;
542
},
543
generateEmailSubject: () => {
544
return "Reset your password";
545
},
546
},
547
cookies: {
548
secure: process.env.NODE_ENV === "production",
549
sameSite: "lax",
550
domain: process.env.COOKIE_DOMAIN,
551
},
552
},
553
fields: [
554
{
555
name: "role",
556
type: "select",
557
options: ["admin", "editor", "user"],
558
defaultValue: "user",
559
},
560
],
561
};
562
563
// Custom OAuth strategies
564
const OAuthUsersCollection: CollectionConfig = {
565
slug: "users",
566
auth: {
567
disableLocalStrategy: true, // Only use OAuth
568
strategies: [
569
{
570
name: "google",
571
strategy: new GoogleStrategy(
572
{
573
clientID: process.env.GOOGLE_CLIENT_ID,
574
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
575
callbackURL: "/auth/google/callback",
576
},
577
async (accessToken, refreshToken, profile, done) => {
578
// Find or create user logic
579
const user = await payload.find({
580
collection: "users",
581
where: {
582
googleId: {
583
equals: profile.id,
584
},
585
},
586
});
587
return done(null, user.docs[0] || null);
588
}
589
),
590
},
591
],
592
},
593
fields: [
594
{
595
name: "googleId",
596
type: "text",
597
hidden: true,
598
},
599
],
600
};
601
```
602
603
## Permission System
604
605
### Permission Types
606
607
Comprehensive permission system for controlling access to collections, globals, and fields.
608
609
```typescript { .api }
610
/**
611
* Base permission result
612
*/
613
interface Permission {
614
/** Whether access is allowed */
615
permission: boolean;
616
/** Optional query constraint */
617
where?: Record<string, unknown>;
618
}
619
620
/**
621
* Field-level permissions
622
*/
623
interface FieldPermissions {
624
/** Create permission */
625
create: {
626
permission: boolean;
627
};
628
/** Read permission */
629
read: {
630
permission: boolean;
631
};
632
/** Update permission */
633
update: {
634
permission: boolean;
635
};
636
/** Nested field permissions */
637
fields?: {
638
[fieldName: string]: FieldPermissions;
639
};
640
}
641
642
/**
643
* Collection-level permissions
644
*/
645
interface CollectionPermission {
646
/** Create document permission */
647
create: Permission;
648
/** Read document permission */
649
read: Permission;
650
/** Update document permission */
651
update: Permission;
652
/** Delete document permission */
653
delete: Permission;
654
/** Field-level permissions */
655
fields: {
656
[fieldName: string]: FieldPermissions;
657
};
658
}
659
660
/**
661
* Global-level permissions
662
*/
663
interface GlobalPermission {
664
/** Read global permission */
665
read: Permission;
666
/** Update global permission */
667
update: Permission;
668
/** Field-level permissions */
669
fields: {
670
[fieldName: string]: FieldPermissions;
671
};
672
}
673
674
/**
675
* Complete user permissions
676
*/
677
interface Permissions {
678
/** Whether user can access admin panel */
679
canAccessAdmin: boolean;
680
/** Collection permissions */
681
collections: CollectionPermission[];
682
/** Global permissions */
683
globals?: GlobalPermission[];
684
}
685
686
/**
687
* User document with authentication methods
688
*/
689
interface UserDocument extends PayloadMongooseDocument {
690
/** Set user password */
691
setPassword: (password: string) => Promise<void>;
692
/** Authenticate user with password */
693
authenticate: (password: string) => Promise<void>;
694
/** Password reset expiration timestamp */
695
resetPasswordExpiration: number;
696
/** User email */
697
email: string;
698
}
699
```
700
701
**Permission Configuration Examples:**
702
703
```typescript
704
// Role-based permissions
705
const PostsCollection: CollectionConfig = {
706
slug: "posts",
707
access: {
708
read: ({ req: { user } }) => {
709
// Anyone can read published posts
710
if (!user) {
711
return {
712
status: {
713
equals: "published",
714
},
715
};
716
}
717
718
// Authors can read their own posts
719
if (user.role === "author") {
720
return {
721
or: [
722
{
723
status: {
724
equals: "published",
725
},
726
},
727
{
728
author: {
729
equals: user.id,
730
},
731
},
732
],
733
};
734
}
735
736
// Admins can read all posts
737
return user.role === "admin";
738
},
739
create: ({ req: { user } }) => {
740
return user && ["admin", "author"].includes(user.role);
741
},
742
update: ({ req: { user } }) => {
743
if (!user) return false;
744
745
if (user.role === "admin") return true;
746
747
// Authors can only update their own posts
748
if (user.role === "author") {
749
return {
750
author: {
751
equals: user.id,
752
},
753
};
754
}
755
756
return false;
757
},
758
delete: ({ req: { user } }) => {
759
return user && user.role === "admin";
760
},
761
},
762
fields: [
763
{
764
name: "title",
765
type: "text",
766
access: {
767
read: () => true, // Anyone can read title
768
update: ({ req: { user } }) => {
769
return user && ["admin", "author"].includes(user.role);
770
},
771
},
772
},
773
{
774
name: "status",
775
type: "select",
776
options: ["draft", "published"],
777
access: {
778
read: () => true,
779
update: ({ req: { user } }) => {
780
// Only admins can change status
781
return user && user.role === "admin";
782
},
783
},
784
},
785
],
786
};
787
```