Breaking Down Complex Authorization Beyond Login with ZITADEL

Dakshitha Ratnayake
6 min readDec 1, 2023

--

Photo by Kyle Glenn on Unsplash

As we move towards a zero-trust mindset, the limitation of coarse-grained security measures like the traditional RBAC system become clear. An essential part of the shift to zero trust that often goes undiscussed is the move from coarse-grained to fine-grained security. Fine-grained authorization addresses this by basing access on attributes like user roles, actions, and even context like time or location, and such detailed access control is vital for contemporary applications. This article discusses how ZITADEL caters to the need for such nuanced authorization. With ZITADEL’s features like roles, meta-data, and actions, users can obtain highly detailed access control suited for a zero-trust setting. Additionally, ZITADEL can work with external authorization services.

Authorization Mechanisms Offered by ZITADEL

ZITADEL is an open source, cloud-native Identity and Access Management solution (IAM) that provides various security mechanisms to secure applications and services. It uses a range of different authorization strategies, including Role-Based Access Control (RBAC) and Delegated Access.

Role-Based Access Control (RBAC) and Delegated Access

ZITADEL uses RBAC to manage user permissions, where permissions are tied to roles and users are allocated these roles. This simplifies user access management based on their organizational roles. An additional feature allows roles to be delegated to other organizations, facilitating permissions sharing with external entities. This is especially valuable for interconnected or hierarchical organizations. While these capabilities offer robust access control, they might not be enough for intricate authorization needs, hence the importance of exploring fine-grained authorization in ZITADEL.

The Actions Feature, Custom Metadata, and Claims for Attribute-based Access Control (ABAC)

ZITADEL enhances the traditional RBAC by introducing its dynamic Actions feature for attribute-based access control (ABAC). Unlike RBAC, which grants access based on user roles, ABAC is more versatile, assessing attributes linked to the user, action, and resource during access requests. With ZITADEL’s Actions, post-authentication scripts can be created to analyze specific user attributes and block access when necessary.

Actions can also establish custom claims to boost the ABAC system, enabling advanced authorization models that restrict access based on attributes like location, time, or any definable factor. ZITADEL lets administrators or permitted developers add custom metadata to users and organizations, amplifying fine-grained access control possibilities. It supports aggregated claims by gathering extra data from external systems like CRM or HR tools. ZITADEL can also manage unique resources, such as shipping orders or IoT devices, and determine access based on attributes like User-Sub, Roles, Claims, IP, and more.

Extending ZITADEL’s Existing Capabilities for Fine-Grained Access Control

Despite the comprehensive features that come with ZITADEL, there may be instances where a more customized or fine-grained approach is needed. Currently, the most effective way to implement fine-grained authorization in ZITADEL is by using custom application logic for smaller projects, or for larger scale projects, leveraging an available third-party tool such as warrant.dev, cerbos.dev, etc. These tools can integrate with ZITADEL, further enhancing your capacity for nuanced, fine-grained authorization.

A Practical Example

Let’s say there’s a hypothetical Newsroom Application in a media company, which talks to a back-end API. Journalists use it to write, while editors edit and publish these articles. This API, written in Python Flask in this example, has specific endpoints and access to these endpoints depends on the user’s role and how experienced they are.

The endpoints:

- write_article: Only for journalists to write.

- edit_article: Just for editors to edit articles.

- review_articles: For senior journalists, and intermediate and senior editors to review articles.

- publish_article: For intermediate and senior journalists, and senior editors to publish.

Internally, the API uses a JWT issued by ZITADEL for checking who’s making requests. Users need to send a valid JWT in their request’s header. This JWT was obtained when the user logged in. The JWT contains info about the user, like their role and experience. This info, contained within custom claims, is key to this use case. The backend decides if the user can access the requested resource based on this information.

The Application Logic

Diagram 1: Interactions of fine-grained authorization

User Onboarding: During the user onboarding process, each user gets a role, e.g. journalist or editor. This is key since it sets who gets what access in our setup.

Managing Experience/Seniority: Besides roles, a user’s experience (like junior, intermediate, and senior in our example) is tracked. If a user’s experience changes, ZITADEL updates it as metadata. If there’s no experience level mentioned when a user onboards ZITADEL, the system just assumes it’s junior.

User Login: A user must first login to access the API. Upon successful login, ZITADEL returns a token with the user’s information.

Token Validation: When a request from a user hits the API, the API validates the token by calling ZITADEL’s token introspection endpoint. Although JWTs can be validated locally using JWKS, we went with ZITADEL’s method to inspect tokens for better security and instant token checks. This way, we can revoke tokens instantly, manage them from one place, and have fewer security issues. It keeps our API’s login and access controls strong and up-to-date with the server.

Fine-Grained Access Control: The application is responsible for authorizing access to resources based on a user’s role and experience level. It uses a predefined access control list that maps each resource endpoint to the user roles and experience levels authorized to access them. This list serves as the rulebook for granting or denying access to resources.

Separation of Concerns: In the design of this API, special attention was given to ensuring that business logic and access control rules are cleanly separated. This is crucial for the maintainability and scalability of the application. By keeping business logic and access rules separate, we get a cleaner, modular design. This lets us update business actions and access rules without affecting each other. This increases the maintainability of the code and makes it easier to manage as the application scales. Additionally, this design makes the system more secure as access rules are abstracted away from the main business logic, reducing the risk of accidentally introducing security vulnerabilities when modifying the business logic.

Try out the Code: Configure ZITADEL and Create the API

You can find all source files and instructions here.

Integrate with an External Authorization Service

ZITADEL allows integration with external authorization services such as warrant.dev, cerbos.dev, or essentially any service that can consume ZITADEL’s users and roles. By using an external authorization service, you have the flexibility to create a fine-tuned authorization strategy that precisely meets your organization’s needs. This could involve creating complex policies that dictate access based on a variety of user attributes and conditions, extending far beyond the traditional roles used in RBAC.

Instead of enforcing a one-size-fits-all solution, ZITADEL believes in giving users the tools and options to construct an access control framework that perfectly suits their organization’s unique needs and challenges. This emphasis on flexibility ensures that as those needs evolve, the access control strategy can adapt seamlessly.

Try ZITADEL for FREE.

--

--