DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Establish Trust Chain From Kafka to Microservices REST APIs With JWT
  • REST API Error Handling With Spring Boot
  • Best Practices To Secure Stateless REST Applications
  • Secure Spring Boot 3 Application With Keycloak

Trending

  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 1
  • Mastering Advanced Traffic Management in Multi-Cloud Kubernetes: Scaling With Multiple Istio Ingress Gateways
  • Designing AI Multi-Agent Systems in Java
  • Power BI Embedded Analytics — Part 3: Power BI Embedded Demo
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Simple, Secure Role Based Access Control (RBAC) For REST APIs

Simple, Secure Role Based Access Control (RBAC) For REST APIs

There are a lot of ways to implement Access Controls, and some are slightly complicated. Have you considered using REST?

By 
Sharone Zitzman user avatar
Sharone Zitzman
·
Apr. 30, 16 · Tutorial
Likes (10)
Comment
Save
Tweet
Share
73.4K Views

Join the DZone community and get the full member experience.

Join For Free

Role Based Access Control (RBAC) is a common approach to managing users’ access to resources or operations. Permissions specify exactly which resources and actions can be accessed. The basic principle is this: instead of separately managing the permissions of each user, permissions are given to roles, which are then assigned to users, or better - groups of users.

Roles Bundle Permissions

Managing permissions per user can be a tedious task when many users are involved. As users are added to the system, maintaining user permissions becomes harder and more prone to errors. Incorrect assignment of permissions can block users’ access to required systems, or worse - allow unauthorized users to access restricted areas or perform risky operations.

In this post, I’ll introduce my take on how to elegantly control access to RESTful applications. There are many different access control models, such as Role Based Access Control (RBAC) and Discretionary access control (DAC). While the principles explained in the document can apply to various models, I’ve chosen RBAC as a reference as it is widely accepted and very intuitive.

A Bit About Roles

Role Based Access Control is a common approach to managing users’ access to resources or operations. Permissions specify exactly which resources and actions can be accessed. The basic principle is this: instead of separately managing the permissions of each user, permissions are given to roles, which are then assigned to users, or better - groups of users.

Roles Bundle Permissions

Managing permissions per user can be a tedious task when many users are involved. As users are added to the system, maintaining user permissions becomes harder and more prone to errors. Incorrect assignment of permissions can block users’ access to required systems, or worse - allow unauthorized users to access restricted areas or perform risky operations.

Reviewing users’ activities usually only yields a limited number of actions that users perform (e.g. read data, submit forms). A closer look into these user actions can reveal that some actions tend to go together, meaning that users who perform action A usually also perform action B. For example, reading and updating reports, or removing and adding accounts. These can then be bundled into “roles”, such as “Editor” or “Account Administrator”. Note that roles are not necessarily related to job titles or organizational structure, but rather reflect related user actions in a meaningful way. Once roles are properly identified and assigned to each user, permissions can then be assigned to roles, instead of users. Managing the permissions of a small number of roles is a much easier task.

As always, an illustration goes a long way:

Here is a set of users and their assigned permissions, linked directly without roles:

And here, the exact same set of users and permissions, organized with roles:

So, you can clearly see how roles make permissions management a lot easier!

Groups Bundle Users

An even better practice is assigning roles to groups of users, instead of individual users.

When reviewing patterns of users’ actions with respect to the roles above, we often find there are a great many commonalities between users, i.e. groups of users tend to “behave” alike - perform the same operations on common resources. This allows us to organize users into groups, and then assign roles to only a few groups, instead of many users. Following the previous examples, it is a likely scenario to find several users that require the “Account Administrator” role, so we can create a group named “Account Admins”, add the users to this group and assign that role to the group, instead of each individual user.

Implementing Roles - Do’s and Dont’s

Never Couple Actions and Authorization Details

In many systems, developers restrict access to a particular operation by specifying permissions directly on the implementing method. Yes, in the code! Typically, a role check is added to the secured method, often by annotating it. Here is an example from a Spring Security based code:

@PreAuthorize("hasRole('Editor')")public void update_order(Order order);

This is a very common practice used in different languages and frameworks. While very easy to implement, it unfortunately creates an undesired coupling between the required role and the actual implementation of the action. Imagine dozens of methods annotated with hard-coded role names. Tracking the effective permissions of each role becomes so difficult that you can almost certainly count on having inaccurate or outdated documentation, or, even worse - unknown, unmanaged permissions scattered in your application.

From the customer’s standpoint, this sort of coupling makes it impossible to modify the set of roles defined beforehand by the developer, or their permissions, because changing it means the code would have to be compiled and packaged each time (!) - probably not the user experience we should aim for. 

How to Avoid Coupling?

