RBAC & Permissions
Role-based access control in AuthSaas — how roles work, how to assign them, and how to enforce them in your app.
Overview#
AuthSaas ships with a fully live role-based access control system. Key properties:
- Roles are per-app (scoped to a
TenantApp) — completely isolated between your different projects. - Three default roles are auto-seeded every time you create an app:
owner,admin, anduser. - New users are automatically assigned the
userrole on registration. - Roles are included in the JWT
rolesarray — read them in your app to gate features without an extra API call.
Default roles#
The following roles and permission sets are created automatically for every new app:
Role Permissions
user read:profile, write:profile
admin + read:users, write:users, read:audit, read:sessions
owner + delete:users, read:roles, write:roles, delete:sessionsThe + notation means the role inherits all permissions from the role above it plus the listed additions.
Permissions catalog#
All 10 available permissions and what they grant:
read:profile— View own profilewrite:profile— Edit own profileread:users— List and view userswrite:users— Create and update usersdelete:users— Delete usersread:roles— View roles and permissionswrite:roles— Create and update rolesread:audit— View audit logsread:sessions— View active sessionsdelete:sessions— Revoke sessions
Assigning roles#
New users automatically receive the user role when they register. To assign a different role — or add additional roles — use the dashboard UI or call the API directly:
// Assign roles to a user via the API
const response = await fetch(`/users/${userId}/roles`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({ roles: ['admin'] }),
});
const { user } = await response.json();
console.log(user.roles); // ['admin']Checking roles#
Read the roles array from the decoded JWT payload to enforce access control in your application:
// Decode the access token in your API route
const payload = verifyAccessToken(req.headers.authorization.slice(7));
// payload.roles = ['admin']
// Gate a feature
if (!payload.roles.includes('admin')) {
return Response.json({ error: 'Forbidden' }, { status: 403 });
}ℹ Note
/auth/refresh to get a new token pair.Custom roles#
You can create custom roles beyond the three defaults. First create the role, then assign permissions to it:
// 1. Create a custom role
const roleRes = await fetch('/roles', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({ name: 'moderator' }),
});
const { role } = await roleRes.json();
// 2. Assign permissions to the new role
await fetch(`/roles/${role.id}/permissions`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({
permissions: ['read:users', 'read:audit'],
}),
});ℹ Note
JWT claims#
The full decoded access token payload — all claims your application can rely on:
{
"sub": "usr_clxxxxxxxxxxxxxxxx",
"email": "user@example.com",
"appId": "app_clxxxxxxxxxxxxxxxx",
"roles": ["admin"],
"iat": 1709812345,
"exp": 1709813245
}