npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

payload-auth-cookie

v0.0.14

Published

Payload CMS authentication plugin for Cookies from external SSO

Downloads

298

Readme

payload-auth-cookie

A Payload CMS authentication plugin for external SSO cookie-based authentication.

This plugin allows you to authenticate users based on cookies set by an external SSO system. It validates sessions via a configurable session endpoint and maps users to Payload CMS collections.

Features

  • 🍪 Cookie-based authentication from external SSO systems
  • 🔑 JWT verification with configurable secret (no external API call needed)
  • 🔐 Support for both admin panel and frontend authentication
  • 👤 Automatic user creation with configurable sign-up policy
  • 🔄 Session validation via external API or JWT verification
  • 📦 TypeScript support with full type definitions

Installation

npm install payload-auth-cookie
# or
pnpm add payload-auth-cookie
# or
yarn add payload-auth-cookie

Quick Start

1. Configure the Plugin

// payload.config.ts
import { buildConfig } from 'payload'
import { authPlugin } from 'payload-auth-cookie'

export default buildConfig({
  plugins: [
    authPlugin({
      name: 'admin',
      useAdmin: true,
      usersCollectionSlug: 'adminUsers',
      successRedirectPath: '/admin',
      sso: {
        cookieName: process.env.SSO_COOKIE_NAME!,
        loginUrl: process.env.SSO_LOGIN_URL!,
        logoutUrl: process.env.SSO_LOGOUT_URL!,
        sessionUrl: process.env.SSO_SESSION_URL!,
      },
    }),
  ],
})

2. Create a Users Collection

// collections/Users.ts
import { withUsersCollection } from 'payload-auth-cookie/collection'

export const AdminUsers = withUsersCollection({
  slug: 'adminUsers',
  auth: {
    disableLocalStrategy: true,
  },
  fields: [
    {
      name: 'name',
      type: 'text',
    },
  ],
})

3. Add Login Button to Admin Panel

// components/SSOLoginButton.tsx
'use client'

import { LoginButton } from 'payload-auth-cookie/client'

export default function SSOLoginButton() {
  return <LoginButton href="/api/admin/auth/login" label="Sign in with SSO" />
}
// payload.config.ts
export default buildConfig({
  admin: {
    components: {
      afterLogin: ['@/components/SSOLoginButton'],
    },
  },
  // ...
})

Configuration

Plugin Options

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | name | string | ✅ | - | Unique name for this auth configuration (used in endpoint paths) | | usersCollectionSlug | string | ✅ | - | Slug of the users collection to authenticate against | | sso | SSOProviderConfig | ✅ | - | SSO provider configuration | | useAdmin | boolean | ❌ | false | Use this configuration for admin panel authentication | | allowSignUp | boolean | ❌ | false | Allow creating new users on first login | | successRedirectPath | string | ❌ | '/' | Path to redirect after successful authentication | | errorRedirectPath | string | ❌ | '/auth/error' | Path to redirect on authentication error | | onSuccess | function | ❌ | - | Callback after successful authentication | | onError | function | ❌ | - | Callback on authentication error |

SSO Provider Configuration

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | cookieName | string | ✅ | - | Name of the cookie set by your SSO system | | loginUrl | string | ✅ | - | URL to redirect for SSO login | | logoutUrl | string | ✅ | - | URL to redirect for SSO logout | | sessionUrl | string | ⚠️ | - | URL to validate session (required if jwt not provided) | | jwt | JWTVerificationConfig | ⚠️ | - | JWT verification config (required if sessionUrl not provided) | | timeoutMs | number | ❌ | 5000 | Timeout for session validation requests |

JWT Verification Configuration

When your SSO cookie contains a JWT, you can verify it locally without calling an external session endpoint:

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | secret | string | ✅ | - | Secret key for verifying JWT signatures | | algorithm | string | ❌ | 'HS256' | JWT algorithm (HS256, HS384, HS512) | | issuer | string | ❌ | - | Expected issuer (iss claim) | | audience | string | ❌ | - | Expected audience (aud claim) | | emailField | string | ❌ | 'email' | Field path to extract email (supports dot notation) | | firstNameField | string | ❌ | 'firstName' | Field path to extract first name | | lastNameField | string | ❌ | 'lastName' | Field path to extract last name | | profilePictureUrlField | string | ❌ | 'profilePictureUrl' | Field path to extract profile picture URL |

Field Mappings

Map SSO response fields to your collection's field names:

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | fieldMappings.nameField | string | ❌ | 'name' | SSO field containing the user's full name | | fieldMappings.firstNameField | string | ❌ | 'firstName' | SSO field containing the user's first name | | fieldMappings.lastNameField | string | ❌ | 'lastName' | SSO field containing the user's last name | | fieldMappings.profilePictureUrlField | string | ❌ | 'profilePictureUrl' | SSO field containing the profile picture URL | | fieldMappings.emailVerifiedField | string | ❌ | 'emailVerified' | SSO field indicating email verification status | | fieldMappings.lastLoginAtField | string | ❌ | 'lastLoginAt' | SSO field containing last login timestamp |

Field Mappings Example

