Understanding RBAC and Authorization in Spring Security
Once the system knows who you are, RBAC decides what that gets you — and roles are just strings with a convention.

Authentication established who you are. Authorization decides what that identity is allowed to do. Spring Security keeps them strictly sequential — a request has already answered the "who" question and carries a proven identity before anything asks "and are they allowed?" Role-based access control, RBAC, is the most common way to answer that second question: rather than pinning permissions to individual users, you give users roles and attach permissions to the roles.
Roles and authorities are the same thing wearing different labels
Here's the detail that quietly confuses nearly everyone. In Spring Security a role isn't a special type — it's just an authority, which is to say a string, with a naming convention on top. When a user authenticates, they carry a set of GrantedAuthority objects, and those are literally strings like ROLE_ADMIN or READ_PRODUCTS. The only real difference between a "role" and an "authority" is that ROLE_ prefix. Call hasRole("ADMIN") and Spring goes looking for the authority ROLE_ADMIN, adding the prefix on your behalf. Call hasAuthority("READ_PRODUCTS") and it matches that exact string. Same machinery, two doors into it. Once you see that roles are just prefixed authorities, a lot of baffling behaviour stops being baffling — like why your hasRole check silently fails when you stored the authority without the ROLE_.
Two places to enforce the rules
Spring Security lets you check authorization at two levels, and they're suited to different jobs. URL-level rules live in your SecurityFilterChain — broad strokes, like "anything under /admin needs ROLE_ADMIN." They're coarse and they run early, which is efficient. Method-level security is the finer instrument: annotate a service method with @PreAuthorize and Spring evaluates the rule before the method runs. If the check fails, the method is never called — the rejection happens before your business logic executes, not somewhere inside it. That "before" is the whole point. You're not bailing out of a method that shouldn't have started; you're stopping it from starting.
@PreAuthorize and the power of expressions
The reason people reach for @PreAuthorize is that it takes a SpEL expression, which can say far more than "has this role." You can check hasRole('ADMIN'), hasAnyRole(...), or something genuinely contextual — like whether the authenticated user actually owns the resource they're trying to edit. Not "an admin," but "this specific user, operating on their own data." To switch method security on, you add @EnableMethodSecurity to a configuration class. If a tutorial tells you to use @EnableGlobalMethodSecurity, it's dated — that one was deprecated in Spring Security 6.
Where RBAC quietly goes wrong
RBAC is powerful, and its characteristic failure is role sprawl. It starts clean — ADMIN, USER — and a year later you have thirty roles, half of them held by exactly one person, and nobody can tell you what SUPPORT_TIER2_READONLY actually grants. Roles are a modelling decision, not a config detail; keep them few and meaningful. The other trap is believing authorization is only the URL rules. A locked front door means nothing if a service method three layers deep does something sensitive without checking. Defence in depth means the operations that matter verify permission themselves, regardless of how the request reached them.
Authorization is the half of security people underinvest in, because authentication feels like the hard part — the passwords, the tokens, the login screen. But a system that knows exactly who you are and is careless about what you can do is not secure. Getting the roles right, and checking them close to the operations that actually matter, is where the real work quietly lives.






