1 Mastering API Access Control with Keycloak

This article builds upon the insightful work of my colleague Sebastian Fulga; you can read his original piece here
 

When it comes to securing Web APIs, authentication is only half the story. Authorization — knowing who can do what is just as critical, yet often receives less attention. In this follow-up, I’ll walk you through implementing fine-grained authorization using Keycloak, empowering you to manage access precisely. Whether you're just starting with authorization or already working with Keycloak, these steps are clear, practical, and designed with developers in mind. 
 

Keycloak is an open-source single sign-on (SSO) solution licensed under Apache-2.0. Its implementation is publicly available on GitHub. Keycloak offers robust features including strong authentication, user management, identity provider integration, user federation, session control, event logging, and more. It’s highly configurable and has detailed official documentation on its website

Keycloak_Logo

2 Setting Up Keycloak for Fine-Grained Authorization

If you’ve already installed and configured Keycloak using the Docker file mentioned in Sebastian Fulga’s original article, you can begin working with your Keycloak server.

In this guide, we'll use the default master realm for simplicity. However, you’re free to create a new realm if preferred, this won’t impact the core behavior, but it will result in URL paths different from those shown here.

Once deployed, Keycloak should be accessible at: http://localhost:7011/

You can log in using the admin credentials defined in your Docker Compose file.

 

Important Version Note: 
At the time of writing, the current Keycloak version is 26.2.5. Future versions may introduce interface changes or new features, so always refer to the official Keycloak documentation and release notes to stay updated. It's best practice to use the latest stable version to take advantage of ongoing improvements from the development team. 

2.1 Create New User

Create_new_userCreate_New_User_2

After creating a new user in Keycloak, the next step is to set up user credentials. To do this, navigate to the "Credentials" tab within the user's detail page in the Keycloak admin console. 

create_credentials

2.2 Creating a New Client and Enabling Authorization in Keycloak

 

Now that you’ve created a user, the next step is to create a new client in Keycloak and enable the Authorization feature. Creating a client is very similar to creating a user.

To get started, navigate to the “Clients” menu in the Keycloak admin console and click the “Create Client” button.

This client represents the application or backend service that will authenticate via the Keycloak API. In our example, we’ve named the client MyApp, but you can choose any name that fits your project.

Here are the essential settings to configure for the client:

  • Client Authentication: ON
  • Authorization: ON
  • Direct Access Grant: Enabled

These settings ensure that your client is fully equipped to handle secure authentication and fine-grained authorization using Keycloak. 

create_new_client

2.3 Creating User Roles for Your Keycloak Client 

 

For our MyApp client, we need to define user roles. Keycloak has two role types: realm roles and client roles.

  • Realm roles can be assigned across the entire realm and all clients.
  • Client roles are limited to the specific client where they are created.

In this tutorial, we’ll use client roles. To create them, go to the Roles tab under your client’s details page.

We’ll apply the Role-Based Access Control (RBAC) approach to show Keycloak’s flexibility in handling fine-grained permissions.

Create the following roles, which will later be used to control access to backend APIs:

Create_roles

2.4 Configure client Authorization 

 

To enable fine-grained access control, navigate to the Authorization tab under the MyApp client page, just as you did for roles.

Keycloak may auto-generate default resources, policies, and permissions. These can be safely deleted to keep your configuration clean. While setting up the Authorization module may take some time, this guide will walk you through each step.

 

Configure Scopes

Scopes define the specific actions a user can perform and are essential for fine-grained authorization in Keycloak. In this example, we’ll use standard scopes like:

  • manage
  • query
  • view

You can also define custom scopes to match your application's needs. 

Configure_scopes

Configure Resources

Resources represent APIs or features you want to protect. These can range from single endpoints to entire application modules.

In this setup, we’ll create two resources:

  • users – linked to the query, view, and manage scopes
  • fetch-weather – without any scope, to demonstrate resource-based permissions

Note: Resources in Keycloak can have one, many, or no scopes. 

create resourceslist resources

Configure Policies

Policies in Keycloak define the rules that must be satisfied to grant access to a resource. They are evaluated during the authorization process and determine whether a user can access a specific resource.

Policies can be based on various conditions, such as:

  • User roles
  • Client applications
  • User groups
  • Attributes or context (e.g., time, regex patterns)

In this guide, we’ll create role-based policies for each of the client roles (user, admin, manager) defined earlier.

These policies will form the foundation for assigning permissions to protected resources. 

create policies

