Resources in Authorization Services — Keycloak
A zero-prior-knowledge guide to Resources — the building block Keycloak's Authorization Services uses to describe exactly what is being protected, before any policy ever decides who gets to touch it.
Before any security system can decide who is allowed to do what, it first needs a precise way of naming the “what.” A hospital cannot write a rule like “only nurses can view records” until it has clearly defined what “a record” even means as a distinct, protectable thing. Keycloak’s Authorization Services face exactly this problem, and they solve it with a concept called the Resource. This article explains, from first principles, what a Resource actually is inside Keycloak, how it fits alongside scopes, policies, and permissions, and why getting resource modeling right is the foundation every other authorization decision in the system is built on top of.
Foundations
Core Concepts
Authorization Services is a feature layered on top of Keycloak’s core identity platform, and Resources are the very first thing you define when using it.
Authentication versus authorization, again
Keycloak’s basic login system answers “who is this person?” — that is authentication. Authorization Services answers a much harder follow-up question: “now that we know who they are, exactly what are they allowed to do, to which specific things?” This second question requires a vocabulary for describing the things being protected in the first place, and that vocabulary starts with the Resource.
What is a Resource?
A Resource is a named representation, registered inside Keycloak, of something in your application that deserves protection — a specific bank account, a document, an API endpoint, an entire category of records, or even an abstract concept like “the admin dashboard.” A Resource does not, by itself, decide who can access it. It simply says, clearly and formally, “this thing exists, and it is a thing that authorization decisions can be made about.”
Think of a large corporate archive room full of filing cabinets. Before the archive can enforce any rule about who may open which drawer, someone first has to label every drawer — “Payroll Records 2024,” “Client Contracts — Northeast Region,” “Executive Board Minutes.” A Resource in Keycloak is exactly that label. It does not lock the drawer itself; it simply gives the drawer a name precise enough that a rule can later be written about it.
Resources are not the same as roles
People new to Keycloak often confuse Resources with the roles they may already know from basic role-based access control, such as “admin” or “editor.” Roles describe something about the user — a label attached to a person or account. A Resource describes something about the thing being protected — a label attached to a piece of data, an endpoint, or a feature. Authorization Services becomes powerful precisely because it lets you combine both sides: which users, in which roles, under which conditions, can perform which actions, on which specific Resources.
Role
“This person is a Manager.” A property of the identity, unrelated to any specific piece of data.
Resource
“This is Invoice #4471.” A named, protectable object that exists independently of who is asking about it.
Scope
“Viewing” or “editing.” A specific action that can be performed on a Resource, covered in the next chapter.
Permission
The actual rule: which Policy, applied to which Resource and Scope, produces an allow or deny decision.
With this vocabulary in place, Keycloak can express far richer rules than plain role checks alone ever could — rules that consider not just who the user is, but exactly which object they are trying to touch and exactly what they are trying to do to it.
Structure
Architecture & Components
A Resource never exists in isolation. It lives inside a small ecosystem of related concepts that together make up Keycloak’s Authorization Services.
The Resource Server
Every Resource belongs to a Resource Server — which, despite the grand-sounding name, is simply a Keycloak client that has had Authorization Services turned on for it. The Resource Server is the application that actually owns and protects the data or functionality in question; it is the one that registers Resources, defines Scopes, writes Policies, and ultimately enforces the decisions Keycloak hands back.
Scopes — the actions that can be taken
A Scope represents a specific action or capability associated with a Resource, such as “view,” “edit,” “delete,” or “approve.” A single Resource can be associated with several Scopes at once, allowing very fine-grained rules — for example, a rule that lets a wide group of users “view” an invoice, but restricts “approve” to a much smaller group, even though both actions target the exact same Resource.
Resource Types — templates for repeated resources
Rather than manually registering thousands of nearly identical Resources one by one, Keycloak supports grouping Resources by a shared type, such as “invoice” or “document.” This lets a single set of Policies and Permissions apply consistently across an entire category, while still allowing individual Resources within that category to carry their own specific attributes when finer distinctions are needed.
Policies and Permissions — the rules that reference Resources
A Policy defines a condition for access — such as “user must have the Manager role,” “request must come from a specific group,” or “access only allowed during business hours.” A Permission is what ties everything together: it associates one or more Resources (and optionally specific Scopes on them) with one or more Policies, producing the actual enforceable rule Keycloak evaluates at request time.
flowchart TD
A["Resource Server (a Keycloak client)"] --> B["Registers Resources"]
A --> C["Defines Scopes"]
A --> D["Writes Policies"]
B --> E["Resource: Invoice #4471"]
C --> F["Scope: view"]
C --> G["Scope: approve"]
D --> H["Policy: has Finance role"]
E --> I["Permission: view+approve on Invoice, guarded by Finance policy"]
F --> I
G --> I
H --> I
I --> J["Authorization decision at request time"]
Fig 1 — How a Resource combines with Scopes and Policies inside a Permission to produce a real authorization decision.
Notice that the Resource itself never contains any access rules. It is purely descriptive. All of the actual decision-making logic lives in Policies and Permissions, which is exactly what makes the model flexible — the same Resource can be referenced by many different Permissions serving different purposes without ever needing to be redefined.
Mechanics
Internal Working
This chapter looks at what actually happens, step by step, when Keycloak registers and later evaluates a Resource during a real authorization check.
How a Resource is registered
A Resource is registered with a unique name inside its Resource Server, optionally paired with a URI pattern that maps it to a real endpoint in the protected application, a set of associated Scopes describing which actions apply to it, and optionally an owner — the specific user the Resource belongs to, which becomes important in user-managed scenarios covered later in this article. Once registered, the Resource exists as a stable, addressable entity inside Keycloak’s authorization data, independent of any particular request.
Static versus dynamic Resources
Some Resources are defined once, ahead of time, by an administrator — for example, “the admin dashboard” or “the billing settings page,” which are fixed features of the application. Others are created dynamically, at runtime, as the application’s own data grows — for example, a new “Resource” being registered in Keycloak the instant a user uploads a new document, so that a Permission can immediately be attached specifically to that one document rather than to documents in general.
A hotel has a fixed set of amenities — the gym, the pool, the business center — registered once when the building opens; these are like static Resources. But every time a new guest checks in, a brand-new hotel room becomes a distinct thing that specifically needs its own access rule for that one guest during their stay; this is like a dynamically created Resource, generated on the fly as the underlying data — the reservation — comes into existence.
How the evaluation actually happens
When a protected application receives a request, it does not decide access itself. Instead, it asks Keycloak’s authorization engine to evaluate the request, passing along which Resource (and often which Scope) the request concerns, together with the identity of the requesting user. Keycloak looks up every Permission associated with that Resource, evaluates the underlying Policies attached to each one, and returns a decision — typically embedded inside a special authorization-aware token called a Requesting Party Token, or RPT — that the application then uses to allow or reject the specific action being attempted.
Resource attributes
Beyond a name and a URI, Resources can carry additional custom attributes — arbitrary key-and-value details specific to the application’s own domain, such as a department code or a classification level. These attributes can then be referenced inside more advanced Policy types, allowing decisions that depend not just on who the user is, but on specific characteristics of the Resource itself at the moment of the request.
Lifecycle
Data Flow & Lifecycle
Following a single document through its entire life shows exactly where Resources enter and influence the picture.
Document is created
A user uploads a new file inside the application. The application calls Keycloak’s Protection API to register a brand-new Resource representing that specific document, often tagging the uploading user as its owner.
Scopes are attached
The application associates the relevant Scopes with the new Resource — commonly “view,” “edit,” and “delete” — describing every action that could ever meaningfully be performed on this particular document.
A Permission is applied
Either automatically, through a Resource-type default, or explicitly, a Permission ties this Resource and its Scopes to one or more Policies — for example, “only the owner and members of the Legal group may view or edit this document.”
A colleague requests access
Another user attempts to open the document. The application asks Keycloak’s authorization engine to evaluate the request against the specific Resource and the “view” Scope.
Keycloak evaluates and responds
Keycloak checks the Policies attached through the relevant Permission, determines whether this specific user satisfies them, and returns an allow or deny decision back to the application.
Document is deleted
When the document is eventually removed from the application, the corresponding Resource is also deregistered from Keycloak, cleanly removing it — and any Permissions specific to it — from future evaluation.
Weighing the Choice
Advantages, Disadvantages & Trade-offs
Modeling authorization around explicit Resources is powerful, but it is also a genuinely bigger commitment than simply checking a user’s role in application code.
Advantages
- Enables fine-grained, per-object rules that plain role checks cannot express, such as “the owner of this specific record, plus their direct manager”
- Centralizes authorization logic inside Keycloak rather than scattering access-control conditions across many different applications and codebases
- Allows access rules to be changed centrally, without redeploying the protected application, since Policies and Permissions live in Keycloak’s configuration
- Supports genuinely dynamic, data-driven access scenarios, including user-managed and resource-owner-driven access
- Provides a consistent authorization model across many applications sharing the same Keycloak realm
Disadvantages & Trade-offs
- Requires more upfront modeling effort than a simple role check, since every protectable thing must first be identified and registered as a Resource
- Adds a network round trip to Keycloak’s authorization engine for evaluation, introducing latency that a purely in-application role check would not have
- Dynamically registering a Resource for every single piece of user-generated data can create a very large number of Resources that must be managed and eventually cleaned up
- Understanding how Resources, Scopes, Policies, and Permissions interact has a steeper learning curve than simpler access-control models
When the complexity is worth it
For an application with a handful of fixed screens and a small number of roles, plain role-based checks are often perfectly sufficient, and introducing full Resource-based Authorization Services would be unnecessary overhead. The trade-off becomes worthwhile once an application needs to protect individual pieces of user-owned or dynamically created data — documents, records, projects — where “who can see this specific thing” genuinely cannot be answered by a role alone.
Defense
Security
Resources sit at the very center of Keycloak’s fine-grained authorization model, which means mistakes in how they are modeled or protected have outsized security consequences.
The Protection API must itself be protected
Registering, updating, and deregistering Resources happens through Keycloak’s Protection API, which requires its own dedicated access token to call. If this Protection API access is not properly restricted to trusted backend services, an attacker who gains access to it could register fraudulent Resources, tamper with existing ones, or manipulate ownership assignments, undermining every downstream Permission that depends on accurate Resource data.
Resource ownership and user-managed access (UMA)
Keycloak’s Authorization Services are built on an open standard called User-Managed Access, or UMA, which allows a Resource’s owner — often the end user themselves, rather than an administrator — to grant or share access to their own Resources with other specific users, similar in spirit to sharing a single file with a named colleague. This is powerful for building applications where end users control their own data sharing, but it also means the security of the entire model depends on Resource ownership being assigned correctly and consistently at creation time.
It is easy to assume that once a Resource is registered, Keycloak automatically knows who “owns” it in a real-world sense. In reality, ownership is only whatever the application explicitly declared at registration time. An application that registers Resources without carefully and correctly assigning ownership can accidentally create Resources with no real owner, or worse, with an incorrect one, silently breaking any user-managed sharing built on top of it.
Stale or orphaned Resources
If an application deletes the underlying data — a document, a record, an account — without also deregistering the corresponding Resource in Keycloak, the Resource becomes an orphaned entry that no longer maps to anything real, yet can still be referenced by Permissions and potentially still be evaluated as accessible. Keeping Resource lifecycle tightly synchronized with the application’s own data lifecycle is essential to avoid this kind of quiet configuration drift.
Over-broad Resource modeling
Modeling too coarsely — for example, registering a single Resource called “All Documents” instead of one Resource per document — collapses fine-grained control back down to something closer to a simple role check, defeating much of the purpose of using Authorization Services in the first place, and potentially granting broader access than intended once a Permission is attached to that overly broad Resource.
Visibility
Monitoring, Logging & Metrics
Because authorization decisions here depend on several moving parts, visibility into how Resources are actually being used and evaluated matters as much as the configuration itself.
Reviewing Resources in the admin console
Keycloak’s admin console provides a dedicated Authorization tab per client, listing every registered Resource, its associated Scopes, and the Permissions referencing it. This gives administrators a direct, searchable inventory of exactly what is being protected, which is essential for auditing whether the application’s real data still matches what Keycloak believes exists.
The built-in Policy Evaluation tool
Keycloak includes a Policy Evaluation feature directly inside the admin console, letting an administrator simulate a specific user requesting a specific Scope on a specific Resource, and see exactly which Policies fired, and why the final decision came out the way it did. This is invaluable for debugging unexpected access denials or unexpected grants without having to reproduce the exact scenario inside the live application.
Watching for growth and drift over time
In applications that dynamically create Resources for every piece of user data, the sheer number of registered Resources can grow very large over time. Periodically reviewing this inventory — checking for orphaned Resources tied to deleted data, or Resources whose ownership no longer matches reality — helps keep the authorization model accurate and prevents silent configuration drift from accumulating unnoticed.
Shape
Design Patterns & Anti-patterns
How an organization chooses to model its Resources has a much bigger long-term impact on maintainability than any individual Policy ever will.
Pattern: Type-based Resources with shared Permissions
Rather than writing a unique Permission for every single Resource, mature deployments group similar Resources under a shared Resource Type, and attach Permissions to the type itself wherever the same rule genuinely applies across the whole category, reserving Resource-specific Permissions only for genuine exceptions.
Pattern: Owner-driven sharing for user-generated content
Applications where end users create and privately own their own content — personal documents, projects, playlists — commonly lean on UMA-based, owner-driven Permissions, letting the actual data owner decide who else can access a specific Resource, rather than forcing every sharing decision through a central administrator.
Pattern: Attribute-driven Resources for cross-cutting rules
Attaching meaningful attributes to Resources — such as a department code or a sensitivity classification — lets a single Policy reference that attribute and apply consistently across many different Resources of different types, without needing a separate Permission written out for every individual case.
Anti-pattern: One Resource per user session instead of per real object
A subtle but damaging mistake is modeling Resources around something transient, like a user’s current session or a single page view, rather than the actual underlying object being protected. This produces a flood of short-lived, meaningless Resources that add overhead without producing any lasting, reusable authorization value.
Situation
A team building a document-sharing feature registers a single, generic “Documents” Resource for the entire application, and writes one Permission granting access to anyone with the “Employee” role, planning to add finer control “later.”
Consequence
Every employee can immediately view every document in the system, regardless of who uploaded it or what it contains, because the model never had a way to distinguish one document from another — the coarse Resource design made per-document control impossible to retrofit without a significant rework.
Better Approach
Register a distinct Resource per document at creation time, tagged with an owner and relevant attributes, and use a shared Resource Type with default Permissions from the very beginning, so fine-grained control is available immediately rather than requiring a painful migration later.
Getting It Right
Best Practices & Common Mistakes
A short list of habits consistently separates a Resource model that scales cleanly from one that becomes an unmanageable tangle within a year.
Model Resources around real, stable objects
A document, a record, an account — not a page view, a session, or a fleeting request.
Assign ownership correctly at creation time
Get this right from the very first registration, since retrofitting correct ownership later is far harder than setting it up properly at the start.
Use Resource Types to avoid Permission sprawl
Group similar Resources so one well-written Permission can govern an entire category instead of hundreds of near-identical individual rules.
Keep Resources synchronized with application data
Deregister a Resource the moment its underlying data is deleted, to avoid orphaned entries lingering in the authorization model.
Modeling too coarsely
A single Resource covering an entire category of sensitive data eliminates the fine-grained control the system was chosen for in the first place.
Leaving the Protection API loosely secured
Any service able to register or modify Resources effectively controls the foundation every Permission is built on — it deserves the same scrutiny as any other privileged credential.
Before registering your first Resource, write down, in plain language, the exact sentence you want to be able to say about access — “only the owner and their manager can approve this specific invoice.” If that sentence cannot be expressed cleanly with the Resources, Scopes, and Policies you are about to create, the modeling likely needs another pass before implementation begins.
In Practice
Real-World & Industry Examples
Resource-based authorization shows up most visibly in applications where “who can see this one specific thing” is a genuinely hard question that a role alone cannot answer.
Document and content management platforms
Enterprise document platforms commonly register one Resource per uploaded file, tagging each with an owning department and sensitivity level as attributes, then use shared Resource-Type Permissions so that a single rule like “Finance department documents are visible only to Finance staff and their direct managers” applies consistently across thousands of individual files without a separate rule per document.
Multi-tenant SaaS platforms
Software-as-a-service products serving many separate customer organizations from one shared Keycloak realm frequently register a Resource per customer account or workspace, ensuring that Permissions can strictly isolate one tenant’s data from another’s, even though every tenant shares the exact same underlying application code and infrastructure.
Consumer applications with user-owned data
Applications that let users share their own content with specific other people — a shared calendar, a personal photo album, a smart-home device — often build directly on UMA-style, owner-managed Resources, letting each user grant or revoke access to their own specific Resources without any administrator needing to be involved in every individual sharing decision.
Healthcare records systems
Systems managing patient records frequently model each patient’s record as its own Resource, with Permissions referencing attributes like the treating department or care team assignment, allowing access rules precise enough to satisfy regulatory requirements that only specifically involved clinical staff can view a given patient’s information.
Questions Answered
FAQ
Wrapping Up
Summary & Key Takeaways
A Resource in Keycloak’s Authorization Services is, at heart, a simple idea doing a lot of quiet, foundational work: give every protectable thing in your application a clear, stable name before ever writing a single rule about who can touch it. Everything else in the system — Scopes describing possible actions, Policies describing conditions, Permissions tying it all together into an enforceable decision — depends entirely on Resources being modeled thoughtfully from the very start. Get the Resource model right, and fine-grained, per-object authorization becomes a natural extension of the application’s real data. Get it wrong, and every Policy built on top inherits the same confusion.
Key Takeaways
- A Resource is a named, protectable thing — a document, an endpoint, a feature — registered inside a Resource Server, describing what exists rather than who can access it.
- Resources, Scopes, Policies, and Permissions are four distinct pieces — the noun, the verb, the condition, and the enforceable rule, respectively.
- Resources can be static or dynamic — some are defined once by an administrator, others are created automatically as real application data comes into existence.
- Ownership powers user-managed access — built on the open UMA standard, letting end users share their own Resources without administrator involvement in every decision.
- Coarse modeling defeats the purpose — a Resource that covers too broad a category collapses fine-grained control back down to something closer to a simple role check.
- The Protection API is itself a privileged surface — whoever can register or modify Resources effectively shapes the entire authorization model built on top of them.
- Keycloak decides, the application enforces — a returned authorization decision only matters if the protected application actually checks and acts on it.