Authentication

Authentication your database understands

Email and password, four OAuth providers and anonymous users, issuing one session that your Postgres policies, functions and storage rules all trust.

Authentication product screenshot
configure-auth
volcano cloud config pull -f volcano-config.yaml# the auth block it writes out, edited to tasteauth:  signup:            { enable_signup: true, enable_anonymous_signins: true }  email_verification: { require_confirmation: true }  managed_pages:     { enabled: true }volcano cloud config deploy✓ auth configured · hosted login and reset pages live# auth.uid() now returns a real user inside every policy
Overview

What happens after the token is issued

Plenty of services will verify a password and hand back a token. The token then means nothing to your database, so you write a permission check in every handler and repeat it wherever data is read. One missed check in new code is a disclosure bug.

Volcano issues the session, and everything else reads it. The same access token sets auth.uid() inside a row-level policy, arrives in a function as a verified __volcano_auth object, and decides what a storage policy allows. You write the rule once, in SQL.

Identity

The same token, three enforcement points

Volcano installs auth.uid(), auth.email(), auth.role() and auth.is_authenticated() into every database, hands functions a verified identity on the event, and exposes the same helpers to storage policies. Authorization gets written once, in the layer that holds the data.

  • Postgres: policies filter rows with auth.uid()
  • Functions: event.__volcano_auth carries user_id and role
  • Storage: the same helpers decide who can read a path
one session, three checks
# access token for user 8f1c…postgres   auth.uid() → 8f1c…      12 of 1284 rowsfunction   __volcano_auth.role → authenticatedstorage    8f1c/report.pdf allowed · 9a2b/… refusedno permission code in between
Anonymous

Let people work before they sign up

Turn anonymous sign-ins on and a visitor gets a real user id immediately, covered by the same policies as everyone else. Converting to a permanent account keeps that id, so the work they already did stays theirs.

  • Opt-in, off until you enable it
  • Same row-level policies as signed-up users
  • convertAnonymous keeps the original user id
volcano.dev/dashboard/auth-settings
Auth settings with the anonymous sign-in switch and token lifetimes
Sessions

Sessions you can list and end

Access tokens are short-lived JWTs, and refresh tokens are held server-side, which is what makes them revocable. A user can see their devices and sign out one of them or all the others.

  • Access token 3600s default, 60s to 86400s
  • Refresh token 30 days, configurable to 90
  • Refresh reuse interval of 10 seconds
await volcano.auth.getSessions()
ses_91f4   macbook · safari      currentses_2c07   iphone · app          2 days agoses_74be   unknown · chrome      3 weeks agoawait volcano.auth.deleteAllOtherSessions()✓ 2 sessions revoked server-side
Capabilities

What authentication covers

Email and password

Signup, email verification, password reset by emailed link, and password change, each configurable per project.

OAuth providers

Google, GitHub, Microsoft and Apple, with linking and unlinking on an account that already exists.

Anonymous users

Opt-in sessions with a real user id that survives conversion into a permanent account.

Hosted pages

Login, password reset and device approval served for your project, with HTML and CSS you can replace.

Identity in Postgres

auth.uid(), auth.email(), auth.role() and auth.is_authenticated() are installed in every database.

Session control

List sessions, delete one, or delete all the others, with refresh tokens that rotate on use.

Code

Sign in, then let the policies do the work

TypeScript
import { VolcanoAuth } from '@volcano.dev/sdk'; const volcano = new VolcanoAuth({ apiUrl: process.env.NEXT_PUBLIC_VOLCANO_API_URL!, anonKey: process.env.NEXT_PUBLIC_VOLCANO_ANON_KEY!, }); const { confirmationRequired } = await volcano.auth.signUp({ email, password }); if (!confirmationRequired) { const { session, error } = await volcano.auth.signIn({ email, password }); } // OAuth redirects the browser, so these return nothing useful to await. volcano.auth.signInWithGoogle(); volcano.auth.signInWithOAuth('github'); // Start without an account, convert later, keep the same user id. await volcano.auth.signUpAnonymous(); await volcano.auth.convertAnonymous({ email, password }); const unsubscribe = volcano.auth.onAuthStateChange((user) => { if (!user) redirect('/login'); });
Use cases

What people build with it

same query, different users
# volcano.from('documents').select('*')ada@acme     →  14 rowsbob@globex   →   3 rowsanonymous    →   0 rowsone policy, no client-side filtering
Platform

Works with the rest of Volcano

Databases and vector
  • Row-level security

    auth.uid() and auth.role() are installed in every database, so a policy can be written on day one.

Functions and agents
  • Identity in handlers

    Functions receive __volcano_auth already validated, so there is no token verification to get wrong.

File storage
  • Storage policies

    Storage rules read the same helpers, so a browser can upload directly without a signing service.

Next.js frontends
  • Protected routes

    Middleware helpers validate the session at the edge, before a Next.js route renders.

Frequently asked questions

Read the docs
Which sign-in methods are supported?

Email and password with optional verification and reset by emailed link, OAuth with Google, GitHub, Microsoft and Apple, and opt-in anonymous users. Magic links, SMS codes, passkeys, TOTP and SAML are not supported.

How does the session reach my database?

Volcano passes the signed-in user into Postgres before your statement runs, which is what makes auth.uid(), auth.email() and auth.role() return real values inside a policy. The rule is written once in SQL, and every caller is held to it.

How long do tokens last?

The access token is a JWT valid for 3600 seconds by default and configurable from 60 seconds to 86400. Refresh tokens default to 30 days, range from one hour to 90 days, and rotate with a 10-second reuse interval.

Can I use my own login screen?

Yes. Build it against signIn, signUp, signInWithOAuth, forgotPassword and resetPassword, take the hosted pages as they are, or keep the hosted flow and replace its HTML and CSS.

What is the difference between the anon key and the service key?

The anon key identifies the project and is safe to ship in a browser, with the user's JWT alongside it. The service key acts as service_role, bypasses row-level security, and belongs on a server only.

How do I connect my own tables to a user?

Store the id that auth.uid() returns. A user_id uuid column plus a policy comparing it to auth.uid() is the whole join, and the same id reaches functions as __volcano_auth.user_id and storage policies as auth.uid().

Ready to add authentication?

Build, deploy, and scale on Volcano's global platform — free to start, with no infrastructure to manage.

Checkout more features