A Payload CMS 3 (beta) plugin for integrating Auth.js 5 (beta).
⚠ This plugin is in beta and under construction. Payload CMS 3 and Auth.js 5 are also in beta. Use at your own risk.
Install the plugin using any JavaScript package manager like PNPM, NPM, or Yarn:
pnpm i payload-authjs
Add the authjsPlugin
in your Payload configuration file:
// payload.config.ts
import { authjsPlugin } from "payload-authjs";
import { authConfig } from "./auth.config";
export const config = buildConfig({
plugins: [
authjsPlugin({
authjsConfig: authConfig,
}),
]
});
Wrap your Auth.js configuration with the withPayload
function before creating the NextAuth instance:
// auth.ts
import payloadConfig from "@payload-config";
import NextAuth from "next-auth";
import { withPayload } from "payload-authjs";
import { authConfig } from "./auth.config";
export const { handlers, signIn, signOut, auth } = NextAuth(
withPayload(authConfig, {
payloadConfig,
}),
);
⚠ Make sure you define your
authConfig
in a separate file than where you use thewithPayload
function to avoid circular dependencies.
Create a new middleware
or wrap your existing middleware, e.g. the Auth.js middleware:
// middleware.ts
export { default } from "payload-authjs/middleware";
// middleware.ts
import NextAuth from "next-auth";
import middleware from "payload-authjs/middleware";
import { authConfig } from "./auth.config";
const { auth } = NextAuth(authConfig);
export default middleware(auth);
And that's it! Now you can sign-in via Auth.js and you are automatically authenticated in Payload CMS. Nice 🎉
You don't need to create a collection for users. This plugin automatically creates a collection with the slug users
.
But if you want to customize the users collection, you can create a collection with the slug users
and add the fields you need.
// users.ts
import type { CollectionConfig } from "payload";
const Users: CollectionConfig = {
slug: "users",
fields: [
{
name: "roles",
type: "json",
},
],
};
export default Users;
Next, you need to extend the user object returned by your Auth.js provider. You can do this like this example:
const authConfig: NextAuthConfig = {
providers: [
github({
profile(profile) {
return {
id: profile.id.toString(),
name: profile.name,
email: profile.email,
image: profile.avatar_url,
roles: ["user"], // <-- Extend the user object with a custom field
};
},
}),
],
...
};
⚠ Keep in mind that Auth.js doesn't update the user after the first sign-in. If you want to update the user on every sign-in, you can use the updateUserOnSignIn
option in the withPayload
function:
// auth.ts
export const { handlers, signIn, signOut, auth } = NextAuth(
withPayload(authConfig, {
payloadConfig,
updateUserOnSignIn: true, // <-- Update the user on every sign-in
}),
);
Now you could access your custom field, e.g. in the access control operations:
const Examples: CollectionConfig = {
slug: "examples",
access: {
read: ({ req: { user } }) => {
return user?.roles?.includes("user") ?? false; // <-- Check if the user has the role "user"
},
},
fields: [
...
],
};
This plugin also export a utility function to get the current payload user
// ServerComponentExample.tsx
const ServerComponentExample = async () => {
const payloadUser = await getPayloadUser<DataFromCollectionSlug<"users">>();
return (
<div>
<h3>Payload CMS User</h3>
<div>
{JSON.stringify(payloadUser)}
</div>
</div>
);
};