What RBAC is and how to implement permissions in Java
What RBAC is, how roles differ from permissions, and how to keep access control organized in Java APIs.
RBAC (role-based access control) is the most widely adopted authorization model in enterprise applications: users receive roles, roles aggregate permissions, and endpoints check whether the caller may run an action. It looks simple — until the code becomes a tangle of if (user.isAdmin()) scattered through controllers.
Roles vs permissions
- Role — a business grouping (ADMIN, FINANCE, SUPPORT)
- Permission — an atomic action (users:read, invoices:approve, reports:export)
Sound implementations map roles to permissions in the IAM, and the API checks permissions — not hardcoded roles. You can rename a profile in the console without a redeploy.
A practical Spring Boot example
Without a center, every controller repeats rules. With declarative RBAC, the intent sits on the endpoint:
@RestController
@RequestMapping("/api/invoices")
public class InvoiceController {
@GetMapping
@GatekeeperProtected(permissions = "invoices:read")
public List<Invoice> list() { ... }
@PostMapping("/{id}/approve")
@GatekeeperProtected(permissions = "invoices:approve")
public Invoice approve(@PathVariable UUID id) { ... }
}When to use RBAC
- Internal teams with stable profiles (admin, operator, auditor)
- B2B SaaS where each customer defines who can access what
- REST APIs with discrete, auditable actions
RBAC does not solve everything. Attribute-based policies (ABAC) can be necessary when the rule depends on dynamic context (time, region, resource owner). Many products start with RBAC and evolve later.
Common mistakes
- Duplicating role names across services with no convention
- Checking the role in the frontend and forgetting the backend
- Permissions that are too broad (ADMIN does everything) with no granularity
- Not versioning permission changes — integrations break quietly
- Mixing tenant A and tenant B permissions in the same token
How Gatekeeper ID helps
The Gatekeeper console centralizes users, groups, roles, and permissions per tenant. The Spring SDK reads JWT claims and applies @GatekeeperProtected before the handler — one source of truth for authorization.
See also protecting endpoints with annotations and centralizing permissions across microservices. For agents that reach a database, read RBAC for Agents.
Conclusion
Well-modeled RBAC separates identity (who) from authorization (what). In Java, the real gain comes when permissions leave the code and live on a manageable platform — with consistent checks across the API.