A better approach would be to first extract the list of possible actions from the code to be handled by an external authorization mechanism (explained below). Then, we can make the code unaware of roles or any other authorization detail, and simply ask if the current user (however it is retrieved) has the required permission (wherever it is defined) to execute the specific method.

This would allow us to use a generic annotation, like this one:

@Securedpublic void update_order(Order order);

Mapping roles and permissions (i.e. the permission to perform a specific action) can now be done in a configuration file, easily customized by customers!

For example, consider this roles_config.yaml file:

order_manager:
  - 'create_order'
  - 'view_order'
  - 'delete_order'
  - 'update_order'
order_inspector: 
  - 'viewer_order'

The @secured wrapper can now evaluate if the current user is allowed to execute ‘update_order’ based on the given configuration file. In this case, it would mean the current user must be assigned the “order_manager” role, which is now both clear and easily configurable. Still, the authorization mechanism must somehow know how to match each permission to a specific method in the code , and someone must do some work and document all available methods (i.e. create_order, view_order etc.). This is resolved (almost) magically below.

Separate Concerns - Authorize Externally

Now that the method implementation code does not include authorization details, the entire authorization logic can be moved to a separate, independent module. By using a generic title (e.g. the annotation “secured”) we allow the entire authorization mechanism to be modified without affecting the application’s code. For example, it would be possible to implement “secured” as a role check, but it would also be possible to use Access Control Lists (ACLs). For example, evaluating if the current user is listed on the order’s ACL list. Another solution could be to use oauth, by asking a third-party (e.g. Facebook) whether the user is allowed to perform that action or not.

REST is the Best

Action Extraction - Out Of The Box

REST is definitely better, or at least the easiest to match this model. RESTful systems (designed properly) already expose resources and methods through a standard HTTP-based API, resources are identified by URIs, and methods are modeled by HTTP verbs (e.g. GET, PUT).

For example, OST http://www.domain.com/bookings will create a new booking, and GET http://www.domain.com/orders/12345 will return details on order #12345. That means the extraction of actions discussed above is ready right out of the box!

Request Gateway

Apart from neatly modeling actions, REST services are typically a good place in the request flow to evaluate authentication and authorization, as this is often the main entry point to a system. For an access control mechanism to make sense, it is recommended to block all other routes to the system, such as direct access to data stores or any remote call mechanism in the code. Another great advantage of this architecture would be response filtering, in case some of the data should not be returned to the user.

Requests Are Also Access Control Tools

REST services process incoming requests, meaning the information found on the requests can be used to make access control decisions. Some useful details are:

  • Request origin - Allows blocking requests that are sent from unknown IP addresses or subnets.
  • Headers - Many interesting details can be passed in headers, such as user credentials, which open the door for a full-blown authentication/authorization process to take place.
  • Target endpoint - As indicated by the request’s URI (e.g. ‘secrets’ in ‘http://domain.com/secrets/’). Access can be restricted to just a subset of the application endpoints, depending on other conditions. For example, while the ‘version’ endpoint is open to all, the ‘secrets’ endpoint is only open to authenticated users.
  • Target method - As represented by the HTTP verb (e.g. DELETE), which means it’s possible to pass or block requests based on the called method.

Putting It All Together - Using REST for Access Control

Remember the simple roles-to-permissions configuration file above? It looked pretty elegant but did entail some work behind the scenes (not shown in this document), such as getting a list of all the methods a user might call and matching each permission to a specific method with that name. Not fun.

This is now resolved!

All available resources are exposed via REST URIs, which, together with HTTP verbs, can cover all the actions that can be performed and need to be secured. In the example below, 3 roles are configured:

  • order_manager - can view, create, update and delete orders
  • order_editor - can view, create and update orders, but not delete them
  • order_inspector - can only view orders


order_manager:
  '/orders':
    - 'GET'
    - 'POST'
    - 'PUT'
    - 'DELETE'
order_editor:
  '/orders':
    - 'GET'
    - 'POST'
    - 'PUT'
order_inspector:
  '/orders':
    - 'GET'

So now we know RESTful systems are a natural fit for access control. By processing incoming requests the REST service is able to retrieve valuable information that can be handed over to a separate module to perform authentication and authorization. If the user is authorized to perform the requested method on the target resource, request processing can continue. Otherwise, this is a proper place to deny further access before reaching any internal application code.

In my next post, I’ll explain how we implement this RBAC model in Cloudify, so check back soon.

REST Web Protocols Role-based access control Spring Security

Published at DZone with permission of Sharone Zitzman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Establish Trust Chain From Kafka to Microservices REST APIs With JWT
  • REST API Error Handling With Spring Boot
  • Best Practices To Secure Stateless REST Applications
  • Secure Spring Boot 3 Application With Keycloak

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!