Aurabase Logo
aurabasedocs
docs›Guides›Multi-tenant RBAC

Multi-tenant RBAC

Model application roles (admin, editor, viewer, billing) on top of Aurabase Auth. Patterns for flat, hierarchical orgs, and per-resource permissions.

10 min read·Level advanced·Revised on Apr 15, 2026
This English text was generated automatically from the French original and has not been reviewed yet.
#
Model

Tables: members, roles, permissions

migrations/rbac.sqlsql
create table orgs (id uuid primary key default gen_random_uuid(), name text not null);

create table org_members (
  org_id   uuid references orgs(id) on delete cascade,
  user_id  uuid references auth.users(id) on delete cascade,
  roles    text[] not null default '{}',
  primary key (org_id, user_id)
);
#
Claims

Inject the roles into the JWT

An Edge Function connected like Auth Hook enriches the JWT with tenant (active org_id) + roles (array). They are merged into the token's app_metadata, where auth.tenant() and auth.has_role() read them in your policies.

functions/jwt-enrich.tstypescript
Deno.serve(async (req) => {
  // Request: { event, project_id, user_id, email, role }, signed with X-Hook-Signature.
  const { user_id } = await req.json()
  const { data: m } = await aura
    .from('org_members')
    .select('org_id, roles')
    .eq('user_id', user_id).single()

  // Response: { claims: { … } }. Its keys are merged into app_metadata. A hook that fails,
  // answers with anything else, or sets a protected claim (sub, role, aud…) refuses the sign-in.
  return Response.json({
    claims: { tenant: m?.org_id, roles: m?.roles || [] },
  })
})
Info

The hook executes on sign-in and on each refresh. Modifying a user's roles becomes active at their next token refresh (max 15 min).

#
Policies

Combine tenant + roles

migrations/orgs_rls.sqlsql
-- Any member of the org sees the projects
create policy "projects_read" on projects
  for select to aura_authenticated
  using (org_id = auth.tenant());

-- Only admin can create/delete
create policy "projects_admin" on projects
  for all to aura_authenticated
  using (org_id = auth.tenant() and auth.has_role('admin'))
  with check (org_id = auth.tenant());
#
Enterprise

Automatic provisioning via SCIM

On Enterprise plan, enable SCIM 2.0 from Okta, Azure AD, Google Workspace. Users + roles are synchronized automatically: immediate addition/removal, instant deprovisioning when an employee leaves.

Last updated · Apr 15, 2026