payload-clerk-plugin
v0.1.1
Published
Payload CMS plugin for Clerk authentication integration
Maintainers
Readme
Payload Clerk Plugin
A comprehensive Payload CMS plugin that integrates Clerk authentication, providing seamless user management, role-based access control, and modern authentication flows.
✨ Features
🔐 Authentication & User Management
- Clerk Authentication Strategy: Replace Payload's default auth with Clerk's secure authentication
- Real-time User Sync: Automatic webhook-based synchronization of user data between Clerk and Payload
- Role-Based Access Control: Flexible RBAC system with customizable admin and user roles
- User Collection Enhancement: Automatically extends your user collection with Clerk-specific fields
🎛️ Admin Dashboard Integration
- Custom Admin Views: Dedicated Clerk Users management interface within Payload admin
- Role Management: Admin interface for updating user roles and permissions
- Dashboard Components: Welcome panel with development tools and navigation enhancements
- Smart Navigation: Conditional admin panel access based on user roles
🔧 Developer Experience
- Webhook Handlers: Pre-built endpoints for Clerk webhook events
- Utility Functions: Access control helpers and role checking utilities
- TypeScript Support: Full type safety with comprehensive TypeScript definitions
- Development Tools: Seeding endpoints and data refresh utilities
🚀 Installation
npm install payload-clerk-plugin
# or
pnpm add payload-clerk-plugin
# or
yarn add payload-clerk-plugin📋 Prerequisites
- Payload CMS v3.x
- Next.js 15+
- React 19+
- Clerk account with a configured application
⚙️ Configuration
1. Configure Payload
Add the plugin to your payload.config.ts:
import { buildConfig } from 'payload'
import { clerkPlugin } from 'payload-clerk-plugin'
export default buildConfig({
// ... your existing config
plugins: [
clerkPlugin({
// Required: Roles configuration
adminRoles: ['admin', 'super-admin'],
allRoles: ['admin', 'editor', 'super-admin'],
// Optional: Collection and endpoint configuration
userCollection: 'users', // default: 'users'
enabled: true, // default: true
// Optional: Custom endpoint paths
clerkConfig: {
adminBaseUrl: '/admin', // default: '/admin'
webhookPath: '/api/clerk/webhooks', // default: '/api/clerk/webhooks'
refreshPath: '/api/refresh-clerk-data', // default: '/api/refresh-clerk-data'
updateRolesPath: '/api/update-user-roles', // default: '/api/update-user-roles'
seedPath: '/api/seed', // default: '/api/seed' (dev only)
}
})
],
})2. Environment Variables
Create or update your .env.local:
# Payload
PAYLOAD_SECRET=your-payload-secret
# Clerk
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...
# Database
DATABASE_URI=mongodb://localhost:27017/your-db
# or for SQLite:
# DATABASE_URI=file:./database.db3. Set Up Next.js Layouts and Components
Root Layout (app/layout.tsx)
import { ClerkProvider } from '@clerk/nextjs'
import { ClerkUserButton } from 'payload-clerk-plugin/client'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<ClerkProvider>
<html>
<body>
<header>
<nav>
{/* Your navigation */}
<ClerkUserButton
adminAccessRoles={['admin', 'super-admin']}
adminBaseUrl="/admin"
/>
</nav>
</header>
{children}
</body>
</html>
</ClerkProvider>
)
}Authentication Pages
Create authentication pages using Clerk's pre-built components:
Sign In (app/login/[[...sign-in]]/page.tsx):
import { SignIn } from '@clerk/nextjs'
export default function Page() {
return <SignIn />
}Sign Up (app/register/[[...sign-up]]/page.tsx):
import { SignUp } from '@clerk/nextjs'
export default function Page() {
return <SignUp />
}User Profile (app/profile/[[...user-profile]]/page.tsx):
import { UserProfile } from '@clerk/nextjs'
export default function Page() {
return <UserProfile />
}Middleware (middleware.ts)
import { authMiddleware } from '@clerk/nextjs'
export default authMiddleware({
publicRoutes: ['/'],
// Protect admin routes
ignoredRoutes: ['/api/clerk/webhooks']
})
export const config = {
matcher: ['/((?!.+\\.[\\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
}🔧 Clerk Dashboard Setup
1. Create Clerk Application
- Go to Clerk Dashboard
- Create a new application
- Choose your preferred social providers
- Copy your API keys to
.env.local
2. Configure Webhooks
- In your Clerk Dashboard, go to Webhooks
- Create a new webhook endpoint:
https://yourdomain.com/api/clerk/webhooks - Subscribe to these events:
user.createduser.updateduser.deleted
- Copy the webhook secret to
CLERK_WEBHOOK_SECRETin your.env.local
3. Set Up User Metadata
Configure custom metadata fields in Clerk:
- Go to User & Authentication → Metadata
- Add public metadata field:
roles(array of strings) - This allows the plugin to manage user roles
4. Authentication Settings
Configure redirect URLs in Paths:
- Sign-in:
/login - Sign-up:
/register - User Profile:
/profile - Home:
/
🎯 Usage Examples
Access Control in Collections
// collections/Posts.ts
import { isAdminRoles } from 'payload-clerk-plugin/access'
export const Posts = {
slug: 'posts',
access: {
read: () => true,
create: isAdminRoles(['admin', 'editor']),
update: isAdminRoles(['admin', 'editor']),
delete: isAdminRoles(['admin'])
},
fields: [
// ... your fields
]
}Using Utility Functions
import { checkRoles } from 'payload-clerk-plugin/utilities'
import { currentUser } from '@clerk/nextjs/server'
export async function GET() {
const user = await currentUser()
if (!user || !checkRoles(['admin'], user.publicMetadata.roles)) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
// Admin-only logic here
return Response.json({ message: 'Success' })
}Custom Hooks Integration
// hooks/requireAuth.ts
import { setCreatedByOnCreate } from 'payload-clerk-plugin/hooks'
export const MyCollection = {
slug: 'my-collection',
hooks: {
beforeChange: [setCreatedByOnCreate]
},
fields: [
// ... your fields
]
}🏗️ Implementation Status
✅ Implemented Features
Core Clerk Integration
- User authentication strategy
- Webhook-based user synchronization
- Real-time data updates between Clerk and Payload
Role-Based Access Control
- Configurable admin and user roles
- Access control utilities and helpers
- Collection-level permission management
Admin Dashboard
- Custom Clerk Users management view
- Role management interface
- Enhanced navigation with conditional access
- Development tools and seeding utilities
Developer Tools
- TypeScript definitions and type safety
- Utility functions for access control
- Pre-built hooks for common patterns
- Comprehensive testing suite
🗺️ Roadmap
🔄 In Progress
- Enhanced Documentation: Comprehensive guides and examples
- Testing Coverage: Extended test suite and E2E testing
- Performance Optimizations: Caching and sync improvements
🎯 Planned Features
Multi-Tenancy Support
- Clerk Organizations Integration: Full organization-based multi-tenancy
- Tenant-Scoped Collections: Automatic data isolation per organization
- Organization Role Management: Advanced RBAC with organization context
- Tenant-Specific Admin Views: Organization-aware admin interface
Billing & Payments
- Clerk Billing Integration: Seamless subscription management
- Usage-Based Billing: Track and bill for resource usage
- Payment Webhooks: Automated subscription lifecycle handling
- Billing Dashboard: Admin interface for subscription management
Advanced Authentication
- Custom Scopes & Permissions: Request custom API scopes (Google Drive, Calendar, etc.)
- Access Token Management: Secure token storage and refresh handling
- OAuth Provider Extensions: Additional third-party authentication options
- Session Management: Advanced session controls and security policies
Internationalization
- i18n Support: Multi-language admin interface
- Localized Authentication: Region-specific auth flows
- Custom Translations: Plugin-specific translation keys
- RTL Language Support: Right-to-left language compatibility
📖 API Reference
Plugin Configuration
interface ClerkPluginConfig {
adminRoles?: string[] // Roles with admin access
allRoles?: string[] // All available system roles
userCollection?: string // Target user collection slug
enabled?: boolean // Enable/disable plugin
clerkConfig?: {
adminBaseUrl?: string // Admin panel base URL
webhookPath?: string // Clerk webhook endpoint
refreshPath?: string // Data refresh endpoint
updateRolesPath?: string // Role update endpoint
seedPath?: string // Seeding endpoint (dev only)
}
}Exported Utilities
// Access control functions
import {
isAdminRoles,
isAllowedRoles,
checkRoles
} from 'payload-clerk-plugin/access'
// Collection hooks
import {
setCreatedByOnCreate
} from 'payload-clerk-plugin/hooks'
// Field generators
import {
getCreatedByField
} from 'payload-clerk-plugin/fields'
// UI components
import {
ClerkUserButton,
AuthProvider
} from 'payload-clerk-plugin/client'🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
- Clone the repository
- Install dependencies:
pnpm install - Start development:
pnpm dev - Run tests:
pnpm test
📄 License
MIT License - see LICENSE for details.
🆘 Support
- GitHub Issues: Report bugs or request features
- Documentation: Payload CMS Docs
- Clerk Docs: Clerk Documentation
🙏 Acknowledgments
Built with ❤️ for the Payload CMS and Clerk communities.
Special thanks to the Payload team for their excellent plugin architecture and documentation.
