Role-Based Access Control
Ithbat IAM uses a resource:action permission model. Every protected operation requires a specific permission string. Roles are named collections of permissions. Users are granted access by assigning them one or more roles.
Permission model
Permissions follow the resource:action convention. There are three actions:
| Action | Description |
|---|---|
read | View or list the resource |
write | Create or update the resource |
delete | Delete the resource |
A user who holds user:write can create and update users. They cannot delete users without user:delete.
Complete permission reference
| Permission | Controls access to |
|---|---|
user:read | List and view user accounts |
user:write | Create and update user accounts |
user:delete | Delete user accounts |
role:read | List and view roles |
role:write | Create and update roles, assign/revoke roles |
role:delete | Delete roles |
group:read | List and view groups and group members |
group:write | Create/update groups, add/remove members, assign roles to groups |
organization:read | List and view organizations and members |
organization:write | Create/update organizations, manage members |
tenant:read | View tenant details, stats, and billing overview |
tenant:write | Update tenant settings, create/suspend/delete tenants |
tenant:delete | Delete tenants |
settings:read | View tenant settings, SAML configs, IdP configs, password policies |
settings:write | Update settings, create SAML/IdP configs, manage IP whitelists |
billing:read | View subscription, invoices, usage, and payment methods |
billing:write | Create/change subscriptions, add/remove payment methods |
oauth:read | List and view OAuth 2.0 clients |
oauth:write | Create, update, and delete OAuth clients |
webhook:read | List webhooks and view delivery logs |
webhook:write | Create/update/delete webhooks, send test events, retry deliveries |
feature:read | View feature flags and tenant overrides |
feature:write | Create/update/delete feature flags and tenant overrides |
invitation:read | List and view invitations |
invitation:write | Send, resend, and revoke invitations |
permission:read | List available permissions |
permission:write | Create custom permissions |
policy:read | View access policies |
policy:write | Create, update, and delete policies |
workflow:read | View workflows, instances, and access requests |
workflow:write | Create/manage workflows, approve/reject access requests |
directory:read | View directory connections and sync jobs |
directory:write | Create/update directory connections, trigger syncs |
scim:read | View SCIM configuration, tokens, and logs |
scim:write | Update SCIM configuration, create/revoke tokens |
email_template:read | View email templates |
email_template:write | Update and preview email templates |
content:read | View content items |
content:write | Create, update, publish, and archive content |
audit:read | View audit logs and login history |
log:read | Query and export raw logs |
analytics:read | View analytics dashboards |
Admin wildcard
The special admin permission grants access to all resources within a tenant. A role containing admin does not need any other permissions listed above. The check is:
hasPermission = permissions.includes('admin') || permissions.includes('system:admin') || permissions.includes(requiredPermission)
Built-in roles
Ithbat IAM includes three system roles that cannot be deleted.
| Role | Permissions | Description |
|---|---|---|
| Tenant Admin | admin (wildcard) | Full access to all tenant resources |
| User | user:read, content:read | Standard member — can view their own profile and public content |
| System Admin | system:admin | Platform-level admin (not assignable per-tenant; platform admin console only) |
Creating custom roles
Custom roles let you apply the principle of least privilege. For example, a Support Agent role that can read users but not modify them.
Via admin console
- Go to Roles → Create Role.
- Enter a Name and optional Description.
- Select individual permissions from the permission tree.
- Click Save.
Via API
POST /api/v1/roles
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}
Content-Type: application/json
{
"name": "Support Agent",
"description": "Read-only access to users and audit logs"
}
After creating the role, assign permissions by updating it:
PUT /api/v1/roles/{id}
Authorization: Bearer {token}
Content-Type: application/json
{
"name": "Support Agent",
"description": "Read-only access to users and audit logs",
"permissions": ["user:read", "audit:read"]
}
Response:
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"tenantId": "c2e3f4a5-...",
"name": "Support Agent",
"description": "Read-only access to users and audit logs",
"permissions": ["user:read", "audit:read"],
"isSystem": false,
"createdAt": "2026-02-24T10:00:00Z",
"updatedAt": "2026-02-24T10:00:00Z"
}
Assigning roles to users
Via admin console
- Go to Users → {user} → Roles.
- Click Assign Role and select from available roles.
Via API
POST /api/v1/users/{userId}/roles
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}
Content-Type: application/json
{
"roleId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}
Remove a role from a user
DELETE /api/v1/users/{userId}/roles/{roleId}
Authorization: Bearer {token}
View a user's effective permissions
GET /api/v1/users/{userId}/permissions
Authorization: Bearer {token}
Response includes the union of all permissions from all roles assigned to the user:
{
"userId": "3fa85f64-...",
"permissions": ["user:read", "audit:read"]
}
Group-based access
Assign roles to groups and users inherit the role when they join the group. This is the recommended approach for managing access at scale.
Assign a role to a group
POST /api/v1/groups/{groupId}/roles
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}
Content-Type: application/json
{
"roleId": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}
View group's roles
GET /api/v1/groups/{groupId}/roles
Authorization: Bearer {token}
When a user is added to a group, they immediately inherit the group's roles. When removed, the inherited roles are revoked.
Organization-level permissions
Ithbat supports organizations within a tenant — sub-units such as departments or business units. A user can have different roles in different organizations.
Add a user to an organization with a specific role
POST /api/v1/organizations/{orgId}/members
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}
Content-Type: application/json
{
"userId": "3fa85f64-...",
"roles": ["7c9e6679-..."]
}
Update a member's organization-level roles
PUT /api/v1/organizations/{orgId}/members/{userId}/roles
Authorization: Bearer {token}
Content-Type: application/json
{
"roles": ["new-role-id"]
}
Checking permissions in your application
From the JWT access token
When a user authenticates, their permissions are embedded in the JWT access token claims. Decode the token to read permissions:
{
"sub": "3fa85f64-...",
"tenant_id": "c2e3f4a5-...",
"permissions": ["user:read", "audit:read"],
"exp": 1740391200
}
In JavaScript/TypeScript
function hasPermission(token: DecodedToken, permission: string): boolean {
return token.permissions.includes('admin') ||
token.permissions.includes('system:admin') ||
token.permissions.includes(permission);
}
if (hasPermission(decodedToken, 'user:write')) {
// show create user button
}
In backend middleware (Go example)
func RequirePermission(required string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
claims := claimsFromContext(r.Context())
for _, p := range claims.Permissions {
if p == "admin" || p == "system:admin" || p == string(required) {
next.ServeHTTP(w, r)
return
}
}
http.Error(w, "forbidden", http.StatusForbidden)
})
}
}
Check permissions via API
For server-side authorization checks without decoding a JWT:
GET /api/v1/users/{userId}/permissions
Authorization: Bearer {token}
Access request workflows
Users without a required permission can submit an access request. A user with workflow:write permission then approves or rejects it.
Submit an access request
POST /api/v1/access-requests
Authorization: Bearer {user_token}
Content-Type: application/json
{
"requestedRoleId": "7c9e6679-...",
"reason": "Need access to run billing reports"
}
View pending approvals
GET /api/v1/access-requests/pending-approvals
Authorization: Bearer {approver_token}
Approve a request
POST /api/v1/access-requests/{id}/approve
Authorization: Bearer {approver_token}
Reject a request
POST /api/v1/access-requests/{id}/reject
Authorization: Bearer {approver_token}
Content-Type: application/json
{
"reason": "Access not required for your current role"
}
Role management API reference
List roles
GET /api/v1/roles
Authorization: Bearer {token}
X-Tenant-ID: {tenant_id}
Get a role
GET /api/v1/roles/{id}
Authorization: Bearer {token}
Get available permissions
Returns the full list of permissions that can be assigned to roles:
GET /api/v1/roles/permissions
Authorization: Bearer {token}
Delete a role
System roles (isSystem: true) cannot be deleted.
DELETE /api/v1/roles/{id}
Authorization: Bearer {token}
Best practices
Principle of least privilege: Grant only the permissions each role needs. Start with read-only access and add write permissions only when necessary.
Use groups for team-based access: Assign roles to groups (Engineering, Finance, Support) rather than individual users. When someone joins or leaves a team, update their group membership rather than their individual permissions.
Avoid assigning admin broadly: The admin wildcard grants full tenant access. Reserve it for your tenant administrators and use specific permissions for everyone else.
Audit role assignments regularly: Review who has user:delete, tenant:write, and billing:write permissions quarterly. Use the audit log to track role assignment history.
Use access request workflows for elevated access: Rather than permanently granting elevated permissions, route time-sensitive requests through the approval workflow.
Next steps
- Multi-Tenancy — organization-level roles and cross-tenant permission model
- Audit Logs — track role assignments, changes, and access decisions
- User Management — manage users and their role assignments