or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdconfiguration.mdcore-operations.mdfield-types.mdglobal-operations.mdindex.mdpreferences.mdversion-control.md

authentication.mddocs/

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

```