Roles & Permissions (RBAC)
Auris implements role-based access control (RBAC) with a tri-state permission resolution model: permissions can be explicitly ALLOW, explicitly DENY, or INHERIT (inherit from the role’s default). User-level permission overrides take precedence over role-level permissions, enabling fine-grained exceptions without creating dedicated roles.
Permission Format
All permissions in Auris follow the action:resource pattern:
manage:users view:invoices create:tickets
edit:roles approve:expenses delete:documents
assign:tickets sign:interventions export:reportsThe action component describes what the permission enables. Common actions: view, create, edit, delete, manage, approve, assign, export, sign, generate.
The resource component describes the entity or feature being accessed. Resources correspond to modules in your application.
There is one special permission — admin:all — which grants unrestricted access to all resources when held by a role. It is assigned to the built-in Administrator role.
Creating Roles
Via the Console
- Navigate to Console → Roles → Create Role
- Enter a name (e.g.,
Invoice Manager), optional description, and choose a color for the role badge - The role is created with no permissions. Configure permissions on the role’s detail page.
Via the API
/api/rolesRequires: manage:rolesCreate a new role. Body: { name: string, description?: string, color?: string }.
// Using the Auris Management Client
const management = await createManagementClient({ ... })
const role = await management.roles.create({
name: 'Invoice Manager',
description: 'Can create and view invoices but not delete them',
color: '#3b82f6',
})Configuring Permissions
Permission Categories
The Console permission editor organizes permissions into 10 categories:
| Category | Example Permissions |
|---|---|
| Documents | view:invoices, create:quotes, approve:expenses, sign:interventions |
| Users | view:users, manage:users, import:users, export:users |
| Roles | view:roles, manage:roles, assign:roles |
| Applications | view:applications, manage:applications, manage:api_keys |
| Organizations | view:organizations, manage:organizations, manage:sso_connections |
| Security | view:audit_logs, manage:attack_protection, view:sessions |
| Billing | view:billing, manage:subscriptions |
| Integrations | view:integrations, manage:webhooks, manage:automations |
| Infrastructure | view:monitoring, manage:devices, manage:firewalls |
| Support | view:tickets, create:tickets, assign:tickets, manage:sla |
Setting Permissions on a Role
In the Console, each permission has a three-way toggle on the role’s detail page:
- ALLOW — The permission is granted to users with this role
- DENY — The permission is explicitly denied, overriding inherited ALLOW from other roles
- INHERIT — The role neither grants nor denies this permission (default)
A user is granted a permission if any of their roles has it set to ALLOW and none of their roles has it set to DENY.
Via the API
/api/roles/:id/permissionsRequires: manage:rolesUpdate role permissions. Body: { permissions: { [permission: string]: 'ALLOW' | 'DENY' | 'INHERIT' } }.
Assigning Roles to Users
Roles are assigned to users in the Console (Users → [User] → Roles tab) or via API:
/api/users/:id/rolesRequires: manage:usersAssign one or more roles to a user. Body: { roleIds: string[] }.
/api/users/:id/roles/:roleIdRequires: manage:usersRemove a role from a user.
Users can have multiple roles. Permissions from all roles are merged. If any role has DENY for a permission, that overrides ALLOW from other roles.
User-Level Permission Overrides
Individual users can have permissions set directly, independent of their roles. User overrides take precedence over all role permissions:
- A user-level ALLOW grants the permission even if no role grants it
- A user-level DENY blocks the permission even if a role grants ALLOW
Console: Users → [User] → Permissions tab → Add Override
/api/users/:id/permission-overridesRequires: manage:usersSet a permission override for a specific user. Body: { permission: string, effect: 'ALLOW' | 'DENY' }.
Checking Permissions
Server-Side (API Routes)
Use the requirePermission() helper to enforce permissions in API routes:
Next.js Route Handler
// app/api/invoices/route.ts
import { requirePermission } from '@auris/nextjs/server'
const config = {
domain: process.env.NEXT_PUBLIC_AURIS_DOMAIN!,
clientId: process.env.NEXT_PUBLIC_AURIS_CLIENT_ID!,
}
export const GET = requirePermission('view:invoices', config, async (req, { session }) => {
// Only reached if the user has view:invoices permission
const invoices = await getInvoices(session.user.id)
return Response.json(invoices)
})
export const POST = requirePermission('create:invoices', config, async (req, { session }) => {
const body = await req.json()
const invoice = await createInvoice(body, session.user.id)
return Response.json(invoice, { status: 201 })
})Client-Side (React Components)
React Hook
import { useCheckPermission, usePermissions } from '@auris/react'
// Check a single permission
function InvoiceActions() {
const { allowed: canCreate, isLoading } = useCheckPermission('create:invoices')
const { allowed: canDelete } = useCheckPermission('delete:invoices')
if (isLoading) return null
return (
<div>
{canCreate && <button>New Invoice</button>}
{canDelete && <button>Delete Selected</button>}
</div>
)
}
// Check multiple permissions at once
function DashboardNav() {
const { has, hasAll, hasAny } = usePermissions([
'view:invoices',
'view:quotes',
'manage:users',
'view:billing',
])
return (
<nav>
{has('view:invoices') && <a href="/invoices">Invoices</a>}
{has('view:quotes') && <a href="/quotes">Quotes</a>}
{has('manage:users') && <a href="/users">Users</a>}
{has('view:billing') && <a href="/billing">Billing</a>}
{hasAll(['view:invoices', 'view:quotes']) && <a href="/documents">All Documents</a>}
{hasAny(['manage:users', 'manage:roles']) && <a href="/admin">Admin</a>}
</nav>
)
}Permission API
/api/roles/checkCheck one or more permissions for the authenticated user. Body: { permissions: string[] } or { permission: string }. Returns an array of { permission, allowed } objects.
/api/rolesRequires: view:rolesList all roles in the tenant, including permission counts and user counts.
/api/roles/:idRequires: view:rolesGet a specific role including its full permission set.
/api/roles/:idRequires: manage:rolesDelete a role. Users who held this role lose the associated permissions immediately.
Permission Resolution Order
When Auris resolves whether a user has a specific permission, it follows this precedence:
- User-level DENY override — If present, the permission is denied. No further evaluation.
- User-level ALLOW override — If present (and no DENY), the permission is granted.
- Role permissions — If any role has ALLOW and no role has DENY, the permission is granted.
- Implicit deny — If no rule grants the permission, it is denied.
User Override DENY → DENIED (stops here)
User Override ALLOW → ALLOWED (stops here)
Any Role DENY → DENIED (stops here)
Any Role ALLOW → ALLOWED
No match → DENIEDApplication-Scoped Permissions
Permissions can optionally be scoped to a specific application. When an applicationId is included in a permission check, Auris evaluates permissions within the context of that application — useful for multi-application tenants where roles may differ per application.
const result = await fetch('/api/roles/check', {
method: 'POST',
headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({
permissions: ['view:invoices', 'create:invoices'],
applicationId: 'app-id-for-billing-app',
}),
})Related Guides
- Fine-Grained Authorization — Object-level access control beyond roles
- Custom JWT Claims — Embed role or permission data in access tokens
- M2M Client Credentials — Authorization for server-to-server calls