Roles and permissions


Organization permissions are Better Auth's access control:
resources with actions (project: ['create', 'update']), and roles that each allow some of them.
| What | Where it's defined | In the UI |
|---|---|---|
| Resources and actions | organization.statements in nuxt.config.ts | Shown on the Roles tab |
App-wide roles (owner, admin, member, your own) | organization.roles in nuxt.config.ts | Shown on the Roles tab |
| An organization's own roles | Made on the organization's Roles tab | Created, edited and deleted |
Your resources
Better Auth comes with resources for itself: organization, member, invitation, team and ac (access
control). Add your app's own with statements:
export default defineNuxtConfig({
betterAuthUi: {
organization: {
enabled: true,
statements: {
project: ['create', 'share', 'update', 'delete']
}
}
}
})
The module builds Better Auth's access control from them (createAccessControl) and passes it to the server and
client plugins, so you don't write any of it yourself.
nuxt.config.ts rather than the UI.Roles
Give roles their permissions with roles:
export default defineNuxtConfig({
betterAuthUi: {
organization: {
enabled: true,
statements: { project: ['create', 'share', 'update', 'delete'] },
roles: {
// A new role.
editor: { project: ['create', 'update'] },
// Naming owner, admin or member adds to Better Auth's role of that name.
admin: { project: ['create', 'share', 'update', 'delete'] }
}
}
}
})
- Owners get every action on your resources, automatically.
- Naming
owner,adminormemberadds permissions to Better Auth's role of that name; it doesn't replace it. - Role pickers (inviting, changing a member's roles) list every role.
- Mistakes fail the build: a role naming a resource or action that isn't in
statementsstops the build with a message saying which.
Roles each organization makes
With dynamicRoles, an organization's owners and admins create their own roles on its Roles tab: a name, and a grid
of every resource and action to tick. Better Auth's
dynamic access control stores them per
organization.
export default defineNuxtConfig({
betterAuthUi: {
organization: {
enabled: true,
statements: { project: ['create', 'share', 'update', 'delete'] },
dynamicRoles: true // or { maximumRolesPerOrganization: 10 }
}
}
})
- Creating, editing and deleting roles needs the
ac:create,ac:updateandac:deletepermissions; owners and admins have them. - Better Auth refuses permissions the editor doesn't have themselves.
- The organization's roles join the role pickers alongside the app-wide ones.
Run Better Auth's migrations after turning it on: it adds an organizationRole table.
Checking permissions
On your server, ask Better Auth whether the signed-in member may do something in their active organization:
export default defineEventHandler(async (event) => {
const { success } = await serverAuth(event).api.hasPermission({
headers: event.headers,
body: { permissions: { project: ['share'] } }
})
if (!success) throw createError({ statusCode: 403 })
})
This counts app-wide and dynamic roles alike. auth.api.getActiveMemberRole({ headers }) (or the client's
organization.getActiveMemberRole()) gives the member's role itself.