What Are They Allowed to Do? RBAC Roles, ABAC Policies, Resource ACLs, OAuth 2 Delegation & JWT Enforcement
1 The Core Paradigm: “What are they allowed to do?”
Every secure distributed system enforces a strict boundary between Identity Verification and Permission Enforcement. Authentication must happen first; once the user’s identity is cryptographically validated, the system queries its authorization model to evaluate whether the requested operation is permitted.
📥 Incoming Client Request (Credentials / Bearer JWT)
sub: user_123)user_123 have permission to perform DELETE /api/posts/99?”Evaluated against: RBAC roles, ABAC attributes, or Resource ACLs✅ Allowed Actions
Policy permits action ➔ Forward to Business Logic & Controller.
HTTP 200 / 204 Success🚫 Denied Actions
Policy rejects action ➔ Short-circuit request immediately.
HTTP 403 ForbiddenProduction enterprise platforms rarely use one model in isolation. Real architectures combine multiple models:
2 Model 1: RBAC (Role-Based Access Control)
In RBAC, permissions are not assigned directly to individual users. Instead, permissions are grouped into Roles (e.g., Admin, Editor, Viewer), and users are assigned one or more roles.
Permissions: Full Superuser Access.
Permissions: Content Operations.
Permissions: Read-Only Access.
Administrator, Developer, Analyst, Support Specialist, View-Only.Super Admin, Editor, Author, Contributor, Subscriber.// Express.js declarative RBAC guard
function requireRole(...allowedRoles: string[]) {
return (req: Request, res: Response, next: NextFunction) => {
const user = req.user; // populated by JWT verification middleware
if (!user) {
return res.status(401).json({ error: "Unauthenticated" });
}
const hasRole = user.roles.some((role) => allowedRoles.includes(role));
if (!hasRole) {
return res.status(403).json({
error: "Forbidden: Insufficient privileges",
required: allowedRoles,
actual: user.roles
});
}
next();
};
}
// Protected route binding
app.delete("/api/v1/users/:id", requireRole("admin"), deleteUserHandler);
app.post("/api/v1/posts", requireRole("admin", "editor"), createPostHandler);
app.get("/api/v1/posts", requireRole("admin", "editor", "viewer"), listPostsHandler); As organizations grow, pure RBAC breaks down. What happens when an editor can edit documents, but only if the document is in draft mode, in their region, and during business hours? You are forced to invent hundreds of hyper-specific roles like Editor_US_East_DraftOnly_Weekday. This is where ABAC solves the problem.
3 Model 2: ABAC (Attribute-Based Access Control)
Rather than evaluating static role names, ABAC dynamically evaluates policies based on contextual attributes across three primary dimensions: the Subject (User), the Resource, and the Environment.
department (e.g. “HR”, “Finance”)age / employmentTypeclearanceLevel (e.g. Level-3)organizationIdconfidentiality (e.g. “internal”, “top-secret”)ownerId (e.g. “user_123”)classification / projectTagstatus (e.g. “published” vs “draft”)timeOfDay (e.g. current_time < 18:00)ipLocation / geoCountrydeviceType (e.g. Corporate Laptop vs Unknown Mobile)tlsVersion / VPN connection state📝 Example Policy from Real World (Handwritten Note):
allow = (user.department == “HR”) && (time < 18:00) && (resource.confidentiality == “internal”)
User attempts action on target object
Enrich with DB metadata & clock/IP info
Execute Boolean expression rules
200 OK or 403 Forbidden
4 Model 3: ACL (Access Control Lists)
In ACL, instead of attaching roles to users or writing broad attribute policies, each resource holds its own individual list of permitted subjects and their granted actions.
document_quarterly_report.pdfEach resource owns its permission list
When you click “Share Document” in Google Drive and type a specific colleague’s email with “Commenter” or “Editor” permissions, you are directly appending a row to that specific file’s Access Control List.
Unmatched fine-grained user-to-resource sharing capability. Ideal for multi-user file storage.
Auditing is excruciating (“Show me all 100,000 files Bob can read”). Querying requires expensive joins on ACL mapping tables.
5 Authorization Models: Comparison Matrix
Choosing the right authorization model is one of the most consequential architectural decisions in database and backend design:
| Model | Core Concept | Granularity | Best Used For | Primary Bottleneck |
|---|---|---|---|---|
| RBAC | Users ➔ Roles ➔ Permissions | Coarse | B2B SaaS dashboards, Stripe, CMS platforms | Role explosion when nuanced business rules emerge |
| ABAC | Policies on User, Resource & Env attributes | Dynamic & Fine | Healthcare (HIPAA), Finance, Government clearance | Policy evaluation complexity & attribute retrieval latency |
| ACL | Resource stores table of permitted subjects | Ultra-Granular | Google Drive, Dropbox, AWS S3 object sharing | Auditing across resources & massive scale table joins |
6 OAuth 2 Delegation: Access on Behalf of the User
As illustrated in page 4 of the notes, the textbook scenario is connecting Vercel to GitHub so Vercel can clone repositories and deploy code on your behalf:
The user clicks “Connect GitHub” on the Vercel dashboard.
GitHub presents consent modal: “Vercel wants permission to read:repo, read:user”. Notice it explicitly does not request delete:repo!
User clicks “Authorize”. GitHub redirects back with a short-lived, single-use authorization_code.
Vercel trades the code + client_secret for a scoped Access Token.
read:repo, not delete:repo).7 Token-Based Authorization: JWT Claims & Enforcement
In distributed microservices, we don’t query a database for every single user privilege check. Instead, we use Token-Based Authorization where cryptographically signed tokens (JWTs) carry identity claims and scopes directly to downstream services.
👤 User
🎟️ JWT Token
🖥️ Server Backend
📋 Decoded JWT Payload (From Handwritten Note)
Claims & Scopes⭐ The Key Distinction (The Golden Rule of AuthZ)
“Token carries identity and claims, and authorization models define what is allowed.
Tokens are just the transport mechanism. They don’t make decisions — your backend does.”
8 Production Scale: PEP / PDP & Google Zanzibar (ReBAC)
In high-scale enterprise architectures, mixing authorization logic directly inside endpoint handler code creates spaghetti code. Standard engineering patterns decouple policy evaluation into dedicated architectural layers:
The guard at the gate (API Gateway, reverse proxy, or HTTP middleware). It intercepts incoming requests, extracts tokens, asks the PDP for a verdict, and strictly denies (403) or permits the request.
The brain. A dedicated engine (such as Open Policy Agent / OPA) that executes compiled declarative logic (like Rego) against attributes and inputs to return a pure Boolean allow: true.
Relationship-Based Access Control. Used by Google (Drive, YouTube, Cloud) to handle billions of ACLs. Instead of tables, permissions are modeled as graph relation tuples (e.g. doc:42#viewer@user:alice).
🚀 OPA / Rego Sidecar Engine
Each microservice runs a local Open Policy Agent sidecar process in memory. Zero network hop latency when evaluating ABAC/RBAC rules!
default allow = false
allow {
input.method == “GET”
input.user.roles[_] == “viewer”
}🌐 Google Zanzibar Graph Store
Solves deep nested group memberships (e.g. “Alice is in Team A which is inside Org B which has viewer rights on Folder C containing File D”).
Check(User, Relation, Object)
➔ Evaluates graph traversal in <10ms at global scale.
9 Quick Revision & Interview Takeaways
AuthN: Who are you? (401 if missing/invalid).
AuthZ: What can you do? (403 if forbidden).
Never give your password to third parties. Tokens grant specific, revocable scopes (e.g. read:repo).
A JWT is just the carrier of claims. Your backend decision engine (PDP) decides whether the operation is permitted!