Skip to main content

Fastapi OPA middleware incl. auth flow.

Project description

Open Policy Agent Middleware for FastAPI

fastapi-opa is an extension to FastAPI that allows you to add a login flow to your application within minutes using open policy agent and your favourite identity provider.

─▄████▄▄░
▄▀█▀▐└─┐░░         FastAPI App
█▄▐▌▄█▄┘██  ---->  @app.get("/")
└▄▄▄▄▄┘███         async def root():  
██▒█▒███▀              return {}
   User                   |                   Identity Provider
    |       ------------------------------>    (e.g. Keycloak)
    |       <------------------------------           |
    |       ---->         |                           |
    |                     |           ---->           |
    |                     |           <----           |
    |                     |           ---------------------------------->  Open Policy Agent
    |                     |           <---------------------------------- 
    |       <-----        |

When a user tries to get a response from an endpoint he/she will be redirected to the identity provider for authorization. After the authentication the app validates the token provided. Once it was validated the user information is used to get an OPA decision whether the user is allowed to get any information from the endpoint.

Installation

poetry add fastapi-opa

How to get started

Checkout the wiki for a complete environment setup with Keycloak and Open Policy Agent:
Getting Started with FastAPI app with Authentication and Authorization

The package provides a very easy way to integrate authentication and authorization. We can decide what authentication flow we inject into the OPAMiddleware to be able choosing between different flows.

from typing import Dict

from fastapi import FastAPI

from fastapi_opa import OPAConfig
from fastapi_opa import OPAMiddleware
from fastapi_opa.auth import OIDCAuthentication
from fastapi_opa.auth import OIDCConfig

# The hostname of your Open Policy Agent instance
opa_host = "http://localhost:8181"
# In this example we use OIDC authentication flow (using Keycloak)
oidc_config = OIDCConfig(
    well_known_endpoint="http://localhost:8000/auth/realms/example-realm/.well-known/openid-configuration",  # well known endpoint
    app_uri="http://localhost:4000",  # host where this app is running
    client_id="example-client",  # client id of your app configured in the identity provider
    client_secret="bbb4857c-21ba-44a3-8843-1364984a36906",  # the client secret retrieved from your identity provider
)
oidc_auth = OIDCAuthentication(oidc_config)
opa_config = OPAConfig(authentication=oidc_auth, opa_host=opa_host)

app = FastAPI()
# Add OPAMiddleware to the fastapi app
app.add_middleware(OPAMiddleware, config=opa_config)


@app.get("/")
async def root() -> Dict:
    return {
        "msg": "success",
    }

Open Policy Agent

The (validated/authenticated) user token is sent to the Open Policy Agent with the additional attributes request_method and request_path.

{
    "input": {
        "exp": 1617466243,
        "iat": 1617465943,
        "auth_time": 1617465663,
        "jti": "9aacb638-70c6-4f0a-b0c8-dbc67f92e3d1",
        "iss": "http://localhost:8080/auth/realms/example-realm",
        "aud": "example-client",
        "sub": "ccf78dc0-e1d6-4606-99d4-9009e74e3ab4",
        "typ": "ID",
        "azp": "david",
        "session_state": "41640fe7-39d2-44bc-818c-a3360b36fb87",
        "at_hash": "2IGw-B9f5910Sll1tnfQRg",
        "acr": "0",
        "email_verified": false,
        "hr": "true",
        "preferred_username": "david",
        "user": "david",
        "subordinates": [],
        "request_method": "GET",
        "request_path": ["finance", "salary", "david"]
    }
}

In open policy agent you can now easily create policies using user roles, routes, or request methods etc.

An example policy (from the official OPA docs) for this setup could be like:

package httpapi.authz

# bob is alice's manager, and betty is charlie's.
subordinates = {"alice": [], "charlie": [], "bob": ["alice"], "betty": ["charlie"]}

# HTTP API request
import input

default allow = false

# Allow users to get their own salaries.
allow {
  some username
  input.request_method == "GET"
  input.request_path = ["finance", "salary", username]
  input.user == username
}

# Allow managers to get their subordinates' salaries.
allow {
  some username
  input.request_method == "GET"
  input.request_path = ["finance", "salary", username]
  subordinates[input.user][_] == username
}

Authentication Flow

These flows are implemented:

  • OpenID Connect

If your favourite flow is not provided yet, there is an interface provided to easily implement it and inject it into OPAMiddleware (fastapi_opa.auth.auth_interface.AuthInterface), or you can open a pull request if you would like to contribute to the package.

Roadmap

  • Add other authentication flows
  • Allow more flexible way of opa jwt enrichment
  • Implement GraphQL query parser as a jwt enrichment strategy

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi-opa-1.0.1.tar.gz (21.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_opa-1.0.1-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

Details for the file fastapi-opa-1.0.1.tar.gz.

File metadata

  • Download URL: fastapi-opa-1.0.1.tar.gz
  • Upload date:
  • Size: 21.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.3 CPython/3.9.2 Linux/5.10.26-1-MANJARO

File hashes

Hashes for fastapi-opa-1.0.1.tar.gz
Algorithm Hash digest
SHA256 99b1b43e21e2b26a598eac50bd39e8e7747bb6626026b0c2a091f24217c427d2
MD5 c086d2716ff67bba2777e74b65a05a64
BLAKE2b-256 8352abfca5d0d3c07478a08dfe834ad55762f2e11e2cb21ed20b6a222159c05e

See more details on using hashes here.

File details

Details for the file fastapi_opa-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: fastapi_opa-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 21.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.3 CPython/3.9.2 Linux/5.10.26-1-MANJARO

File hashes

Hashes for fastapi_opa-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5f1498885fc23bb7f00287629402361327997a11cf995c2e20353d2d9c136f32
MD5 15c04dfa5e8b90c7d61b510fadb801f2
BLAKE2b-256 64800c4de1644c0baf77be3d65a4dd4c98cc19ccddb16cda2c6c7bbb245e913c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page