The Four Pillars of Access Control
Every system that limits who can see or do something is built on one of four classic models: Discretionary Access Control (DAC), Mandatory Access Control (MAC), Role-Based Access Control (RBAC), and Attribute-Based Access Control (ABAC). Whether you're designing a SaaS product or just trying to understand why your admin panel behaves the way it does, knowing these models helps you make better decisions.
At their core, all of them boil down to three things: a user, a system or application, and a policy. The user wants to do something—read a file, click a button, see a report. The system decides whether to allow it, based on some rule. How that rule is defined and enforced is what separates the models.
DAC: The Owner Decides
DAC is the oldest and most intuitive approach. The person who owns an object—a file, a folder, a database record—gets to decide who else can access it. The system keeps an Access Control List (ACL) for each object, listing users and their permissions. If you own a document, you can grant read or write access to specific people, and they can even pass those permissions along.
NTFS, the Windows file system, is a classic example. Right-click a folder, go to Properties, and you'll see the security tab where you can add users and tick boxes for full control, modify, read, and so on. It works fine for personal files, but it falls apart at scale. Trying to give a uniform set of permissions to a whole group of files across many folders becomes a nightmare. You end up chasing permissions one object at a time.
MAC: The System Rules
MAC was born to fix the chaos of DAC. Here, the system—not the object owner—sets the rules. Every object gets a label, and every user gets a clearance. The system checks whether the user's clearance meets the object's label before allowing access.
Think of a spy thriller where an agent tries to pull up a file and gets a message: "Access denied: requires Level 1 clearance." That's MAC in action. The file has a label, the agent doesn't have the right one, and the system says no. No exceptions, no owner discretion.
MAC is perfect for military or government settings where hierarchy matters more than convenience. But in a commercial SaaS product, it's too rigid. You can't let a user temporarily share a document with a colleague without going through a formal clearance process. That's why MAC rarely appears outside high-security environments.
RBAC: Roles Make It Practical
RBAC is the workhorse of modern applications. Instead of assigning permissions directly to users, you create roles—like "HR Manager" or "Editor"—and attach permissions to those roles. Users get roles, and the system figures out what they can do based on the role's permissions.
For example, MongoDB uses RBAC. It defines granular permissions like find (run queries), insert (add data), and collStats (view collection statistics). Then it bundles those into predefined roles: read might include find, while readWrite adds insert and collStats. You assign a user the readWrite role, and they can do everything that role allows.
RBAC scales well because you manage a handful of roles instead of thousands of individual permissions. It's also flexible enough to mimic DAC and MAC in some cases. But there's a common pitfall: people sometimes check for the role itself rather than the permission. I've seen code like this:
if (user.hasRole('hr')) { // give a raise }That works until a manager also needs to give raises. Then you have to go edit the code. The right way is to check whether the user's role has the give_raise permission. That way, you just grant that permission to the manager's role, and the code doesn't change.
RBAC's Family Tree
The basic RBAC model is called RBAC0. From there, you get extensions:
- RBAC1 adds role hierarchies—a "supervisor" role can inherit all permissions of a "worker" role.
- RBAC2 introduces separation of duties, so a single user can't hold conflicting roles—like being both a player and a referee. Static separation prevents assigning conflicting roles at all; dynamic separation only prevents activating them in the same session.
- RBAC3 combines both, giving you the full toolkit.
Most systems stick with RBAC0 or RBAC1, and that's usually enough.
Designing a Permission System with RBAC
When you're building a permission system from scratch, think in terms of users, roles, and permissions. Permissions break down into two kinds: menu permissions (what you can see and click) and data permissions (which rows you can access).
Let's say you're working for a mid-sized manufacturing company with thousands of employees. They use an OA system, an HR system, a CRM, and an ERP. Each employee has a different job, so they need different features.
Start with account management. Every person who interacts with the system gets an account tied to their identity—name, department, phone number. Then define roles. What types of people use the system? An HR specialist, a sales rep, a production manager? For each role, decide which menus they see and which buttons they can click. Also decide data scope—should a sales rep see only their own leads or all leads in the region?
The fineness of control is a trade-off. You could stop at the menu level, which is enough for many SaaS tools. Or you could go down to individual buttons and even specific fields, like Salesforce does. The more granular, the more flexible for users, but the more complex for you to build and maintain. There's no universal answer—it depends on the business.
ABAC: Rules Over Roles
ABAC takes a different approach. Instead of predefining roles and permissions, you write rules that evaluate attributes. Attributes can be about the user (age, department), the environment (time of day), the operation (read, write), or the object (a document's classification).
For instance, a rule might say: "Allow all homeroom teachers to enter the school gate during class hours." Here, "homeroom teacher" is a user attribute, "class hours" is an environment attribute, "enter" is the operation, and "school gate" is the object. The system evaluates these attributes dynamically each time a request comes in.
ABAC is incredibly flexible—you can express almost any policy without changing code. But that flexibility comes at a cost. You need a rule engine, configuration files (often XML or YAML), and someone who understands how to write the rules. XACML, an ABAC standard, is powerful but notoriously complex. Even Kubernetes initially tried ABAC and then switched to RBAC in version 1.8 because ABAC was too hard to manage.
So why is RBAC still more popular? Because most applications don't need that level of dynamism. If your access rules are relatively static, RBAC is simpler to understand, implement, and audit. ABAC shines when you have many changing conditions—like a system that must handle compliance rules that vary by region or time.
Picking What Works for You
There's no one-size-fits-all. For a small internal tool, DAC might be fine. For a government agency, MAC is non-negotiable. For most commercial software, RBAC is the sweet spot. But if your team is comfortable with rule engines and you need to handle complex, dynamic policies, ABAC is worth the extra effort.
The key is to start simple. Get RBAC working, then layering on ABAC-like rules if needed. Many systems actually end up as a hybrid. That's fine—what matters is that the model fits your problem, not the other way around.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!