Role-Based Access Control (RBAC): A Simple and Elegant Implementation - Part 1
DB Schema Design
Photo by Nick Morrison on Unsplash
In today's digital landscape, securing access to resources is paramount. Role-Based Access Control (RBAC) is a powerful approach to managing user permissions efficiently. This blog post will guide you through implementing RBAC in a simple yet elegant way, complete with schema examples and a straightforward architecture.
In Part 1, we’ll see how we can plan db schema for RBAC.
Understanding RBAC
RBAC is an approach to restricting system access to authorized users based on their roles within an organization. It's a method of regulating access to computer or network resources based on the roles of individual users.
The Architecture
Let's start with a high-level view of our RBAC architecture:
In this architecture:
Users are associated with roles
Roles contain permissions
All data is stored in Redis for fast access
The application queries Redis and enforces permissions
Schema Design
Now, let's dive into the schema design for our RBAC system. We'll use two main tables: users
and roles
.
Users Table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role_id INTEGER NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Roles Table
CREATE TABLE roles (
id SERIAL PRIMARY KEY,
name VARCHAR(50) UNIQUE NOT NULL,
description TEXT,
parent_role_id INTEGER,
permissions JSONB NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Notice the permissions
field in the roles
table. This JSONB field will store our permissions in a flexible JSON format.
Permissions Structure
The permissions in our RBAC system are structured as a JSON object. Here's an example of what the permissions
field might look like:
{
"user_management": ["create", "read", "update", "delete"],
"content_management": ["create", "read", "update"],
"reports": ["read", "generate"],
"settings": ["read", "update"]
}
In this structure:
The keys (e.g., "user_management") represent different modules or areas of the application.
The values are arrays of permitted actions within that module.
This structure allows for granular control over permissions while maintaining flexibility.
Implementing RBAC with Redis
To implement this system with Redis, we'll use Redis hashes to store our user and role data. Here's how we might structure our Redis data:
For Users:
HSET user:1 id 1 username "john_doe" email "john@example.com" role_id 2
For Roles:
HSET role:2 id 2 name "editor" description "Can edit content" parent_role_id 1 permissions '{"content_management":["create","read","update"],"reports":["read"]}'
Checking Permissions
When a user attempts to perform an action, we can check their permissions like this:
Get the user's role ID from Redis
Fetch the role details, including permissions
Check if the required permission exists in the role's permission set
Here's a pseudocode example:
def check_permission(user_id, module, action):
# Get user's role ID
role_id = redis.hget(f"user:{user_id}", "role_id")
# Get role permissions
role_permissions = json.loads(redis.hget(f"role:{role_id}", "permissions"))
# Check if the action is allowed
return action in role_permissions.get(module, [])
# Usage
if check_permission(user_id, "content_management", "update"):
# Allow the action
else:
# Deny the action
Conclusion
This RBAC implementation offers a balance of simplicity and power. By using Redis for storage, we ensure fast access to our permission data. The JSON structure for permissions provides flexibility, allowing us to easily add or modify permissions as our application grows.
Remember, while this system is a great starting point, you may need to adapt it to your specific needs. Always consider factors like caching strategies, regular permission updates, and how to handle permission inheritance if you implement a hierarchical role structure.
By implementing RBAC, you're taking a significant step towards securing your application and providing a foundation for scalable user management. Happy coding!
I've created a detailed blog post on implementing Role-Based Access Control (RBAC) in a simple and elegant way. The post includes:
An explanation of RBAC
A simple architecture diagram
Schema examples for users and roles tables
A sample JSON structure for permissions
An explanation of how to implement this using Redis
A pseudocode example of checking permissions
Would you like me to explain or elaborate on any part of this blog post?