Access Control Plugin
Manage roles, permissions, and user access.
Overview
The Access Control plugin provides a comprehensive Role-Based Access Control (RBAC) system for managing authorization in your application. It enables you to define roles, assign permissions to those roles, and grant roles to users, creating a flexible and scalable authorization model.
What It Does
- Role Management — Create and manage roles. Supports system-managed roles that cannot be modified or deleted once created. Roles also support adding a weight to determine their hierarchy and precedence. This is reminicent of the concept of "role hierarchy" in traditional RBAC systems, but implemented with a flexible weight system that allows for more granular control.
- Permission Management — Define fine-grained permissions with unique keys
- Role-Permission Mapping — Associate permissions with roles and manage bulk updates
- User Authorization — Assign roles to users and query their effective permissions
- Audit Tracking — Track who granted permissions and assigned roles
The plugin uses a hierarchical model: Users → Roles → Permissions, allowing you to manage authorization at any level and simplifying policy changes across multiple users.
Configuration
Standalone Mode
[plugins.access_control]
enabled = trueLibrary Mode
accesscontrolplugin "github.com/Authula/authula/plugins/access-control"
accesscontrolplugintypes "github.com/Authula/authula/plugins/access-control/types"
accesscontrolplugin.New(accesscontrolplugintypes.AccessControlPluginConfig{
Enabled: true,
})API Reference
Roles Management
| HTTP Method | Route Path | Description |
|---|---|---|
POST | /access-control/roles | Create a new role |
GET | /access-control/roles | List all available roles |
GET | /access-control/roles/by-name/{role_name} | Get a role by name |
GET | /access-control/roles/{role_id} | Get a role by ID |
PATCH | /access-control/roles/{role_id} | Update a role |
DELETE | /access-control/roles/{role_id} | Delete a role |
Permissions Management
| HTTP Method | Route Path | Description |
|---|---|---|
POST | /access-control/permissions | Create a new permission |
GET | /access-control/permissions | List all permissions |
GET | /access-control/permissions/{permission_id} | Get a permission by ID |
PATCH | /access-control/permissions/{permission_id} | Update a permission |
DELETE | /access-control/permissions/{permission_id} | Delete a permission |
Role-Permission Mapping
| HTTP Method | Route Path | Description |
|---|---|---|
POST | /access-control/roles/{role_id}/permissions | Add a single permission to a role |
GET | /access-control/roles/{role_id}/permissions | Get all permissions assigned to a role |
PUT | /access-control/roles/{role_id}/permissions | Replace all permissions of a role (bulk update) |
DELETE | /access-control/roles/{role_id}/permissions/{permission_id} | Remove a permission from a role |
User Access & Permissions
| HTTP Method | Route Path | Description |
|---|---|---|
GET | /access-control/users/{user_id}/roles | Get all roles assigned to a user |
POST | /access-control/users/{user_id}/roles | Assign a role to a user |
PUT | /access-control/users/{user_id}/roles | Replace all roles of a user (bulk update) |
DELETE | /access-control/users/{user_id}/roles/{role_id} | Remove a role from a user |
GET | /access-control/users/{user_id}/permissions | Get all permissions for a user |
POST | /access-control/users/{user_id}/permissions/check | Check whether a user has permissions |
Database Schema
This plugin creates the following database tables:
Table: access_control_roles
| Field | Type | Key | Description |
|---|---|---|---|
id | string | PK | Unique identifier for the role |
name | string | - | Name of the role |
description | string? | - | Role description |
weight | int | - | Role weight for hierarchy |
is_system | boolean | - | Whether role is system-managed |
created_at | timestamp | - | Record creation time |
updated_at | timestamp | - | Record last update time |
Table: access_control_permissions
| Field | Type | Key | Description |
|---|---|---|---|
| id | string | PK | Unique identifier for permission |
| key | string | - | Permission key identifier |
| description | string? | - | Permission description |
| is_system | boolean | - | Whether permission is system-managed |
| created_at | timestamp | - | Record creation time |
| updated_at | timestamp | - | Record last update time |
Table: access_control_role_permissions
| Field | Type | Key | Description |
|---|---|---|---|
| role_id | string | PK | Role identifier |
| permission_id | string | PK | Permission identifier |
| granted_by_user_id | string? | FK | User who granted the permission |
| granted_at | timestamp | - | Time when permission was granted |
Table: access_control_user_roles
| Field | Type | Key | Description |
|---|---|---|---|
| user_id | string | PK | User identifier |
| role_id | string | PK | Role identifier |
| assigned_by_user_id | string? | FK | User who assigned the role |
| assigned_at | timestamp | - | Time when role was assigned |
| expires_at | timestamp? | - | Time when role assignment expires |
Migrations are automatically handled when the plugin is initialized.
Plugin Capabilities
access_control.enforce: Enforce access control on an API endpoint
Example Usage
Standalone mode:
[[route_mappings]]
path = "/admin/users"
method = "GET"
# Make sure to include an auth capability plugin (e.g. session.auth) before the access control plugin
# to ensure the user is authenticated before enforcing permissions.
plugins = ["session.auth", "access_control.enforce"]
permissions = ["users.read"] # Specify the required permission to access this routeLibrary mode:
import (
authulaconfig "github.com/Authula/authula/config"
authulamodels "github.com/Authula/authula/models"
sessionplugin "github.com/Authula/authula/plugins/session"
accesscontrolplugin "github.com/Authula/authula/plugins/access-control"
)
config := authulaconfig.NewConfig(
// Other config options...
authulaconfig.WithRouteMappings([]authulamodels.RouteMapping{
{
Method: "GET",
Path: "/admin/users",
Plugins: []string{
sessionplugin.HookIDSessionAuth.String(),
accesscontrolplugin.HookIDAccessControlEnforce.String(),
},
Permissions: []string{
"users.read",
},
},
}),
)Notes
- System-managed roles and permissions are protected from modification or deletion to ensure critical access controls remain intact.
- Role weights allow you to establish a hierarchy, where higher-weighted roles take precedence over lower-weighted ones. This is very useful for scenarios where users may have multiple roles, and you want to determine which role is of higher priority. Also this is important to take into consideration as a user can only grant roles with equal or lower weight than their highest role, preventing privilege escalation.
- An example of this is an
Adminrole with weight100,Editorrole with weight50, andViewerrole with weight25. AnAdmincan assign any of these roles, while anEditorcan only assign theViewerrole.
- An example of this is an
Client Plugin
If you're using the Authula SDK, add the plugin to the SDK like so:
import { createClient } from "authula";
import { AccessControlPlugin } from "authula/plugins";
export const authulaClient = createClient({
url: "http://localhost:8080/auth",
plugins: [
// other plugins...
new AccessControlPlugin(),
],
});