Skip to content

Role-Based Access Control

This guide shows how to add roles to your gau setup.

  • Roles are stored in the User table in the database.
  • On first sign-in, you can set a role via roles.defaultRole or compute one with roles.resolveOnCreate.
  • The session returned by getSession() includes user.role when your adapter returns it.

Add a role column. You can constrain values if you want.

schema.ts
import { sqliteTable, text } from 'drizzle-orm/sqlite-core'
export const Users = sqliteTable('users', {
// ...
role: text().$type<'admin' | 'user'>().default('user'),
})

See roles.

These are all optional, by default user is the default role, adminRoles is ['admin'], and adminUserIds is [].

auth.ts
import { createAuth } from '@rttnd/gau/core'
export const auth = createAuth({
// ...
roles: {
defaultRole: 'user',
resolveOnCreate({ providerId, profile }) {
// Example:
return profile.email === 'admin@example.com' ? 'admin' : 'user'
},
adminRoles: ['admin'],
adminUserIds: ['1234567890'],
},
})

On first sign-in, resolveOnCreate is called. If it returns a role, it’s used; otherwise defaultRole.

Authorize in your route handlers/middleware using session.user?.role.

admin.remote.ts
import { getRequestEvent, query } from '$app/server'
import { error } from '@sveltejs/kit'
export const getSession = query(
async () => {
const event = getRequestEvent()
const session = await event.locals.getSession()
if (session.user?.role !== 'admin')
error(403, 'Forbidden')
return session
},
)
+page.ts
import type { PageLoad } from './$types'
import { error } from '@sveltejs/kit'
export const load: PageLoad = async (event) => {
const session = await event.locals.getSession()
if (session.user?.role !== 'admin')
error(403, 'Forbidden')
return session
}
routes/api/+server.ts
import type { RequestHandler } from './$types'
import { error } from '@sveltejs/kit'
export const GET: RequestHandler = async (event) => {
const session = await event.locals.getSession()
if (session.user?.role !== 'admin')
error(403, 'Forbidden')
return session
}