
Product
Introducing Webhook Events for Alert Changes
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.
@clocklimited/payload-2fa
Advanced tools
Add an extra security layer to PayloadCMS using a Time-based One-time Password (TOTP).
If you find this plugin useful, consider supporting its development through donations. Your contributions help improve security and stability!
TOTP is a widely used authentication mechanism that generates a unique, time-sensitive code based on a shared secret and the current time. This code is typically used as a second factor in authentication (2FA), adding an extra layer of security to protect against unauthorized access.
This plugin enhances security by wrapping the existing access controls under a TOTP verification process. Users must enter a valid TOTP code generated by an authenticator app (such as Google Authenticator, Authy, or Microsoft Authenticator) to gain access, reducing the risk of unauthorized logins even if credentials are compromised.
Install the plugin using any JavaScript package manager like pnpm, npm, or Yarn:
pnpm add @clocklimited/payload-2fa
In the plugins array of your Payload Config, call the plugin with options:
import { buildConfig } from 'payload'
import { payloadTotp } from '@clocklimited/payload-2fa'
const config = buildConfig({
collections: [
{
slug: 'users',
auth: true,
fields: [],
},
],
plugins: [
payloadTotp({
collection: 'users',
// see below for a list of available options
}),
],
})
export default config
IMPORTANT: The plugin overrides all collections, therefore it should be the last plugin in the array, or at least not followed by plugins that add collections/globals.
collectionThe collection property specifies which collection with auth enabled should have TOTP protection. Currently, the plugin supports TOTP for a single collection at a time.
disabledAllows you to conditionally disable the plugin based on runtime conditions.
forceSetupBy default, the plugin does not force users to configure TOTP. The TOTP verification will only be prompted if the user has configured it. This option forces all users to configure their TOTP after login, enhancing security by ensuring 2FA is enabled for all accounts.
disableAccessWrapperThe disableAccessWrapper property disables the default access wrapper for all collections and globals. Read more about it.
totpThe totp property is used to configure the TOTP class from the otpauth package. You can customize the following options:
algorithm: The hash algorithm to use (e.g. 'SHA1', 'SHA256', 'SHA512')digits: Number of digits in the generated token (default: 6)issuer: The issuer name to display in authenticator appsperiod: Token validity period in seconds (default: 30)By default, PayloadCMS has access set to ({user}) => Boolean(user). Since PayloadCMS naturally handles access for logged-in users, this plugin follows the same pattern.
The plugin will override the provided access function. This means that TOTP verifications will be called first, and if successful, it will then call the original function and return its result. This approach ensures compatibility with role-based access control and other custom access patterns.
There are cases where collections or globals need to be available for non-logged-in users. To handle this, the plugin provides disableAccessWrapper globally or per global/collection. If you have many collections/globals that provide custom access or public access, you should use the plugin options disableAccessWrapper.
In case of changing the default access, you can deactivate per collection/global:
import type { CollectionConfig } from 'payload'
export const posts: CollectionConfig = {
slug: 'posts',
access: {
read: () => true,
},
fields: [],
custom: {
totp: {
disableAccessWrapper: {
read: true,
},
},
},
}
The disableAccessWrapper from custom has the same type as access in Collection/Global based on the context.
In case that you need a more complex access, for example based on a header or auth user, you can import totpAccess:
import type { CollectionConfig } from 'payload'
import { totpAccess } from '@clocklimited/payload-2fa'
export const posts: CollectionConfig = {
slug: 'posts',
admin: {
useAsTitle: 'title',
},
access: {
read: (args) => {
return (
args.req.headers.get('authorization') === 'Bearer 123' ||
totpAccess(({ req: { user } }) => Boolean(user))(args)
)
},
},
fields: [],
custom: {
totp: {
disableAccessWrapper: {
read: true,
},
},
},
}
After logging in, navigate to your account settings where you'll find the "Authenticator app" field. If forceSetup is enabled, you'll be automatically redirected to the Setup TOTP page.
Click the "Setup" button to proceed to the Setup TOTP Page:
Scan the QR code or copy the secret into your preferred authenticator app, then enter the generated PIN code.
Upon successful verification, you'll be redirected back to your account page.
Now, when you log out and log back in, you'll be prompted to enter your TOTP PIN code:
After entering the correct PIN, you'll be redirected to the main dashboard page.
FAQs
Add an extra security layer to PayloadCMS using a Time-based One-time Password (TOTP).
We found that @clocklimited/payload-2fa demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.

Security News
ENISA has become a CVE Program Root, giving the EU a central authority for coordinating vulnerability reporting, disclosure, and cross-border response.

Product
Socket now scans OpenVSX extensions, giving teams early detection of risky behaviors, hidden capabilities, and supply chain threats in developer tools.