Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A Payload CMS 3 plugin for Auth.js/NextAuth 5

License

NotificationsYou must be signed in to change notification settings

CrawlerCode/payload-authjs

Repository files navigation

payload-authjs banner

Payload CMS plugin for Auth.js/NextAuth

GitHub Actions Workflow StatusNPM VersionNPM LicenseNPM Downloads

APayload CMS 3 plugin for integratingAuth.js 5 (beta).

⚠ This plugin and Auth.js 5 is in beta and may have some bugs. Please report any issues you find.

⚡ How it works

This plugin

  • creates ausers collection in Payload CMS.
  • use an customDatabase Adapter for Auth.js to store the users in the Payload CMS database.
  • use a customAuth Strategy for Payload CMS to retrieve the session from Auth.js.

⚙️ Installation / Setup

Install the plugin using any JavaScript package manager such as PNPM, NPM, or Yarn:

pnpm i payload-authjs

1. Setup Auth.js

First of all, this plugin only integrates Auth.js into Payload CMS by getting the user session from Auth.js. It doesn't handle the Auth.js stuff. You need to setup Auth.js before you can use this plugin.

1.1. Create your Auth.js configuration

Define your Auth.js configuration in a file (e.g.auth.config.ts):

// auth.config.tsimporttype{NextAuthConfig}from"next-auth";importgithubfrom"next-auth/providers/github";exportconstauthConfig:NextAuthConfig={providers:[github,// <-- Add your provider here],};

1.2. Create your Auth.js instance

Next, create your Auth.js instance in a file (e.g.auth.ts). But before creating the Auth.js instance, you need to wrap your Auth.js configuration with thewithPayload function:

// auth.tsimportpayloadConfigfrom"@payload-config";importNextAuthfrom"next-auth";import{withPayload}from"payload-authjs";import{authConfig}from"./auth.config";// ⚠ Import the config from a separate fileexportconst{ handlers, signIn, signOut, auth}=NextAuth(withPayload(authConfig,{    payloadConfig,}),);

⚠ Make sure you define your config in a separate file than where you create the NextAuth instance to avoid circular dependencies.

1.3. Add Auth.js route handler

Add the Auth.js route handler under/app/api/auth/[...nextauth]/route.ts:

// app/api/auth/[...nextauth]/route.tsimport{handlers}from"@/auth";exportconst{GET,POST}=handlers;

1.4. Add Auth.js middleware (optional)

Add optionalmiddleware.ts to keep the session alive, this will update the session expiry each time it's called.

⚠ Unlike what you would normally do in Auth.js, you cannot use themiddleware of@/auth directly. You have to create a new Auth.js instance without thewithPayload wrapper to beedge-compatible.

// middleware.tsimportNextAuthfrom"next-auth";import{authConfig}from"./auth.config";exportconst{auth:middleware}=NextAuth(authConfig);exportconstconfig={matcher:["/((?!api|_next/static|_next/image|favicon.ico|admin/login).*)"],};

2. Add the payload-authjs plugin to Payload CMS

And finally, add theauthjsPlugin to your Payload configuration file:

// payload.config.tsimport{authjsPlugin}from"payload-authjs";import{authConfig}from"./auth.config";exportconstconfig=buildConfig({plugins:[authjsPlugin({authjsConfig:authConfig,}),],});

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 users collection. This plugin automatically creates a collection with the slugusers.


🪄 Getting the payload session

This plugin also provides some utility functions to get the current payload session/user within your Next.js application.

Server side (getPayloadSession)

Instead of using theauth function of Auth.js, you can use thegetPayloadSession function to get the current session in the server-side code (e.g. in RSC or API routes):

// ServerComponentExample.tsximport{getPayloadSession}from"payload-authjs";constServerComponentExample=async()=>{constsession=awaitgetPayloadSession();return(<><h3>Payload CMS User:</h3><pre>{JSON.stringify(session?.user)}</pre></>);};

Client side (usePayloadSession)

Instead of using theuseSession hook of Auth.js, you can use theusePayloadSession hook to get the current session in the client-side code:

Before you can use theusePayloadSession hook, you need to wrap your app with thePayloadSessionProvider:

// layout.tsximport{PayloadSessionProvider}from"payload-authjs/client";import{getPayloadSession}from"payload-authjs";constLayout:React.FC<{children:React.ReactNode}>=async({ children})=>{return(<htmllang="en"><body><PayloadSessionProvidersession={awaitgetPayloadSession()}>{children}</PayloadSessionProvider></body></html>);};exportdefaultLayout;

ℹ️ Passing the session to thePayloadSessionProvider is optional, but it can be useful to avoid loading states.

You are now ready to use theusePayloadSession hook in your client-side code:

// ClientComponentExample.tsx"use client";import{usePayloadSession}from"payload-authjs/client";exportconstClientComponentExample=()=>{const{ session}=usePayloadSession();return(<><h3>Payload CMS User:</h3><pre>{JSON.stringify(session?.user)}</pre></>);};

Within Payload CMS

Click to expand

Within the Payload admin panel (useAuth)

If you want to access the current user in the Payload admin panel e.g. in a custom component. You can use theuseAuth hook from Payload CMS:

"use client";import{Banner,useAuth}from"@payloadcms/ui";importtype{User}from"@/payload-types";exportconstCustomAdminComponent=()=>{const{ user}=useAuth<User>();if(!user){returnnull;}return<Bannertype="success">Hi,{user.name}</Banner>;};

