Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 23, 2022 01:47 am GMT

Authorization on FastAPI with Casbin

Nowadays, tons of APIs (both external and internal) are created and used every day. With methods like authentication/firewall restriction, we can identify who can invoke the methods, or restrict from where is trying to access. But, can we identify and authorize given users to invoke some methods rather than others? In the following tutorial we will cover how to authorize different users to execute certain REST API methods in an easy and straightforward way.

Situation

In this case, we have an Items REST API implemented on Python 3.10 with FastAPI framework. It allows to list all items and get, create and delete an item. All of these operations must be performed by authenticated users. For sake of simplicity, the following users can be used for authentication:

UserPasswordRole
alicesecret2Admin
johndoesecretUser

The application consists of the files: main.py, utils.py and requirements.txt, with the following code.
main.py

utils.py

requirements.txt

You can create a conda environment, install required packages and run the api with:

conda create -n itemsapi pipconda activate itemsapipip install -r requirements.txtpython3 -m uvicorn main:app --reload 

After the API is up and running, let's follow these steps to test it:

  1. Open http://127.0.0.0:8000/docs url in browser.
  2. Click on "Authorize" and login with username and password (as per Users table shown before).
  3. To get all items list, select on /items GET API method. Then, click on "Try out" button and on "Execute" button.
  4. To delete the item with id = 1, select on /item DELETE API method, click on "Try out" and execute the method with item_id = 1. The response is 204 and item is deleted successfully.

Image description

Goal

Although only registered users (johndoe and alice in this case) can perform items actions, all of them are able to delete items. As per their roles, alice should be able to delete items, but johndoe shouldn't. To achieve this we will implement authorization at REST API method level, in an easy and extensible way with Casbin.

Implementation

Overview

Casbin is an open source authorization library with support for many models (like Access Control Lists or ACLs, Role Based Access Control or RBAC, Restful, etc) and with implementations on several programming languages (ie: Python, Go, Java, Rust, Ruby, etc).
It consists of two configuration files:

  • A model file: a CONF file (with .conf extension) which specifies the authorization model to be applied (in this case we will use Restful one)
  • A policy file: a CSV file that list API methods permissions for each user.

Steps

1) Install casbin python package with pip
pip install casbin
2) Define Conf policy
Create new file called model.conf with the following content:

You can find more details about Casbin model syntax on the documentation

3) Define Policy file

Create a new CSV file called policy.csv and paste the following:

Each row is an allowed permissions with the following values: the second column is the user, the third is the API resource or url, and the last one is a set of allowed methods. In this case, alice will have access to list create and delete items, while johndoe may list and create items but not delete them.

4) Update Python API code to enforce authorization.
In the main.py file, with following lines:

import casbin...async def get_current_user_authorization(req: Request, curr_user: User = Depends(get_current_active_user)):    e = casbin.Enforcer("model.conf", "policy.csv")    sub = curr_user.username    obj = req.url.path    act = req.method    if not(e.enforce(sub, obj, act)):        raise HTTPException(            status_code=status.HTTP_401_UNAUTHORIZED,            detail="Method not authorized for this user")    return curr_user

It imports the casbin module and create a new authorization function that read the configuration files with casbin.Enforcer and enforce the user has the required permission.

Then, on the defined API methods, change the old method get_current_active_user with the new get_current_user_authorization

@app.get("/items/{item_id}")async def read_item(item_id: int, req: Request, curr_user: User = Depends(get_current_user_authorization)):    return items_dao.get_item(item_id)@app.post("/items/")async def create_item(item: Item, req: Request, curr_user: User = Depends(get_current_user_authorization)):    answer = items_dao.create_item(item)    if not(answer):        raise HTTPException(            status_code=status.HTTP_400_BAD_REQUEST,            detail="Item with given id already exists")    else:        return [email protected]("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)async def delete_item(item_id: int, req: Request, curr_user: User = Depends(get_current_user_authorization)):    items_dao.delete_item(item_id)    return Response(status_code=status.HTTP_204_NO_CONTENT)

Test

  1. Start the updated API
  2. Open http://127.0.0.0:8000/docs url in browser.
  3. Click on "Authorize" and login with "johndoe".
  4. Try to delete item with id=1. It will be rejected with a 401 Unauthorized error.
  5. Logout from that user. Then login with "alice".
  6. Try to delete item with id=1. The request works fine, returns 204 and item is deleted.

Image description

Conclusion

On this post we saw how to use Casbin to implement authorization on REST APIs. Keep in consideration that this example can be extended combining with other authorization models like RBAC, and only changing the model and policy configuration files.


Original Link: https://dev.to/teresafds/authorization-on-fastapi-with-casbin-41og

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To