Skip to content

Permission System

Moka.Auth provides a flexible and granular permission system that allows you to control access to your application’s resources.

Overview

The permission system is built on these core concepts:

  • Permissions: Individual access rights (e.g., “users.read”, “users.write”)
  • Roles: Groups of permissions (e.g., “Admin”, “User”)
  • Users: Can have both direct permissions and role-based permissions

Setting Up Permissions

1. Using YAML Configuration

Create a seed-data.yaml file:

permissions:
- name: users.read
description: Can read user data
- name: users.write
description: Can modify user data
- name: roles.manage
description: Can manage roles
- name: permissions.manage
description: Can manage permissions
roles:
- name: Admin
description: Administrator role
permissions:
- users.read
- users.write
- roles.manage
- permissions.manage
- name: User
description: Basic user role
permissions:
- users.read
users:
- username: admin
password: Admin123!
roles:
- Admin
permissions:
- permissions.manage

Load the configuration:

var yamlFilePath = Path.Combine(app.Environment.ContentRootPath, "seed-data.yaml");
await app.SeedMokaAuthDataFromYamlAsync(yamlFilePath);

2. Using JSON Configuration

Create a seed-data.json file:

{
"permissions": [
{
"name": "users.read",
"description": "Can read user data"
},
{
"name": "users.write",
"description": "Can modify user data"
}
],
"roles": [
{
"name": "Admin",
"description": "Administrator role",
"permissions": ["users.read", "users.write"]
}
],
"users": [
{
"username": "admin",
"email": "[email protected]",
"password": "Admin123!",
"roles": ["Admin"],
"permissions": ["permissions.manage"]
}
]
}

Load the configuration:

var jsonFilePath = Path.Combine(app.Environment.ContentRootPath, "seed-data.json");
await app.SeedMokaAuthDataFromJsonAsync(jsonFilePath);

3. Using Environment Variables

Set environment variables:

Terminal window
MOKA_AUTH_PERMISSIONS='users.read,users.write,roles.manage'
MOKA_AUTH_ADMIN_ROLE_PERMISSIONS='users.read,users.write'
MOKA_AUTH_USER_ROLE_PERMISSIONS='users.read'

Load from environment:

await app.SeedMokaAuthDataFromEnvironmentAsync();

4. Programmatic Configuration

await app.SeedMokaAuthDataAsync(new MokaAuthSeederOptions
{
Permissions =
[
new PermissionSeedConfiguration
{
Name = "users.read",
Description = "Can read user data"
},
new PermissionSeedConfiguration
{
Name = "users.write",
Description = "Can modify user data"
}
],
Roles =
[
new RoleSeedConfiguration
{
Name = "Admin",
Description = "Administrator role",
Permissions = ["users.read", "users.write"]
},
new RoleSeedConfiguration
{
Name = "User",
Description = "Basic user role",
Permissions = ["users.read"]
}
],
UseTransaction = true, // Use transaction for safety
ThrowOnError = false, // Don't throw on error, just log it
RecreateDefaults = false // Don't update existing entities
});

Using Permissions

1. Attribute-based Authorization

Use the RequirePermission attribute to protect endpoints:

[RequirePermission("users.read")]
[HttpGet]
public IActionResult GetUsers()
{
return Ok(_userService.GetUsers());
}
// Require multiple permissions
[RequirePermission("users.read", "users.write")]
[HttpPost]
public IActionResult CreateUser([FromBody] CreateUserRequest request)
{
return Ok(_userService.CreateUser(request));
}

2. Programmatic Authorization

Check permissions in your code:

public class UserService
{
private readonly IPermissionService _permissionService;
public async Task<bool> CanUserAccessResource(string userId, string resource)
{
return await _permissionService.UserHasPermissionAsync(userId, $"{resource}.read");
}
}

Managing Permissions

1. Creating Permissions

public class PermissionController : ControllerBase
{
private readonly IPermissionService _permissionService;
[RequirePermission("permissions.create")]
[HttpPost]
public async Task<IActionResult> CreatePermission([FromBody] CreatePermissionRequest request)
{
var permission = await _permissionService.CreatePermissionAsync(
request.Name,
request.Description
);
return Ok(permission);
}
}

2. Assigning Permissions

// Assign to User
await _permissionService.AssignPermissionToUserAsync(userId, permissionId);
// Assign to Role
await _permissionService.AssignPermissionToRoleAsync(roleId, permissionId);

Permission Inheritance

Moka.Auth supports permission inheritance through roles:

// Create a role hierarchy
await _roleService.CreateRoleAsync("User", "Basic user role");
await _roleService.CreateRoleAsync("Editor", "Can edit content");
await _roleService.CreateRoleAsync("Admin", "Full system access");
// Set up inheritance
await _roleService.AddRoleToRoleAsync("Admin", "Editor");
await _roleService.AddRoleToRoleAsync("Editor", "User");

Common Permission Patterns

CRUD Operations

// Define permissions
await _permissionService.CreatePermissionAsync("users.create");
await _permissionService.CreatePermissionAsync("users.read");
await _permissionService.CreatePermissionAsync("users.update");
await _permissionService.CreatePermissionAsync("users.delete");
// Create role with CRUD permissions
var permissions = new[] { "users.create", "users.read", "users.update", "users.delete" };
await _roleService.CreateRoleWithPermissionsAsync("UserManager", permissions);

Resource-based Permissions

// Fine-grained resource permissions
await _permissionService.CreatePermissionAsync("documents.read.public");
await _permissionService.CreatePermissionAsync("documents.read.private");
await _permissionService.CreatePermissionAsync("documents.read.confidential");

Checking Multiple Permissions

Using OR Logic

[RequirePermission("documents.read.public", "documents.read.private", RequirementOperator.Or)]
public IActionResult GetDocument(string id)
{
// User can access if they have either permission
return Ok(_documentService.GetDocument(id));
}

Using AND Logic

[RequirePermission("documents.read", "documents.share")]
public IActionResult ShareDocument(string id)
{
// User must have both permissions
return Ok(_documentService.ShareDocument(id));
}