Skip to content

User Authentication

PocketBase ships with a complete authentication system out of the box: email/password login, OAuth2 providers (Google, GitHub, and more), email verification, password reset, one-time passwords (OTP), and multi-factor authentication (MFA) — no extra services required.

Two kinds of login: app users and superusers

“PocketBase login” means one of two things, and they use different collections:

App users Superusers (dashboard admins)
Collection users (or any auth collection you create) _superusers
Where they log in Your app, through the SDK The dashboard at https://<instance-name>.pocketbasecloud.com/_/
Access Whatever your API rules allow Everything — rules are bypassed

There is no default superuser login in PocketBase. A self-hosted instance prints a one-time installer link on first start, or you create one with ./pocketbase superuser upsert EMAIL PASS. On PocketBase Cloud every instance is created with a platform-managed superuser — your account email plus a generated password, shown on the instance page and by pbc pocketbase info --name <instance>. Forgot it? Reset it without the old password: see Upserting a Superuser Credential.

Superusers can also authenticate from code, for scripts and server-side jobs:

await pb.collection("_superusers").authWithPassword("[email protected]", "password");

Never ship superuser credentials to a browser or mobile app — use them only on a server you control.

Auth collections

Users live in auth collections. Every instance starts with a built-in users collection, and you can create additional ones (e.g., staff) if you need separate user types.

Email / password auth

Register a user

await pb.collection("users").create({
  email: "[email protected]",
  password: "s3cr3t-password",
  passwordConfirm: "s3cr3t-password",
});

Log in

const authData = await pb
  .collection("users")
  .authWithPassword("[email protected]", "s3cr3t-password");

console.log(pb.authStore.isValid); // true
console.log(pb.authStore.token);   // JWT
console.log(pb.authStore.record);  // the user record

The SDK stores the token in pb.authStore (backed by localStorage in the browser) and automatically sends it with every subsequent request.

Log out

pb.authStore.clear();

OAuth2 login (Google, GitHub, …)

Using the portal

  1. Open your instance’s admin panel at https://<instance-name>.pocketbasecloud.com/_/
  2. Go to Collections → users → Options → OAuth2
  3. Enable a provider and paste in its client ID and secret

Using the CLI

pbc admin use https://<instance-name>.pocketbasecloud.com
pbc admin login

pbc admin auth users config    # show authRule, oauth2, passwordAuth, mfa, otp, …

pbc admin auth users config --set 'oauth2={"enabled":true,"providers":[
  {"name":"google",
   "clientId":"<GOOGLE_CLIENT_ID>.apps.googleusercontent.com",
   "clientSecret":"<GOOGLE_CLIENT_SECRET>"}]}'

--set replaces that field entirely. To add a second provider, run pbc admin auth users config first and include every provider you want to keep in the JSON you send — otherwise the ones you omit are removed.

The same command edits the rest of the collection’s auth settings — for example, turning password login off once OAuth2 works:

pbc admin auth users config --set 'passwordAuth={"enabled":false}'

Then in your app the whole flow is one call:

const authData = await pb
  .collection("users")
  .authWithOAuth2({ provider: "google" });

PocketBase opens the provider’s consent screen, handles the redirect, and creates the user record on first login.

Tip: when registering the OAuth app with the provider, use https://<instance-name>.pocketbasecloud.com/api/oauth2-redirect as the redirect URL.

Single sign-on (SSO)

For company SSO, use the OpenID Connect provider in the same OAuth2 list. Any OIDC-compliant identity provider — Okta, Auth0, Keycloak, Microsoft Entra ID, Authentik — plugs in with its client ID, secret, and auth/token/userinfo URLs, and your app calls authWithOAuth2 exactly as above. PocketBase has no SAML support; if your identity provider only speaks SAML, put an OIDC bridge (Keycloak, Authentik) in front of it.

One-time passwords (OTP)

OTP login emails the user a short code instead of asking for a password — useful for passwordless sign-in. Enable it in the dashboard under Collections → users → Options → One-time password (OTP), and make sure mail settings are configured so the code can be sent.

// 1. email a code to the user
const { otpId } = await pb.collection("users").requestOTP("[email protected]");

// 2. exchange the code the user typed for an auth token
await pb.collection("users").authWithOTP(otpId, "123456");

requestOTP returns an otpId even when the email doesn’t exist, so the endpoint doesn’t leak which addresses have accounts. A successful OTP login also marks the email as verified. Short numeric codes can be guessed, so for anything sensitive pair OTP with a second factor (below) rather than using it alone.

Multi-factor authentication (MFA)

MFA requires two different auth methods in a row — for example a password and then an emailed OTP. Enable OTP and Multi-factor authentication under Collections → users → Options. The first login then fails with an mfaId, which you pass to the second method:

try {
  await pb.collection("users").authWithPassword("[email protected]", "s3cr3t-password");
} catch (err) {
  const mfaId = err.response?.mfaId;
  if (!mfaId) throw err; // wrong password or another error

  const { otpId } = await pb.collection("users").requestOTP("[email protected]");
  const code = prompt("Enter the code we emailed you"); // your own UI here
  await pb.collection("users").authWithOTP(otpId, code, { mfaId });
}

Editing OTP or MFA from the terminal works too — pbc admin auth users config shows the otp and mfa fields. Because --set replaces a field entirely, copy the current JSON and change only what you need.

Email verification and password reset

PocketBase generates the verification and reset flows for you:

// send a verification email
await pb.collection("users").requestVerification("[email protected]");

// send a password reset email
await pb.collection("users").requestPasswordReset("[email protected]");

Email templates and the sender address can be customized in the admin panel under Settings → Mail settings, or from the terminal:

pbc admin settings mail                        # current SMTP config
pbc admin settings mail set '<json>'
pbc admin settings mail test [email protected]   # send a test message

The verification and reset templates live on the auth collection itself, so they’re edited with pbc admin auth users config --set 'verificationTemplate={…}'.

Protecting data per user

Combine auth with API rules to scope records to their owner. A common pattern is an owner relation field on the collection with rules like:

@request.auth.id != "" && owner = @request.auth.id

Next steps