Plugin Setup

TIP: Checkout the example project to learn more about the setup and usage pattern



The steps below outline how to set up the plugin for admin authentication.


1. Environment Variables

Create a .env file in the root of your project and add the following environment variables:


txt.env
            PAYLOAD_SECRET=
NEXT_PUBLIC_SERVER_URL=

PAYLOAD_AUTH_SECRET=
NEXT_PUBLIC_PAYLOAD_AUTH_URL=

        

TIP: To generate secrets you can run openssl rand -base64 32 command in your terminal to generate unique random base64 string.



2. Collection

2.1. Users Collection

Use the withUsersCollection function imported from the package. This function accepts a CollectionConfig object as its argument. While it's not mandatory to create the users collection using this function, if you do, make sure not to set auth: true, as the function adds custom authentication fields that may conflict with Payload's built-in authentication system.


tssrc/collections/Auth/Users.ts
            import { CollectionConfig } from "payload";
import { withUsersCollection } from "payload-auth-plugin/collection";

export const Users: CollectionConfig = withUsersCollection(
  {
    slug: "users",
    admin: {
      defaultColumns: ['fullName', 'email'],
      useAsTitle: 'email',
    },
    fields: [
      {
        name: 'email',
        type: 'email',
        required: true,
        label: 'Email',
      },
      {
        name: 'last_name',
        label: 'Last Name',
        type: 'text',
      },
      {
        name: 'first_name',
        label: 'First Name',
        type: 'text',
      },
    ],
    timestamps: true,
  }
);

        


2.2. Accounts Collection

Use the withAccountCollection function imported from the plugin. This function takes the CollectionConfig and Users collection slug as arguments.


tssrc/collections/Auth/Accounts.ts
            import { CollectionConfig } from "payload";
import { withAccountCollection } from 'payload-auth-plugin/collection'
import { Users } from "@/collections/Auth/Users";

export const Accounts: CollectionConfig = withAccountCollection(
  {
    slug: "accounts",
  },
  Users.slug
);

        


2.3. Hook

The deleteLinkedAccounts hook can be used to delete all accounts that belongs to an user when a user is being removed.


tssrc/collections/Auth/Users.ts
            import { CollectionConfig } from "payload";
import { withUsersCollection } from 'payload-auth-plugin/collection'
import { deleteLinkedAccounts } from 'payload-auth-plugin/collection/hooks'
import { Accounts } from '@/collections/Auth/Accounts'

export const Users: CollectionConfig = withUsersCollection(
  {
    //---rest of the config---
    hooks: {
        afterDelete: [deleteLinkedAccounts(Accounts.slug)],
    },
  },
);

        


3. Plugin Setup

In the Payload CMS config file, import the Payload Auth plugin, and add it to the plugins array:


tssrc/payload.config.ts
            import { buildConfig } from "payload/config";
import { authPlugin } from 'payload-auth-plugin'
import {
  Auth0AuthProvider,
  GoogleAuthProvider,
  PasswordProvider,
} from 'payload-auth-plugin/providers'
import { Accounts } from '@/collections/Auth/Accounts'
import { Users } from '@/collections/Auth/Users'

export default buildConfig({
  // --- rest of the config
  serverURL: process.env.NEXT_PUBLIC_SERVER_URL,
  collections: [
    // --- rest of the collections
      Accounts,
      Users,
    ],
  plugins: [
    // --- rest of the plugins
    authPlugin({
      name: 'admin', // must be unique
      useAdmin: true, // not mandatory, and only use this for admin
      allowOAuthAutoSignUp: true,
      usersCollectionSlug: Users.slug,
      accountsCollectionSlug: Accounts.slug,
      successRedirectPath: '/admin/collections',
      errorRedirectPath: '/admin/auth/signin',
      providers: [
        GoogleAuthProvider({
          client_id: process.env.GOOGLE_CLIENT_ID as string,
          client_secret: process.env.GOOGLE_CLIENT_SECRET as string,
        }),
        Auth0AuthProvider({
          domain: process.env.AUTH0_DOMAIN as string,
          client_id: process.env.AUTH0_CLIENT_ID as string,
          client_secret: process.env.AUTH0_CLIENT_SECRET as string,
        }),
      ],
    }),
  ],
});

        


4. Admin Client Components

Create the auth client


tssrc/lib/auth.ts
            import { AuthClient } from 'payload-auth-plugin/client'

export const adminAuthClient = new AuthClient('admin')

        

Signin component

Create an auth component for the signin page.


tsxsrc/components/AfterLogin/index.tsx
            'use client'
import React from 'react'
import { Button } from '@payloadcms/ui'
import './styles.scss'
import { adminAuthClient } from '@/lib/auth'

export const AdminLogin = () => {
  const { oauth } = adminAuthClient.signin()

  const handleGoogleSignin = async () => {
    oauth('google')
  }
  const handleAuth0Signin = async () => {
    oauth('auth0')
  }
  return (
    <div className="oauth-container">
      <Button type="button" onClick={handleGoogleSignin} className="oauth-btn">
        Signin with Google
      </Button>
      <Button type="button" onClick={handleAuth0Signin} className="oauth-btn">
        Signin with Auth0
      </Button>
    </div>
  )
}

        

Add some styles


scsssrc/components/AfterLogin/styles.scss
            @import '~@payloadcms/ui/scss';

.oauth-container {
  display: flex;
  width: 100%;
  flex-direction: column;
  column-gap: 4px;
}
.oauth-btn {
  padding-block: 8px;
  width: 100%;
}

        

Finally, import the custom login component in your Payload config.


tssrc/payload.config.ts
            export default buildConfig({
  // --- rest of the config
  admin: {
    // --- rest of the admin config
    components: {
      afterLogin: ['@/components/AfterLogin/index#AdminLogin'],
    },
  },
});

        

Now, go to /admin/login path to test the custom login component.


Follow this example project to setup and use the plugin for both the front-end app and the admin app.



Session and signout

Server side session

Use the auth client to get user's session in the server side. It is required to pass request headers as an argument


tssrc/app/(frontend)/[slug
            import { adminAuthClient } from '@/lib/auth';
import { headers } from 'next/headers'

const session = await adminAuthClient.getSession(
  { 
    headers: await headers()
  }
)

if (session.isError) {
  redirect('/auth/signin')
}

        

Client side session

Use auth client to create a hook to get user's session in the client side.

tssrc/hooks/session.ts
            import { adminAuthClient } from '@/lib/auth'
import { useEffect, useState } from 'react'

export const useSession = () => {
  const [loading, setLoading] = useState<boolean>()
  const [session, setSession] = useState({
    data: {},
    message: '',
    isSuccess: false,
  })

  useEffect(() => {
    setLoading(true)
    const fetchSession = async () => {
      const { data, isSuccess, message } = await adminAuthClient.getClientSession()

      if (!isSuccess) {
        setSession({
          data: {},
          message,
          isSuccess,
        })
      }

      setSession({
        data,
        message,
        isSuccess,
      })
      setLoading(false)
    }
    fetchSession()
  }, [])

  return {
    loading,
    ...session,
  }
}

        

tssrc/app/(frontend)/[slug
            "use client";

import { useSession } from '@/hooks/session'

const { isSuccess, loading, data } = useSession()

        

Signout

Use the auth client for signout


tssrc/app/(frontend)/[slug
            import { adminAuthClient } from '@/lib/auth';

const handleSignOut = async () => {
  await adminAuthClient.signout({ returnTo: '/auth/signin' })
}