There are a few key aspects to understand when configuring role-based policies in Keycloak:

 

  1. Multiple Roles: A single policy can include various roles. The "Required" checkbox determines whether a role must be present for access. In our case, since each policy includes just one role, it will be required by default. For multi-role policies, be sure to define which roles are mandatory. 
     
  2. Fetch Roles: This option is disabled by default. When enabled, Keycloak fetches roles in real time from the database rather than relying solely on the roles present in the access token. This can be powerful for dynamic role evaluation. If left disabled, users will retain the roles from their current token until a new token is issued. 
     
  3. Logic Setting: The "Logic" configuration controls how decisions are applied:
  • Positive: The policy behaves as defined, permits access, and denies blocks it.
  • Negative: The result is inverted, the permit becomes denied, and vice versa.

By the end of this section, you should have a complete list of role-based policies, each linked to one of the roles created earlier.

listing policies

Configure Permissions

 

The final step in setting up Keycloak fine-grained authorization is to configure permissions. This step must come last, as it depends on previously defined resources, scopes, and policies.

Permissions control what actions a user or client can perform on specific resources or scopes. They are a key part of Keycloak's authorization module, enabling precise access control by linking resources to the policies that govern access decisions.

 

Keycloak supports two types of permissions:

  1. Scope-based permissions – applied to specific actions or scopes
  2. Resource-based permissions – applied directly to a resource

 

For this demo, we’ll use both types:

  • Scope-Based Permissions:
  1. permission_query-users
  2. permission_view-users
  3. permission_manage-users

 

  • Resource-Based Permission:
  1. permission_fetch-weather
create_permissions

There are a few key points worth noting:

  1. Permissions can simultaneously support one or more 'Authorization scopes'.
  2. Similarly, multiple 'Policies' can be backed by Permissions at the same time.
  3. The 'Decision strategy' dictates how the policies associated with a given permission are evaluated and how a final decision is reached. Here are the options:
  • 'Affirmative' implies that at least one policy must be positive.
  • 'Unanimous' means that all policies must be favorable.
  • 'Consensus' means that the number of positive outcomes must outweigh the number of negative ones.

In the end we will have the following permissions:

Listing_permissions

We observe that we have one permission of the type 'Resource-Based'. This permission is much like the others, except that the scope is not a prerequisite.

Now that we have everything in place, we can delve into the code to investigate how we handle authorization. However, before we do that, roles must be assigned to our user; otherwise, we'll lack access to our APIs.

Navigate to the Users tab in Keycloak, and then proceed to our user to assign all the roles from our MyApp client, just as illustrated:

Assign_roles_to_user

3 How to Implement Fine-Grained Access Control with Keycloak

Let's start with the project structure, although this is not very important since you can create your own file structure. Since this is just a demo project, we will keep it simple.

Project_structure

Dependencies required from NuGet gallery:

- Microsoft.AspNetCore.Authentication.JwtBearer

Appsettings.json:

AppSettings_json_file

To validate JSON Web Tokens (JWT) in your ASP.NET Core application, you typically configure a JwtSettings section in appsettings.json. When using Keycloak, you don't need to set a secret key manually. Instead, Keycloak simplifies JWT signature verification by exposing a MetadataAddress endpoint.

This metadata endpoint (/.well-known/openid-configuration) provides Keycloak’s OpenID Connect configuration. It includes essential information such as:

  • The issuer (iss)
  • Supported scopes and response types
  • Authorization and token endpoints
  • Public keys for JWT signature validation
  • Logout endpoints and supported algorithms

With this built-in support, Keycloak enables secure and standardized token validation with minimal manual setup.

Next, you’ll define a custom authorization requirement by creating a new class: PermissionRequirement.cs. This record should implement Microsoft's IAuthorizationRequirement interface.AspNetCore.Authorization namespace.

This class forms the foundation for a custom authorization policy, allowing you to enforce fine-grained access control based on your application’s logic, such as user roles, scopes, or specific permissions.

Permission_requirement_record

Then we need to create a new file named ApplicationPolicies.cs that will contain two classes:

defined_backend_policies

In our code, we have defined a static class known as DependencyInjection. The purpose of this class is to house our helper methods for dependency injection. These helper methods are designed as extension methods and these are being invoked in the Program.cs file.

DependencyInjection_helper_class

In this section, we're setting up Authentication and Authorization for our service. We're also adding http clients. As an extra step, we're setting up a reverse proxy, which we'll discuss in more detail later.

We need to specify the previously defined necessary policies within the AddAuthorization method.

 

For simplicity, we stick with minimal APIs, which are the examples in the Program.cs file:

Program_class

All API requests in this demo are GET requests, designed to return simple messages that confirm Keycloak authorization is functioning correctly.

Protected Endpoints and Required Policies:

  •  /api/users → Requires the QueryUsers policy
  • /api/users/{id} → Requires the ViewUsers policy
  • /api/users/manage → Requires the ManageUsers policy

