payload-workos-oauth
v2.0.0
Published
WorkOS OAuth plugin for Payload CMS v3 - adds Google OAuth login to your Payload admin panel
Maintainers
Readme
payload-workos-oauth
WorkOS OAuth plugin for Payload CMS - adds Google OAuth login to your Payload admin panel.
Version 2.0.0+ supports Payload CMS v3.72.0+ For Payload v2, use v1.x
Features
- 🔐 Google OAuth authentication via WorkOS
- 🎨 Clean, customizable login button
- 🔒 Admin-only access control
- 🍪 JWT-based authentication with secure cookies
- ⚡ No session middleware required
- 🎯 Easy integration with existing Payload CMS projects
- 🎭 Optional: Hide default email/password login form
Installation
For Payload v3 (Current)
npm install payload-workos-oauth@^2.0.0For Payload v2 (Legacy)
npm install payload-workos-oauth@^1.0.0Prerequisites
- A WorkOS account
- Google OAuth configured in your WorkOS dashboard
- Payload CMS v3.72.0 or higher (or v2.0.0+ for v1.x of this plugin)
Usage
1. Configure the plugin in your Payload config
import { buildConfig } from "payload";
import { workosOAuthPlugin } from "payload-workos-oauth";
export default buildConfig({
// ... other config
serverURL: process.env.PAYLOAD_PUBLIC_SERVER_URL,
admin: {
components: {
// Add the OAuth button to the login page
beforeLogin: ["payload-workos-oauth/BeforeLogin"],
},
},
plugins: [
workosOAuthPlugin({
clientID: process.env.WORKOS_CLIENT_ID || "",
clientSecret: process.env.WORKOS_API_KEY || "",
callbackURL: `${process.env.PAYLOAD_PUBLIC_SERVER_URL}/workos-oauth/callback`,
}),
],
});Important for Payload v3: You must add the BeforeLogin component to your admin.components.beforeLogin array as shown above. This is required for the button to appear on the login page.
2. Generate the import map (Required!)
After adding the component to your config, you must regenerate Payload's import map:
npm run generate:importmap
# or
pnpm generate:importmap
# or
yarn generate:importmapThis step is required for the button to appear on the login page.
3. Set environment variables
WORKOS_CLIENT_ID=your_workos_client_id
WORKOS_API_KEY=your_workos_api_key
PAYLOAD_PUBLIC_SERVER_URL=https://your-domain.com4. Configure WorkOS
In your WorkOS dashboard:
- Add a redirect URI:
https://your-domain.com/workos-oauth/callback - Enable Google OAuth provider
- Copy your Client ID and API Key
5. Ensure users have admin role
Only users with role: 'admin' can log in via OAuth. Make sure your users collection has this field configured.
Plugin Configuration Options
These options are passed to the workosOAuthPlugin() function:
| Option | Type | Required | Description |
| ----------------- | -------- | -------- | ----------------------------------------------------------------------- |
| clientID | string | Yes | Your WorkOS Client ID |
| clientSecret | string | Yes | Your WorkOS API Key |
| callbackURL | string | Yes | The OAuth callback URL |
| authorizePath | string | No | Custom authorization endpoint path (default: "/workos-oauth/authorize") |
| callbackPath | string | No | Custom callback endpoint path (default: "/workos-oauth/callback") |
| successRedirect | string | No | Custom redirect after login (default: "/admin") |
BeforeLogin Component Props
The BeforeLogin component accepts these optional props:
| Prop | Type | Default | Description |
| --------------- | --------- | ------------------------- | ------------------------------------------------- |
| authorizePath | string | "/workos-oauth/authorize" | Path to the authorization endpoint |
| buttonLabel | string | "Sign in with Google" | Text to display on the button |
| showDivider | boolean | true | Whether to show the "OR" divider below the button |
Customizing the Button
You can customize the button by creating a wrapper component:
// src/components/CustomOAuthButton.tsx
'use client'
import { BeforeLogin } from 'payload-workos-oauth'
export default function CustomOAuthButton() {
return (
<BeforeLogin
buttonLabel="Sign in with Work Email"
showDivider={false}
/>
)
}Then use it in your config:
admin: {
components: {
beforeLogin: ["@/components/CustomOAuthButton"],
},
}Hide Default Login Form
If you want to show only the OAuth button and hide the default email/password login form, you can:
- Set
showDivider={false}on the BeforeLogin component - Use CSS to hide the default form
// src/components/OAuthOnly.tsx
'use client'
import { BeforeLogin } from 'payload-workos-oauth'
export default function OAuthOnly() {
return (
<>
<BeforeLogin showDivider={false} />
<style>{`
.template-default form,
.template-default .form-submit {
display: none !important;
}
`}</style>
</>
)
}Then use it in your config:
admin: {
components: {
beforeLogin: ["@/components/OAuthOnly"],
},
}Custom Button Component
You can create a completely custom button component from scratch:
// src/components/MyCustomOAuthButton.tsx
'use client'
import React from 'react'
export default function MyCustomOAuthButton() {
const handleLogin = () => {
window.location.href = '/workos-oauth/authorize'
}
return (
<button onClick={handleLogin} className="my-custom-button">
🚀 Login with Google
</button>
)
}Then add it to your Payload config:
admin: {
components: {
beforeLogin: ["@/components/MyCustomOAuthButton"],
},
}How It Works
- User clicks "Sign in with Google" on the Payload admin login page
- User is redirected to WorkOS/Google OAuth
- User authenticates with Google
- WorkOS redirects back to your callback URL with an authorization code
- Plugin exchanges the code for user profile information
- Plugin finds the user in Payload by email (must have
role: 'admin') - Plugin generates a JWT token and sets a secure cookie
- User is redirected to the admin dashboard
Security
- Only users with
role: 'admin'can authenticate via OAuth - JWT tokens are signed with your Payload secret
- Cookies are set with
httpOnlyflag for security - All server-side modules are properly isolated from client bundle
License
MIT
Author
Bibek Thapa
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
