Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Authentication Server Functions

Payload provides login, logout, and refresh server functions that manage authentication cookies for you. Each function requires your Payload config, so it must run on the server.

The examples below expose the same call signatures for Next.js and TanStack Start:

  • loginAction({ email, password })
  • logoutAction()
  • refreshAction()

Next.js

Import the helpers from @payloadcms/next/auth in a file marked with 'use server':

1
'use server'
2
3
import { login, logout, refresh } from '@payloadcms/next/auth'
4
import config from '@payload-config'
5
6
type LoginArgs = {
7
email: string
8
password: string
9
}
10
11
export function loginAction({ email, password }: LoginArgs) {
12
return login({
13
collection: 'users',
14
config,
15
email,
16
password,
17
})
18
}
19
20
export function logoutAction() {
21
return logout({ config })
22
}
23
24
export function refreshAction() {
25
return refresh({ config })
26
}

TanStack Start

Import the helpers from @payloadcms/tanstack-start/server inside each createServerFn handler:

1
import { createServerFn } from '@tanstack/react-start'
2
3
type LoginArgs = {
4
email: string
5
password: string
6
}
7
8
const loginServerFn = createServerFn({ method: 'POST' })
9
.validator((data: LoginArgs) => data)
10
.handler(async ({ data }) => {
11
const [{ login }, { default: config }] = await Promise.all([
12
import('@payloadcms/tanstack-start/server'),
13
import('@payload-config'),
14
])
15
16
await login({
17
collection: 'users',
18
config,
19
email: data.email,
20
password: data.password,
21
})
22
})
23
24
const logoutServerFn = createServerFn({ method: 'POST' }).handler(async () => {
25
const [{ logout }, { default: config }] = await Promise.all([
26
import('@payloadcms/tanstack-start/server'),
27
import('@payload-config'),
28
])
29
30
return logout({ config })
31
})
32
33
const refreshServerFn = createServerFn({ method: 'POST' }).handler(async () => {
34
const [{ refresh }, { default: config }] = await Promise.all([
35
import('@payloadcms/tanstack-start/server'),
36
import('@payload-config'),
37
])
38
39
return refresh({ config })
40
})
41
42
export function loginAction(data: LoginArgs) {
43
return loginServerFn({ data })
44
}
45
46
export function logoutAction() {
47
return logoutServerFn()
48
}
49
50
export function refreshAction() {
51
return refreshServerFn()
52
}

Client Usage

The normalized functions can be called the same way from event handlers in either framework:

1
'use client'
2
3
import { loginAction } from './actions'
4
5
async function handleLogin({
6
email,
7
password,
8
}: {
9
email: string
10
password: string
11
}) {
12
try {
13
await loginAction({ email, password })
14
} catch (error) {
15
// Display the error to the user
16
}
17
}

All three functions reject when the operation fails. Use the same try/catch pattern for refreshAction and logoutAction so failures do not become unhandled promise rejections.

Was this page helpful?

Next

Authentication Emails