CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-payload

Node, React and MongoDB Headless CMS and Application Framework

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

authentication.mddocs/

Authentication System

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.

Capabilities

Login Operation

Authenticates a user with email and password credentials.

/**
 * Authenticate a user with email and password
 * @param options - Login options including collection, credentials, and configuration
 * @returns Promise resolving to login result with user data and token
 */
function login<T>(options: LoginOptions): Promise<LoginResult & { user: T }>;

interface LoginOptions {
  /** The auth-enabled collection slug (e.g., "users", "admins") */
  collection: string;
  /** Login credentials */
  data: {
    /** User's email address */
    email: string;
    /** User's password */
    password: string;
  };
  /** Express request object (for cookie handling) */
  req?: PayloadRequest;
  /** Express response object (for cookie handling) */
  res?: Response;
  /** How many levels deep to populate user relationships */
  depth?: number;
  /** Locale for the operation */
  locale?: string;
  /** Fallback locale if content not found in specified locale */
  fallbackLocale?: string;
  /** Whether to override access control */
  overrideAccess?: boolean;
  /** Whether to include hidden fields */
  showHiddenFields?: boolean;
}

interface LoginResult {
  /** JWT token for authenticated requests (if not using cookies) */
  token?: string;
  /** The authenticated user document */
  user: User;
  /** Token expiration timestamp */
  exp?: number;
}

Usage Examples:

import payload from "payload";

// Basic login
const loginResult = await payload.login({
  collection: "users",
  data: {
    email: "user@example.com",
    password: "secure-password",
  },
});

console.log("User:", loginResult.user);
console.log("Token:", loginResult.token);

// Login with populated relationships
const loginWithProfile = await payload.login({
  collection: "users",
  data: {
    email: "user@example.com",
    password: "secure-password",
  },
  depth: 1, // Populate user profile relationships
});

// Login in Express route (with cookies)
app.post("/api/login", async (req, res) => {
  try {
    const result = await payload.login({
      collection: "users",
      data: req.body,
      req,
      res,
    });
    
    res.json(result);
  } catch (error) {
    res.status(401).json({ error: error.message });
  }
});

Password Reset Operations

Forgot password and reset password functionality for user account recovery.

/**
 * Initiate password reset process by sending reset token to user's email
 * @param options - Forgot password options
 * @returns Promise resolving to forgot password result
 */
function forgotPassword(options: ForgotPasswordOptions): Promise<ForgotPasswordResult>;

/**
 * Reset user password using a valid reset token
 * @param options - Reset password options including token and new password
 * @returns Promise resolving to reset password result
 */
function resetPassword(options: ResetPasswordOptions): Promise<ResetPasswordResult>;

interface ForgotPasswordOptions {
  /** The auth-enabled collection slug */
  collection: string;
  /** User's email address */
  data: {
    email: string;
  };
  /** Express request object */
  req?: PayloadRequest;
  /** How many levels deep to populate user relationships */
  depth?: number;
  /** Locale for the operation */
  locale?: string;
  /** Fallback locale */
  fallbackLocale?: string;
  /** Whether to override access control */
  overrideAccess?: boolean;
  /** Whether to include hidden fields */
  showHiddenFields?: boolean;
  /** Token expiration time in seconds */
  expiration?: number;
  /** Disable sending the email */
  disableEmail?: boolean;
}

interface ResetPasswordOptions {
  /** The auth-enabled collection slug */
  collection: string;
  /** Reset data including token and new password */
  data: {
    /** Reset token from email */
    token: string;
    /** New password */
    password: string;
  };
  /** Express request object */
  req?: PayloadRequest;
  /** How many levels deep to populate user relationships */
  depth?: number;
  /** Locale for the operation */
  locale?: string;
  /** Fallback locale */
  fallbackLocale?: string;
  /** Whether to override access control */
  overrideAccess?: boolean;
  /** Whether to include hidden fields */
  showHiddenFields?: boolean;
}

interface ForgotPasswordResult {
  /** Success message */
  message: string;
}

interface ResetPasswordResult {
  /** Success message */
  message: string;
  /** JWT token for immediate login */
  token?: string;
  /** The user document */
  user?: User;
}

Usage Examples:

// Initiate password reset
const forgotResult = await payload.forgotPassword({
  collection: "users",
  data: {
    email: "user@example.com",
  },
});

console.log(forgotResult.message); // "Check your email for a reset link"

