Github

The FastApi starter kit leverages the oneloop-python SDK under the hood, but provides a helpful middleware that can be used for verifying API keys.

You can fork the starter kit repo, or copy the middleware from it.

If you haven’t already, create an account with Oneloop. Here is the link to our QuickStart Guide to help you get started.

Installation

pip install typing fastapi oneloop-python

To learn more about the this SDK, you can visit the Python SDK documentation.

Usage

Middleware

Let’s first add the middleware that will be used to verify the API key. This will save you from having to write the same code in every route.

middleware.py
import json
from typing import List, TypedDict, Optional
from fastapi import Request, HTTPException
from oneloop_client.client import OneloopApi
from oneloop_client.types import VerifyApiKeyResponse, ErrorResponse

class ScopeObject(TypedDict):
    id: str
    create: Optional[bool]
    read: Optional[bool]
    update: Optional[bool]
    delete: Optional[bool]

oneloop = OneloopApi(token="your-oneloop-api-key")

def oneloop_middleware(scopes: List[ScopeObject] = []):
    async def middleware(request: Request):
        # Extract the authorization header
        auth_header = request.headers.get("authorization")
        if not auth_header:
            raise HTTPException(status_code=401, detail="Customer API key is missing")

        # Create the verify request
        verify_request = oneloop.verify_api_key(
            key=auth_header.replace("Bearer ", ""),
            requested_scopes=[
                {
                    "id": scope["id"],
                    "representation": scope["id"],
                    "read": scope.get("read", False),
                    "create": scope.get("create", False),
                    "update": scope.get("update", False),
                    "delete": scope.get("delete", False),
                }
                for scope in scopes
            ]
        )

        try:
            # Verify the API key
            verify_response: VerifyApiKeyResponse = oneloop.verify_api_key(verify_request)

            if verify_response.status != "VALID":
              raise HTTPException(status_code=401, detail=verify_response.status)

        except Exception as e:
            error = json.loads(e.body)
            code = error['error']['code']
            message = error['error']['message']
            raise HTTPException(status_code=code, detail=message)



    return middleware

Authenticate the API key

Now, let’s use the middleware in a FastApi route and authenticate the API key.

routes.py
# Define your routes
@app.get("/", dependencies=[Depends(oneloop_middleware())])
async def read_root():
    return {"Hello": "World"}

Checking for permissions

You can also check for permissions in your routes. Let’s say you have a route that requires a specific read access for profile data. You want to check if the API key has the required scope before returning the data. You can pass that scope to the middleware.

Let’s modify the above route to check for profile read access.

routes.py
# Define your routes and check for permissions
@app.get("/", dependencies=[Depends(oneloop_middleware([{"id": "profile", "read": True}]))])
async def read_root():
    return {"Hello": "World"}