FastAPI
Learn how to leverage the Permit API and SDK to seamlessly integrate robust access control into your FastAPI application. This step-by-step guide walks you through setting up your environment, creating policies with the Permit CLI with minimal code and maximum flexibility.
In this guide, we will quickly go through the steps to integrate Permit.io with FastAPI. We will use Permit's CLI to create a new environment and a policy with a template. Then, we will use the Permit SDK to integrate it with our FastAPI application. We will also set up the PDP (Policy Decision Point) server locally using Docker.
Prerequisites
- FastAPI application
- Docker (for running the PDP server)
- Node.js (for installing and running the Permit CLI)
- Permit.io account (Follow this guide to create an account)
Installing the Permit CLI
We will first install the Permit CLI. Permit CLI is a command-line tool that allows you to create policies, run the PDP server, and perform other tasks. To install the CLI, execute the command below in your terminal.
npm install -g @permitio/cli
Once the installation is complete, execute permit
to confirm the installation.
Authenticating the CLI
To use the CLI, we need to authenticate it with our Permit account. To authenticate, execute
permit login
This will open a browser window and ask you to log in with your Permit account. After logging in, the CLI will be authenticated and ready to use. This will also log you into the default environment (a project can have multiple environments). We can change the environment by executing permit env select
and then selecting the environment we want to use.
Creating a policy with a template
Now, let's create a policy with a template. The benefit of using a template is that we can create a policy with predefined roles and resources using best practices. This will save us time and effort in creating a policy from scratch. To check the available templates, execute permit template list
. Based on our needs, we can apply the template to a new policy by executing permit template apply --template <template-name>
.
We will be using the blog-rbac template to create a new policy. This template is great for a blog application. It has a Viewer role that can view the blog posts and a Editor role that can edit the blog posts. It also has a Post resource that represents a blog post.....
To apply the template, execute the command below.
permit template apply --template blog-rbac
This will create a new policy with the blog-rbac template
Accessing the policy
Now, let's visit the Permit dashboard to check the created policy and also get the API key that we will use to authenticate our application when using the Permit SDK.
As we can see in the image below, the CLI has created Resources, Roles, and Policies. Now, let's add Read permission to the Viewer for the Visit resource. It is very easy to add permissions using the dashboard. We can also add more roles and resources as per our needs.
To get the API key, click on Projects from the left sidebar, then click on the three dots on the environment we want to use, and click on Copy API Key and store it in a safe place. We will be using this API key to authenticate our application with Permit.io. If you are having any difficulty getting the API key, follow this guide.
Once we are done, let's move toward the implementation part and integrate Permit.io with our Express.js application.
FastAPI Integration
Once you have a FastAPI application is ready (or you can create a new one for the sake of this guide), we will install the Permit's Python SDK. The Permit SDK is a Python library that allows us to interact with the Permit API. To install the Permit SDK, execute the below command in your terminal.
pip install permit
Read more about the Python SDK here.
Now, below is the application code we created. In this we will be syncing users and creating tenants. The code is explained in detail below.
# main.py
from fastapi import FastAPI, status
from permit import Permit
from pydantic import BaseModel, EmailStr
import os
app = FastAPI()
class UserIn(BaseModel):
email: EmailStr
first_name: str
last_name: str
class TenantIn(BaseModel):
key: str
name: str
description: str = None # Optional field
# Initialize Permit SDK
permit = Permit(
token=os.getenv("PERMIT_API_KEY"),
pdp=os.getenv("PDP_URL", ""), # Update if your PDP URL differs
)
# Sync user with Permit.io
@app.post("/sync-user", status_code=status.HTTP_201_CREATED)
async def sync_user(user_in: UserIn):
user = await permit.api.users.sync(
{
"key": user_in.email,
"email": user_in.email,
"first_name": user_in.first_name,
"last_name": user_in.last_name,
}
)
return user
# Create tenant with Permit.io
@app.post("/create-tenant", status_code=status.HTTP_201_CREATED)
async def create_tenant(tenant_in: TenantIn):
tenant = await permit.api.tenants.create(
{
"key": tenant_in.key,
"name": tenant_in.name,
"description": tenant_in.description,
}
)
return tenant
At the top, we have imported the necessary dependencies and created a FastAPI application. After that, we have defined the UserIn
and TenantIn
models to validate the request body using Pydantic
. Then we have initialized the Permit SDK. It needs two environment variables PERMIT_API_KEY
and PDP_URL
. The PERMIT_API_KEY
is the API key we copied from the Permit dashboard, and the PDP_URL
is the URL of the PDP server. We will set this up later.
The Permit
class is used to interact with the Permit API. We can use this class to sync users, create tenants, check permissions, and perform other tasks.
# Sync user with Permit.io
@app.post("/sync-user", status_code=status.HTTP_201_CREATED)
async def sync_user(user_in: UserIn):
user = await permit.api.users.sync(
{
"key": user_in.email,
"email": user_in.email,
"first_name": user_in.first_name,
"last_name": user_in.last_name,
}
)
return user
# Create tenant with Permit.io
@app.post("/create-tenant", status_code=status.HTTP_201_CREATED)
async def create_tenant(tenant_in: TenantIn):
tenant = await permit.api.tenants.create(
{
"key": tenant_in.key,
"name": tenant_in.name,
"description": tenant_in.description,
}
)
return tenant
In this part of the code, we have defined two endpoints: sync-user
and create-tenant
. The sync-user
endpoint is used to sync a user with Permit.io. It expects a unique key, email, first name, and last name. The create-tenant
endpoint is used to create a tenant with Permit.io. It expects a unique key, name, and description. We are using email as the unique key for the user.
The sync-user
endpoint uses the sync
method of the Permit
class to sync the user with Permit.io. The create-tenant
endpoint uses the create
method of the Permit
class to create a tenant with Permit.io. Both methods return the created user and tenant respectively.
Syncing the user
Once we are done with the code, let's run the FastAPI application and test the sync-user
using curl
.
As we can see in the above image, the user is created successfully and we get a lot of information about the user in the response like, id
, project_id
, key
, etc.
Giving the user access to the resource
Let's now head over to the Permit dashboard and check if the user is created successfully. To do that, select Directory from the left sidebar and we can see the user we just created.
Now, let's give this user access to the resource we created in the policy. To do that, select the user we just created. Then click on the Add Role button and select Tenant and then select the Viewer role and save it. This will give the user access to the Visit resource we created in the policy. We will verify this later when we check the access. Also, we can give the access programmatically, it was a demo to show how easy it is to add access using the dashboard.
We can also add more roles and resources as per our need. Now, let's set up the PDP server and check the access.
Setting up the PDP server
Now, our application is ready by syncing the user and we have a policy created. Let's enforce and check the policy. To enforce the policy we use Permit's PDP (Policy Decision Point) to check if the user has access to the resource. So first let's set up the PDP.
We can leverage the Permit's CLI to start a PDP server locally. Otherwise, we would need to run long Docker commands to start the PDP server. The PDP server is a service that evaluates access requests and returns a decision (permit or deny) based on the policies defined in Permit.io. To start it, execute the below command in your terminal. Make sure Docker is running on your machine as this will start a PDP container locally.
permit pdp run
Once you execute the above command, you will see an output like below with information like container id, name, etc. It will start a PDP server locally on your machine. You can check the logs to see if the PDP server is running successfully. The PDP server will be running on port 7766
by default. You can also change the port.
Once the PDP server is running, update the PDP_URL
environment variable in your application.
Checking the access
To check the access, we will create a new endpoint /check-permission
in our FastAPI application. This endpoint will check if the user has access to the resource. Below is the code for the new endpoint. We need to modify the existing code to add the new endpoint like below.
.
class PermissionCheck(BaseModel):
user: str
action: str
resource: str
.
.
# check permission endpoint
@app.post("/check-permission")
async def check_permission(data: PermissionCheck):
permitted = await permit.check(data.user, data.action, data.resource)
if permitted:
return {"message": "User is permitted"}
else:
return {"message": "User is not permitted"}, status.HTTP_403_FORBIDDEN
In this code, we are using the check
method to check if the user has access to the resource. The check
method takes three parameters: user
, action
, and resource
. The user
is the unique key of the user, action
is the action that the user is trying to perform, and resource
is the resource that the user is trying to access. If the user is permitted, it returns true, otherwise false. We are using the check
method of the Permit
class to check if the user has access to the resource.
Now, everything is ready, let's restart the FastAPI server and test and check the access using curl
. As we have created a user and gave them access to the resource via the dashboard, it should be permitted to access the resource.
As we can see in the image above, the user is permitted to access the resource. To check it works the other way around, let's remove the access from the dashboard and check again.
Now this time we can see that the user is not permitted to access the resource. This is how we can enforce policies using Permit.io with FastAPI.
Conclusion
In this guide, we have seen how to integrate Permit.io with FastAPI. We have created a policy with a template using the Permit CLI. We have also seen how to sync users and create tenants with Permit.io. Finally, we have checked the access using the PDP server. This is how easy it is to integrate Permit.io with FastAPI. You can use the same approach to integrate Permit.io with other frameworks as well.