Guide

Authentication

Forward the user's JWT so PostgREST row-level security applies.

PostgREST authorizes each request with a JWT: its role claim picks the Postgres role and its other claims are readable in RLS policies. Nuxt PostgREST's job is getting the right JWT onto each request.

With nuxt-auth-utils

If nuxt-auth-utils is installed, it's detected automatically — no config needed. After your login flow mints a PostgREST JWT, store it in the session under postgrest_token (configurable with tokenKey):

server/api/login.post.ts
export default defineEventHandler(async (event) => {
  // ...verify credentials, then sign a JWT with your PGRST_JWT_SECRET
  const token = await signPostgrestJwt({ role: 'authenticated', sub: user.id })

  await setUserSession(event, {
    user: { id: user.id, name: user.name },
    postgrest_token: token,
  })
})

Where you store it decides who can use it:

Stored atusePostgrest() (client + SSR)usePostgrestUser() (server)
session.postgrest_token✅✅
session.secure.postgrest_token❌✅
If you only query from server routes, store the token under secure. It never reaches the browser, and the browser never talks to PostgREST directly.

Type the session field so it autocompletes:

shared/types/auth.d.ts
declare module '#auth-utils' {
  interface UserSession {
    postgrest_token?: string
  }
}
export {}

With any other auth library

nuxt-auth-utils is the only auth library this module knows about. Anything else — Better Auth, a custom session, your own JWT issuer — isn't special-cased: write a small function that pulls the token out of your session however that library exposes it, and pass the result in yourself:

const postgrest = usePostgrest({ token: myAuth.accessToken })
server/api/todos.get.ts
export default defineEventHandler(async (event) => {
  const token = await getTokenSomehow(event)
  const postgrest = await usePostgrestUser(event, { token })
  // ...
})

Anonymous requests

With no token, the client falls back to the public key, and with no key it sends no Authorization header at all. PostgREST then runs the query as its db-anon-role.

Token expiry

The module does not refresh tokens. If your PostgREST JWTs expire, reissue them in your auth flow (for example on session refresh) and update the session field. A 401 with PGRST301 from PostgREST means the token expired or is invalid.

Copyright © 2026