// Reset password with token
const resetResult = await payload.resetPassword({
  collection: "users",
  data: {
    token: "reset-token-from-email",
    password: "new-secure-password",
  },
});

console.log(resetResult.message); // "Password reset successfully"
console.log("Auto-login token:", resetResult.token);

Account Security Operations

Email verification and account unlocking for enhanced security.

/**
 * Verify user's email address using verification token
 * @param options - Email verification options
 * @returns Promise resolving to verification success status
 */
function verifyEmail(options: VerifyEmailOptions): Promise<boolean>;

/**
 * Unlock a locked user account
 * @param options - Account unlock options
 * @returns Promise resolving to unlock success status
 */
function unlock(options: UnlockOptions): Promise<boolean>;

interface VerifyEmailOptions {
  /** The auth-enabled collection slug */
  collection: string;
  /** Verification token from email */
  token: string;
  /** Express request object */
  req?: PayloadRequest;
  /** How many levels deep to populate user relationships */
  depth?: number;
  /** Locale for the operation */
  locale?: string;
  /** Fallback locale */
  fallbackLocale?: string;
  /** Whether to override access control */
  overrideAccess?: boolean;
  /** Whether to include hidden fields */
  showHiddenFields?: boolean;
}

interface UnlockOptions {
  /** The auth-enabled collection slug */
  collection: string;
  /** Unlock data including email */
  data: {
    /** User's email address */
    email: string;
  };
  /** Express request object */
  req?: PayloadRequest;
  /** How many levels deep to populate user relationships */
  depth?: number;
  /** Locale for the operation */
  locale?: string;
  /** Fallback locale */
  fallbackLocale?: string;
  /** Whether to override access control */
  overrideAccess?: boolean;
  /** Whether to include hidden fields */
  showHiddenFields?: boolean;
}

Usage Examples:

// Verify email address
const isVerified = await payload.verifyEmail({
  collection: "users",
  token: "verification-token-from-email",
});

if (isVerified) {
  console.log("Email verified successfully");
}

// Unlock account
const isUnlocked = await payload.unlock({
  collection: "users",
  data: {
    email: "locked-user@example.com",
  },
});

if (isUnlocked) {
  console.log("Account unlocked successfully");
}

Authentication Configuration

Auth-Enabled Collections

Collections must be configured with authentication to use these operations.

interface CollectionConfig {
  slug: string;
  auth?: AuthConfig | boolean;
  // ... other collection options
}

interface AuthConfig {
  /** Token expires in (seconds) */
  tokenExpiration?: number;
  /** Maximum login attempts before locking */
  maxLoginAttempts?: number;
  /** Account lock duration (seconds) */
  lockTime?: number;
  /** Use email verification */
  verify?: boolean | EmailVerificationConfig;
  /** Forgot password configuration */
  forgotPassword?: ForgotPasswordConfig;
  /** Login rate limiting */
  useAPIKey?: boolean;
  /** Disable username (use email only) */
  disableLocalStrategy?: boolean;
  /** Custom login strategies */
  strategies?: AuthStrategy[];
  /** Cookie settings */
  cookies?: CookieOptions;
}

interface EmailVerificationConfig {
  /** Generate token function */
  generateEmailHTML?: (args: {
    token: string;
    user: User;
  }) => string;
  /** Generate email subject */
  generateEmailSubject?: (args: {
    token: string;
    user: User;
  }) => string;
}

interface ForgotPasswordConfig {
  /** Generate reset email HTML */
  generateEmailHTML?: (args: {
    token: string;
    user: User;
  }) => string;
  /** Generate email subject */
  generateEmailSubject?: (args: {
    token: string;
    user: User;
  }) => string;
}

User Types

interface User extends TypeWithID {
  /** User's email address */
  email?: string;
  /** Password reset token */
  resetPasswordToken?: string;
  /** Reset token expiration */
  resetPasswordExpiration?: string;
  /** Password salt */
  salt?: string;
  /** Password hash */
  hash?: string;
  /** Failed login attempts count */
  loginAttempts?: number;
  /** Account lock expiration timestamp */
  lockUntil?: number;
  /** Email verification status */
  _verified?: boolean;
  /** Email verification token */
  _verificationToken?: string;
  /** API key for API authentication */
  apiKey?: string;
  /** Whether account is enabled */
  enableAPIKey?: boolean;
}