Inside access control operations (req.user)

Simply use thereq.user object to determine the current user:

constExamples:CollectionConfig={slug:"examples",access:{read:({req:{ user}})=>{returnBoolean(user)// <-- Check if the user is authenticated},},fields:[    ...],};

Inside custom endpoints (req.user)

Simply use thereq.user object to determine the current user:

constExamples:CollectionConfig={slug:"examples",fields:[    ...],endpoints:[{method:"get",path:"/example",handler:(req)=>{returnResponse.json(req.user);// <-- Return the user object},},],};

🛠️ Advanced usage / Customization

If you want to customize the users collection, you can create a collection with the slugusers and add your customizations there.

// users.tsconstUsers:CollectionConfig={slug:"users",fields:[],};

✏️ Customize existing fields

Click to expand

You can customize the existing fields in the users collection by adding the field to the collection and modifying the field. The fields are merged together.

// users.tsconstUsers:CollectionConfig={slug:"users",fields:[{name:"id",type:"text",label:"Identifier",// <-- Add a label to the id fieldadmin:{hidden:true,// <-- Hide id field in admin panel},},{name:"accounts",type:"array",fields:[{name:"provider",type:"text",label:"Account Provider",// <-- Add label to provider field},],},],};

✨ Add additional fields

You can also add additional fields to the users collection.

Click to expand

There are 2 ways to add additional fields. It depends on the data you want to store and yourAuth.js session strategy (session.strategy).

1. Database fields (jwt session & database session)

If you want to store additional data in the database, you can add a new field to the users collection and extend your Auth.js provider to include the new field in the user.

For example, you could add alocale field to the users collection:

// users.tsconstUsers:CollectionConfig={slug:"users",fields:[// Add custom field for 'locale'{name:"locale",type:"text",},],};

Next, you need to extend the user object returned by your Auth.js provider. You can do this as shown in this example:

// auth.config.tsconstauthConfig:NextAuthConfig={providers:[keycloak({/**       * Add additional fields to the user on first sign in       */profile(profile){return{// Default fields from keycloak providerid:profile.sub,name:profile.name,email:profile.email,image:profile.picture,// Custom fieldslocale:profile.locale,// <-- Add your custom field (e.g. get locale from the profile)};},}),],  ...};

⚠ Note 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 thesignIn event. (SeeEvents)

2. Virtual fields (jwt session only)

If you are using the Auth.jsjwt session strategy (it's the default), you can use avirtual field to add additional data that should not be stored in the database.This plugin extracts the virtual fields from your Auth.js jwt session (if available) and adds them to the user object.

For example, you could add aroles field to the users collection:

// users.tsconstUsers:CollectionConfig={slug:"users",fields:[// Add custom field for 'roles'{name:"roles",type:"json",virtual:true,// <-- Make the field virtualadmin:{hidden:true,},},],};

This plugin can only get the virtual fields, ifthey are included in the Auth.js session. So you need to extend your Auth.js token and session with your field.

You can do this as shown in this example:

// auth.config.tsconstauthConfig:NextAuthConfig={callbacks:{jwt:({ token, trigger})=>{// Add the virtual field to the token only on signIn/signUp (jwt callback will be called multiple times)if(trigger==="signIn"||trigger==="signUp"){token.roles=["example-role"];// <-- Add your virtual field to the token}returntoken;},session:({ session, token})=>{if(token){session.user.roles=token.roles;// <-- Forward the virtual field from the token to the session}returnsession;},},  ...};

At this point, you can implement your own logic to extend the session. For example extract from profile, fetch from a server, or something else.

More information about extending your session can be found in theAuth.js documentation.

Using custom fields

Now you can access your custom field, e.g. in the access control operations or elsewhere:

constExamples:CollectionConfig={slug:"examples",access:{read:({req:{ user}})=>{returnuser?.roles?.includes("user")??false;// <-- Check if the user has the role "user"},},fields:[    ...],};

🟦 Typescript

If you are using typescript you can declare your Auth.js user type as shown in the following example:

// auth.config.tsimporttype{PayloadAuthjsUser}from"payload-authjs";importtype{UserasPayloadUser}from"@/payload-types";declare module"next-auth"{interfaceUserextendsPayloadAuthjsUser<PayloadUser>{}}

More information about typescript can be found in theAuth.js documentation.

🎉 Events

Auth.js emits someevents that you can listen to. This plugin extends the events with additional parameters such as theadapter andpayload instance.

More information about the events can be found in theAuth.js documentation.

The following events are available:

  • signIn
  • signOut
  • createUser
  • updateUser
  • linkAccount
  • session

signIn Event

ThesignIn event is fired when a user successfully signs in. For example, you could use this event to update the user's name on every sign-in:

// auth.tsexportconst{ handlers, signIn, signOut, auth}=NextAuth(withPayload(authConfig,{    payloadConfig,events:{/**       * Update user 'name' on every sign in       */signIn:async({ adapter, user, profile})=>{if(!user.id||!profile){return;}awaitadapter.updateUser!({id:user.id,name:(profileasunknownasGitHubProfile).name??(profileasunknownasGitHubProfile).login,email:profile.email??undefined,image:(profileasunknownasGitHubProfile).avatar_url,});},},}),);

📓 Examples


[8]ページ先頭

©2009-2025 Movatter.jp