Modal Title
API Management / Security

Building Access Permissions into Your API

If an authorization mechanism is implemented as a global shared provider, it will help remove duplication, freeing developers to focus on business logic.
Dec 7th, 2022 8:10am by
Featued image for: Building Access Permissions into Your API
Feature image via Pixabay

Microservices-oriented architecture has evolved from a buzzword to standard architecture practice for building large-scale applications. Applications are designed as blocks of independently deployable services and communicate with each other via lightweight mechanisms.

Microservices offer a lot of advantages, including flexible language selection, functionality-based scalability, independent deployment, and independent product development teams. They can, however, bring challenges as well. One of those challenges is authentication and authorization of resources.

In a monolithic application, a single user session can be used to authenticate and authorize the user. With independent microservices, the user context is not shared among them. That means that authentication and authorization need to be handled in each microservice, causing duplication of the auth logic. The duplicated code can distract developers and can be difficult to maintain and monitor.

If an authorization mechanism is implemented as a global shared provider, it will help remove duplication, freeing the development team to focus on the business logic.

In this tutorial, you will be building REST API endpoints in Python and adding resource access permissions to these endpoints using Cerbos.

Building a RESTful API

You will be building RESTful APIs on Python with permission management. To get started with this tutorial, make sure you have the following prerequisites:

In this tutorial, you will be creating REST APIs for the TODO service. The APIs will be built using Flask web framework.

Initialize the API by importing the Flask module into your application:


The API you’re building will have Create, Update, Read, and Delete REST API endpoints.

Now add the API endpoints for the TODO resource:


Here you’ve added a TODO class that will contain all the necessary methods to handle the request to the provided routes. The line api.add_resource(TODO, '/todo') is to define the routes from which the API will be accessed.

Once you have the resource, add the methods to handle the GET, POST, PUT, EDIT requests:


Before running the Python file, make sure to install the Flask and flask_restful dependencies:


Now you can start the Flask server by running the main.py file:


This will start the Flask app in the default port 5000. To check the GET /todo API, use the curl command:


Now that you have the server up and running, add the remaining endpoints create, update, delete including authentication.

Authentication


The API key for the users is managed in a dict. Create a new file resources.py with the API tokens. This file is imported by the main file to check if the token is valid.


Here you can see that an authentication mechanism is added to check if the API key provided by the user is valid. If the token is invalid, the user will receive the message “API key invalid.”

The next step is to add an authorization mechanism in the API. You will need to set up the following authorization policies.

Authorization

GET

  • User with admin role can get their TODO or any other user’s TODO.
  • User with user role can get only their TODO and cannot get other users’ TODO.

CREATE

  • User with user or admin role can create a TODO for self.

UPDATE

  • User with admin role can update their TODO or any other user’s TODO.
  • User with user role can update only their TODO and cannot update other users’ TODO.

DELETE

  • User with admin role can delete any TODO.
  • User with user role cannot delete any TODO.

I will be using Cerbos for authorization of the user requests. Cerbos helps you to authorize by defining context-aware access control policies for your application resources.

There are three steps to add managing your permissions using Cerbos:

  1. Deploy and run Cerbos
  2. Define your policies
  3. Check permissions

Run Cerbos

Create a policies directory where all the policies will be stored:


Start the Cerbos server using the container image.


This will start the Cerbos server in port 3592. Navigate to the port (http://localhost:3592/), where you can see documentation about the Cerbos API. You can also try out the API from the web page.

Define Your Policies

The policies will be defined in a user-friendly YAML format. Not only developers, but any non-technical person can go through the YAML file and understand the defined policies, which are found in a central place and are easy to manage.

Create a file derived_roles.yml inside the cerbos-bin/policies directory:


There are three derived roles created to which the policies will be attached. Create a file resource_policy.yml to store the resource policies:

Check Permissions

The final step is to check the permissions in the API endpoint to validate if the user is authorized to access the TODO resource.

Create a generic Python file that will handle the permission check. To check the permission, make an API call to the Cerbos server with data about the user, their attributes, and the role of the user in a JSON format. Modify the get method to include the permissions check using Cerbos:


> Note: The generic implementation for Cerbos check and calls can be found in the GitHub repo.

In the resource.py file, add the Users resource and the TodoItems resource.


These resources would ideally be in a database, but for simplicity, I am adding them to a file.

Now try to access the TODO resource with the token of a user. I am using Postman to make the requests.

When User 2 Tries to Access Resource 4

Resource 4 belongs to user 2, so the user should be able to access the resource:

Note: Clicking images opens a new link to a larger size.

When User 2 Tries to Access Resource 5

Resource 5 belongs to user 1 but is a public resource. In the policy file, I have defined the policy to “view” public resources to everyone, so users will be able to access it:

When User 2 Tries to Access Resource 3

Resource 3 belongs to user 1 and is not a public resource, so the user will not be able to access it:

Similarly, you can add the check to all the remaining endpoints and validate the authorization of the resources. The complete code can be found in the GitHub repo. You can play around by changing the policies and see how it changes the resource access permission.

Conclusion

While designing your API, permission management is a key functionality to keep in mind for the security of the resources. If any permission checks are missing, you will be compromising the data of your platform. It’s important to have a proper permission check for each resource, but you also don’t want to spend a lot of time thinking about permissions while developing each API. The permission check should be easy to implement and easy to test.

Using an external provider like Cerbos helps to centralize permission management in an easy-to-understand format. This solves the access permissions problem for developers and non-technical users alike.

Group Created with Sketch.
TNS owner Insight Partners is an investor in: Pragma, Docker, Postman.
THE NEW STACK UPDATE A newsletter digest of the week’s most important stories & analyses.