Supabase Auth Hooks
Fail-closed sign-up verification and JWT assurance claims for Supabase Auth and Postgres RLS.
Install the Auth Hooks package
terminal
npm install @decionis/presence-authCreate the sign-up gate
supabase-hooks.ts
import { createSupabaseBeforeUserCreatedHook } from "@decionis/presence-auth/supabase"; const hook = createSupabaseBeforeUserCreatedHook({ apiHost: "https://presence.decionis.com", apiSecret: process.env.PRESENCE_API_SECRET!, signingSecret: process.env.SUPABASE_HOOK_SECRET!,}); export async function POST(request: Request) { const result = await hook({ headers: Object.fromEntries(request.headers), rawBody: await request.text(), }); return Response.json(result.body, { status: result.status });}Register both Auth Hooks
supabase/config.toml
[auth.hook.before_user_created]enabled = trueuri = "https://hooks.example.com/before-user-created"secrets = "env(SUPABASE_HOOK_SECRET)" [auth.hook.custom_access_token]enabled = trueuri = "https://hooks.example.com/custom-access-token"secrets = "env(SUPABASE_HOOK_SECRET)"Enforce the assurance claim in RLS
presence-policy.sql
create policy "verified humans only"on public.transfers for insert to authenticatedwith check ( coalesce( (auth.jwt() -> 'presence' ->> 'verified')::boolean, false ));Two signed, fail-closed hooks
- 01
The Before User Created hook verifies Supabase's Standard Webhooks signature over the unmodified request body, reads the Presence Session Token from user metadata, and allows only a PASS disposition by default.
- 02
The Custom Access Token hook preserves Supabase's reserved claims and adds a presence assurance claim. PostgreSQL Row Level Security then denies sensitive writes unless presence.verified is true.
Verify the implementation
Every hook request is authenticated before Presence is called; stale, tampered, or incorrectly signed bodies return 401.
Supabase Auth Hooks →PASS admits sign-up and stamps presence.verified=true; DENY, missing tokens, unresolved checks, and outages fail closed by default.
Presence decision contract →
Current limits
- The hook endpoint and both secrets are server-side. Never expose the Presence tenant secret or the Supabase hook signing secret to a browser.
- Install @decionis/presence-auth from npm and import the Supabase-specific handlers from @decionis/presence-auth/supabase.
One next step
Continue with the executable path.