authPlugin({
  name: 'app',
  usersCollectionSlug: 'appUsers',
  sso: {
    cookieName: 'sso_token',
    loginUrl: 'https://sso.example.com/login',
    logoutUrl: 'https://sso.example.com/logout',
    jwt: {
      secret: process.env.SSO_JWT_SECRET!,
    },
    fieldMappings: {
      nameField: 'full_name',           // Maps SSO's full_name → user.name
      profilePictureUrlField: 'avatar', // Maps SSO's avatar → user.profilePictureUrl
    },
  },
})

JWT Configuration Example

authPlugin({
  name: 'admin',
  useAdmin: true,
  usersCollectionSlug: 'adminUsers',
  sso: {
    cookieName: 'sso_token',
    loginUrl: 'https://sso.example.com/login',
    logoutUrl: 'https://sso.example.com/logout',
    jwt: {
      secret: process.env.SSO_JWT_SECRET!,
      algorithm: 'HS256',
      issuer: 'https://sso.example.com',
      emailField: 'user.email',  // For nested JWT payloads
    },
  },
})

Authentication Flow

Admin Login Flow

  1. User navigates to /admin
  2. If not authenticated, clicks "Sign in with SSO" button
  3. Plugin redirects to loginUrl with returnUrl parameter
  4. User authenticates with external SSO
  5. SSO system sets a cookie (e.g., supaku_session)
  6. User is redirected back to /api/admin/auth/login
  7. Plugin validates cookie via sessionUrl or JWT verification
  8. Plugin finds/creates user and sets Payload session cookie
  9. User is redirected to /admin

Frontend Login Flow

  1. User navigates to /auth/login (or custom login page)
  2. App redirects to /api/app/auth/login
  3. If no SSO cookie, redirects to loginUrl
  4. After SSO authentication, user returns with cookie
  5. Plugin validates and creates session
  6. User is redirected to success path

Session Validation Methods

Method 1: Session URL (API-based)

Your SSO session endpoint (sessionUrl) should:

  1. Accept the SSO cookie in the request
  2. Return JSON with at least an email field
  3. Return 200 OK for valid sessions
  4. Return non-2xx for invalid/expired sessions

Expected Response Format

The plugin supports multiple response formats:

Direct user data:

{
  "email": "[email protected]",
  "firstName": "John",
  "lastName": "Doe",
  "profilePictureUrl": "https://example.com/avatar.jpg"
}

Nested user object (automatically extracted):

{
  "authenticated": true,
  "user": {
    "email": "[email protected]",
    "firstName": "John",
    "lastName": "Doe",
    "profilePictureUrl": "https://example.com/avatar.jpg"
  }
}

Method 2: JWT Verification (Local)

If your SSO cookie is a JWT, configure jwt instead of sessionUrl:

sso: {
  cookieName: 'sso_token',
  loginUrl: 'https://sso.example.com/login',
  logoutUrl: 'https://sso.example.com/logout',
  jwt: {
    secret: process.env.SSO_JWT_SECRET!,
  },
}

The JWT payload should contain at least an email field (configurable via emailField).

Multiple Auth Instances

You can configure multiple auth instances for different user types. Each instance creates its own set of endpoints and correctly returns users from its associated collection:

plugins: [
  authPlugin({
    name: 'admin',
    useAdmin: true,
    usersCollectionSlug: 'adminUsers',
    successRedirectPath: '/admin',
    sso: adminSSOConfig,
  }),
  authPlugin({
    name: 'app',
    allowSignUp: true,
    usersCollectionSlug: 'appUsers',
    successRedirectPath: '/',
    sso: appSSOConfig,
  }),
]

With this configuration:

  • /api/admin/auth/session returns users from adminUsers collection
  • /api/app/auth/session returns users from appUsers collection
  • Each endpoint syncs SSO data to its own collection's user records
  • Authentication strategies are uniquely named (sso-cookie-adminUsers, sso-cookie-appUsers)

API Endpoints

The plugin creates the following endpoints (prefixed with your configured name):

| Endpoint | Method | Description | |----------|--------|-------------| | /api/{name}/auth/login | GET | Initiates login or validates SSO cookie | | /api/{name}/auth/logout | GET | Clears session and redirects to SSO logout | | /api/{name}/auth/session | GET | Returns current session status | | /api/users/me | GET | Returns current user (for Payload admin bar compatibility) |

Admin Bar Compatibility

The plugin automatically adds a /api/users/me endpoint to support the Payload admin bar, which expects this endpoint to exist. This works around an issue where Payload calls /api/users/me on every page load even when disableLocalStrategy: true is set on the users collection.

Helper Functions

Server-Side

import {
  validateSSOSession,
  verifyJWTSession,
  fetchSSOSession,
  getEmailFromSession,
  parseCookies,
  generateUserToken,
} from 'payload-auth-cookie'

Client-Side

import { LoginButton, AuthProvider, useAuth } from 'payload-auth-cookie/client'

Environment Variables

# Common
SSO_COOKIE_NAME=supaku_session
SSO_LOGIN_URL=https://sso.example.com/login
SSO_LOGOUT_URL=https://sso.example.com/logout

# For Session URL validation
SSO_SESSION_URL=https://sso.example.com/api/session

# For JWT verification (alternative to SESSION_URL)
SSO_JWT_SECRET=your-jwt-signing-secret

License

MIT