interface PayloadRequest extends Request {
  /** Authenticated user */
  user?: User;
  /** Request locale */
  locale?: string;
  /** Fallback locale */
  fallbackLocale?: string;
  /** Request payload */
  payload: Payload;
}

Advanced Authentication Configuration

Authentication Configuration Options

Complete authentication configuration for collections with auth enabled.

/**
 * Authentication configuration for collections
 */
interface AuthConfig {
  /** JWT token expiration time in seconds (default: 7200) */
  tokenExpiration?: number;
  /** Email verification configuration */
  verify?: boolean | VerifyConfig;
  /** Maximum login attempts before account lock */
  maxLoginAttempts?: number;
  /** Account lock duration in milliseconds */
  lockTime?: number;
  /** Enable API key authentication */
  useAPIKey?: boolean;
  /** Population depth for user documents */
  depth?: number;
  /** Cookie configuration */
  cookies?: CookieConfig;
  /** Forgot password email configuration */
  forgotPassword?: ForgotPasswordConfig;
  /** Disable local username/password strategy */
  disableLocalStrategy?: boolean;
  /** Custom authentication strategies */
  strategies?: AuthStrategy[];
}

/**
 * Email verification configuration
 */
interface VerifyConfig {
  /** Function to generate verification email HTML */
  generateEmailHTML?: (args: {
    req: PayloadRequest;
    token: string;
    user: any;
  }) => Promise<string> | string;
  /** Function to generate verification email subject */
  generateEmailSubject?: (args: {
    req: PayloadRequest;
    token: string;
    user: any;
  }) => Promise<string> | string;
}

/**
 * Cookie configuration for auth
 */
interface CookieConfig {
  /** Use secure cookies (HTTPS only) */
  secure?: boolean;
  /** SameSite cookie attribute */
  sameSite?: boolean | 'none' | 'strict' | 'lax';
  /** Cookie domain */
  domain?: string;
}

/**
 * Forgot password email configuration
 */
interface ForgotPasswordConfig {
  /** Function to generate password reset email HTML */
  generateEmailHTML?: (args: {
    req?: PayloadRequest;
    token?: string;
    user?: unknown;
  }) => Promise<string> | string;
  /** Function to generate password reset email subject */
  generateEmailSubject?: (args: {
    req?: PayloadRequest;
    token?: string;
    user?: any;
  }) => Promise<string> | string;
}

/**
 * Custom authentication strategy
 */
interface AuthStrategy {
  /** Strategy name */
  name?: string;
  /** Passport strategy instance or factory */
  strategy: Strategy | ((payload: Payload) => Strategy);
}

Authentication Configuration Examples:

// Basic auth configuration
const UsersCollection: CollectionConfig = {
  slug: "users",
  auth: {
    tokenExpiration: 7200, // 2 hours
    verify: true, // Enable email verification
    maxLoginAttempts: 5,
    lockTime: 600000, // 10 minutes
    useAPIKey: true,
  },
  fields: [
    {
      name: "firstName",
      type: "text",
      required: true,
    },
    {
      name: "lastName", 
      type: "text",
      required: true,
    },
  ],
};

// Advanced auth with custom emails
const AdvancedUsersCollection: CollectionConfig = {
  slug: "users",
  auth: {
    tokenExpiration: 86400, // 24 hours
    verify: {
      generateEmailHTML: ({ user, token, req }) => {
        return `
          <h1>Welcome ${user.firstName}!</h1>
          <p>Please verify your email by clicking the link below:</p>
          <a href="${req.payload.getAdminURL()}/verify/${token}">
            Verify Email
          </a>
        `;
      },
      generateEmailSubject: ({ user }) => {
        return `Welcome ${user.firstName} - Please verify your email`;
      },
    },
    forgotPassword: {
      generateEmailHTML: ({ user, token, req }) => {
        return `
          <h1>Password Reset</h1>
          <p>Click the link below to reset your password:</p>
          <a href="${req.payload.getAdminURL()}/reset-password/${token}">
            Reset Password
          </a>
        `;
      },
      generateEmailSubject: () => {
        return "Reset your password";
      },
    },
    cookies: {
      secure: process.env.NODE_ENV === "production",
      sameSite: "lax",
      domain: process.env.COOKIE_DOMAIN,
    },
  },
  fields: [
    {
      name: "role",
      type: "select",
      options: ["admin", "editor", "user"],
      defaultValue: "user",
    },
  ],
};

