ProvenPin Install

FastAPI + PyJWT bearer auth: working versions (tested 2026-10-15)

OAuth2 password flow in FastAPI issuing PyJWT tokens, with a current-user dependency guarding routes.

passed2 passed · 0 failed2026-10-15 11:35 UTC
Status
passed
Last passed
2026-10-15 11:35 UTC
Tests
2 / 2
Language
Python
Runtime
Python 3.13.16
pinned versions5
fastapi@0.143.1pyjwt@2.15.1httpx@0.28.1python-multipart@0.0.32pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38728226240

The code

Exactly the files that passed. Your agent can pull them with get_recipe("fastapi-jwt-auth") (install), or see them on GitHub.

requirements.txt
fastapi==0.143.1
pyjwt==2.15.1
httpx==0.28.1
python-multipart==0.0.32
pytest==9.1.1
app/__init__.py
app/main.py
import os
from datetime import datetime, timedelta, timezone
import jwt
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm

SECRET = os.environ.get("JWT_SECRET", "dev-only-secret-change-me-32-bytes!!")
ALGO = "HS256"
oauth2 = OAuth2PasswordBearer(tokenUrl="token")
app = FastAPI()

def make_token(sub: str, minutes: int = 15) -> str:
    exp = datetime.now(timezone.utc) + timedelta(minutes=minutes)
    return jwt.encode({"sub": sub, "exp": exp}, SECRET, algorithm=ALGO)

def current_user(token: str = Depends(oauth2)) -> str:
    try:
        return jwt.decode(token, SECRET, algorithms=[ALGO])["sub"]
    except jwt.PyJWTError:
        raise HTTPException(status.HTTP_401_UNAUTHORIZED, "invalid token", headers={"WWW-Authenticate": "Bearer"})

@app.post("/token")
def login(form: OAuth2PasswordRequestForm = Depends()):
    if form.password != "correct-horse":
        raise HTTPException(400, "bad credentials")
    return {"access_token": make_token(form.username), "token_type": "bearer"}

@app.get("/me")
def me(user: str = Depends(current_user)):
    return {"user": user}
tests/test_auth.py
from fastapi.testclient import TestClient
from app.main import app, make_token

client = TestClient(app)

def test_login_and_me():
    tok = client.post("/token", data={"username": "ada", "password": "correct-horse"}).json()["access_token"]
    assert client.get("/me", headers={"Authorization": f"Bearer {tok}"}).json() == {"user": "ada"}

def test_rejects_bad_and_expired():
    assert client.get("/me").status_code == 401
    expired = make_token("ada", minutes=-1)
    assert client.get("/me", headers={"Authorization": f"Bearer {expired}"}).status_code == 401
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.