To enforce these policies, we’ve implemented a custom authorization handler called RequestBasedHandler. This handler sends a request to Keycloak on each API call to:

  •  Verify the user's authentication
  • Validate the applied authorization policy

In our setup, the client (we’re using Postman) sends API requests with the Keycloak-issued access token, retrieved from: http://localhost:7011/realms/master/protocol/openid-connect/token

This ensures each API request is checked in real time against the latest Keycloak roles and permissions.

 

RequestBasedHandler:

RequestBasedHandler

Let's now authenticate and get a new access token from Keycloak:

<pre><code class="language-bash">
curl --location 'http://localhost:7011/realms/master/protocol/openid-connect/token/' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIx...' \
--data-urlencode 'client_id=MyApp' \
--data-urlencode 'audience=MyApp' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \
--data-urlencode 'response_mode=permissions'
</code></pre>
 

This request returns a JSON object containing the list of all authorized resources and associated scopes for the authenticated user. This is useful for debugging, auditing, or dynamically adapting frontend behavior based on user permissions.

[ { "rsid": "0d7d72a8-8cc8-47b0-a38b-b973d9b197da", "rsname": "fetch weather" }, { "scopes": [ "view", "manage" ], "rsid": "38ffed86-d128-4eff-a1f9-261727c9548e", "rsname": "users" } ]

Share on:

* I read and understood the ASSIST Software website's terms of use and privacy policy.

Want to stay on top of everything?

Get updates on industry developments and the software solutions we can now create for a smooth digital transformation.

Frequently Asked Questions

1. Can you integrate AI into an existing software product?

Absolutely. Our team can assess your current system and recommend how artificial intelligence features, such as automation, recommendation engines, or predictive analytics, can be integrated effectively. Whether it's enhancing user experience or streamlining operations, we ensure AI is added where it delivers real value without disrupting your core functionality.

2. What types of AI projects has ASSIST Software delivered?

We’ve developed AI solutions across industries, from natural language processing in customer support platforms to computer vision in manufacturing and agriculture. Our expertise spans recommendation systems, intelligent automation, predictive analytics, and custom machine learning models tailored to specific business needs.

3. What is ASSIST Software's development process?  

The Software Development Life Cycle (SDLC) we employ defines the following stages for a software project. Our SDLC phases include planning, requirement gathering, product design, development, testing, deployment, and maintenance.

4. What software development methodology does ASSIST Software use?  

ASSIST Software primarily leverages Agile principles for flexibility and adaptability. This means we break down projects into smaller, manageable sprints, allowing continuous feedback and iteration throughout the development cycle. We also incorporate elements from other methodologies to increase efficiency as needed. For example, we use Scrum for project roles and collaboration, and Kanban boards to see workflow and manage tasks. As per the Waterfall approach, we emphasize precise planning and documentation during the initial stages.

5. I'm considering a custom application. Should I focus on a desktop, mobile or web app?  

We can offer software consultancy services to determine the type of software you need based on your specific requirements. Please explore what type of app development would suit your custom build product.   

  • A web application runs on a web browser and is accessible from any device with an internet connection. (e.g., online store, social media platform)   
  • Mobile app developers design applications mainly for smartphones and tablets, such as games and productivity tools. However, they can be extended to other devices, such as smartwatches.    
  • Desktop applications are installed directly on a computer (e.g., photo editing software, word processors).   
  • Enterprise software manages complex business functions within an organization (e.g., Customer Relationship Management (CRM), Enterprise Resource Planning (ERP)).

6. My software product is complex. Are you familiar with the Scaled Agile methodology?

We have been in the software engineering industry for 30 years. During this time, we have worked on bespoke software that needed creative thinking, innovation, and customized solutions. 

Scaled Agile refers to frameworks and practices that help large organizations adopt Agile methodologies. Traditional Agile is designed for small, self-organizing teams. Scaled Agile addresses the challenges of implementing Agile across multiple teams working on complex projects.  

SAFe provides a structured approach for aligning teams, coordinating work, and delivering value at scale. It focuses on collaboration, communication, and continuous delivery for optimal custom software development services. 

7. How do I choose the best collaboration model with ASSIST Software?  

We offer flexible models. Think about your project and see which models would be right for you.   

  • Dedicated Team: Ideal for complex, long-term projects requiring high continuity and collaboration.   
  • Team Augmentation: Perfect for short-term projects or existing teams needing additional expertise.   
  • Project-Based Model: Best for well-defined projects with clear deliverables and a fixed budget.   

Contact us to discuss the advantages and disadvantages of each model. 

ASSIST Software Team Members