// Custom OAuth strategies
const OAuthUsersCollection: CollectionConfig = {
  slug: "users",
  auth: {
    disableLocalStrategy: true, // Only use OAuth
    strategies: [
      {
        name: "google",
        strategy: new GoogleStrategy(
          {
            clientID: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
            callbackURL: "/auth/google/callback",
          },
          async (accessToken, refreshToken, profile, done) => {
            // Find or create user logic
            const user = await payload.find({
              collection: "users",
              where: {
                googleId: {
                  equals: profile.id,
                },
              },
            });
            return done(null, user.docs[0] || null);
          }
        ),
      },
    ],
  },
  fields: [
    {
      name: "googleId",
      type: "text",
      hidden: true,
    },
  ],
};

Permission System

Permission Types

Comprehensive permission system for controlling access to collections, globals, and fields.

/**
 * Base permission result
 */
interface Permission {
  /** Whether access is allowed */
  permission: boolean;
  /** Optional query constraint */
  where?: Record<string, unknown>;
}

/**
 * Field-level permissions
 */
interface FieldPermissions {
  /** Create permission */
  create: {
    permission: boolean;
  };
  /** Read permission */
  read: {
    permission: boolean;
  };
  /** Update permission */
  update: {
    permission: boolean;
  };
  /** Nested field permissions */
  fields?: {
    [fieldName: string]: FieldPermissions;
  };
}

/**
 * Collection-level permissions
 */
interface CollectionPermission {
  /** Create document permission */
  create: Permission;
  /** Read document permission */
  read: Permission;
  /** Update document permission */
  update: Permission;
  /** Delete document permission */
  delete: Permission;
  /** Field-level permissions */
  fields: {
    [fieldName: string]: FieldPermissions;
  };
}

/**
 * Global-level permissions
 */
interface GlobalPermission {
  /** Read global permission */
  read: Permission;
  /** Update global permission */
  update: Permission;
  /** Field-level permissions */
  fields: {
    [fieldName: string]: FieldPermissions;
  };
}

/**
 * Complete user permissions
 */
interface Permissions {
  /** Whether user can access admin panel */
  canAccessAdmin: boolean;
  /** Collection permissions */
  collections: CollectionPermission[];
  /** Global permissions */
  globals?: GlobalPermission[];
}

/**
 * User document with authentication methods
 */
interface UserDocument extends PayloadMongooseDocument {
  /** Set user password */
  setPassword: (password: string) => Promise<void>;
  /** Authenticate user with password */
  authenticate: (password: string) => Promise<void>;
  /** Password reset expiration timestamp */
  resetPasswordExpiration: number;
  /** User email */
  email: string;
}

Permission Configuration Examples:

// Role-based permissions
const PostsCollection: CollectionConfig = {
  slug: "posts",
  access: {
    read: ({ req: { user } }) => {
      // Anyone can read published posts
      if (!user) {
        return {
          status: {
            equals: "published",
          },
        };
      }
      
      // Authors can read their own posts
      if (user.role === "author") {
        return {
          or: [
            {
              status: {
                equals: "published",
              },
            },
            {
              author: {
                equals: user.id,
              },
            },
          ],
        };
      }
      
      // Admins can read all posts
      return user.role === "admin";
    },
    create: ({ req: { user } }) => {
      return user && ["admin", "author"].includes(user.role);
    },
    update: ({ req: { user } }) => {
      if (!user) return false;
      
      if (user.role === "admin") return true;
      
      // Authors can only update their own posts
      if (user.role === "author") {
        return {
          author: {
            equals: user.id,
          },
        };
      }
      
      return false;
    },
    delete: ({ req: { user } }) => {
      return user && user.role === "admin";
    },
  },
  fields: [
    {
      name: "title",
      type: "text",
      access: {
        read: () => true, // Anyone can read title
        update: ({ req: { user } }) => {
          return user && ["admin", "author"].includes(user.role);
        },
      },
    },
    {
      name: "status",
      type: "select",
      options: ["draft", "published"],
      access: {
        read: () => true,
        update: ({ req: { user } }) => {
          // Only admins can change status
          return user && user.role === "admin";
        },
      },
    },
  ],
};

Install with Tessl CLI

npx tessl i tessl/npm-payload

docs

authentication.md

configuration.md

core-operations.md

field-types.md

global-operations.md

index.md

preferences.md

version-control.md

tile.json