FastAPI Anchor
Session-based auth for FastAPI with HttpOnly cookies and optional PostgreSQL storage. Logout invalidates the session on the server so it stops working immediately.
Inspired by Lucia. Built on fastapi-sessions by Jordan Isaacs.
Features
| Feature | Description |
|---|---|
| Cookie-based | Session ID in a signed HttpOnly cookie. No token in JS, better XSS story. |
| Backend storage | In-memory (dev) or PostgreSQL (prod). Session lives in your DB. |
| Real logout | Delete the session row; the next request with that cookie gets 401. |
| Pluggable | Same frontend/backend/verifier model as fastapi-sessions. Mix and match. |
Installation
pip install fastapi-anchor
With PostgreSQL support:
pip install fastapi-anchor[postgres]
Quick start (in-memory)
from uuid import UUID, uuid4
from fastapi import Depends, FastAPI, HTTPException, Response
from fastapi_anchor.backends.implementations import InMemoryBackend
from fastapi_anchor.frontends.implementations import SessionCookie, CookieParameters
from fastapi_anchor.session_verifier import SessionVerifier
from pydantic import BaseModel
class SessionData(BaseModel):
user_id: str
cookie_params = CookieParameters(max_age=14*24*3600, httponly=True, secure=False)
cookie = SessionCookie(
cookie_name="session",
identifier="auth",
auto_error=True,
secret_key="your-secret",
cookie_params=cookie_params,
)
backend = InMemoryBackend[UUID, SessionData]()
class AuthVerifier(SessionVerifier[UUID, SessionData]):
def __init__(self):
self._identifier = "auth"
self._backend = backend
self._auto_error = True
self._auth_http_exception = HTTPException(status_code=401, detail="Invalid session")
@property
def identifier(self): return self._identifier
@property
def backend(self): return self._backend
@property
def auto_error(self): return self._auto_error
@property
def auth_http_exception(self): return self._auth_http_exception
def verify_session(self, model: SessionData): return True
verifier = AuthVerifier()
app = FastAPI()
@app.post("/login")
async def login(user_id: str, response: Response):
session_id = uuid4()
await backend.create(session_id, SessionData(user_id=user_id))
cookie.attach_to_response(response, session_id)
return {"ok": True}
@app.get("/me", dependencies=[Depends(cookie)])
async def me(session_data: SessionData = Depends(verifier)):
return session_data
@app.post("/logout")
async def logout(response: Response, session_id: UUID = Depends(cookie)):
await backend.delete(session_id)
cookie.delete_from_response(response)
return {"ok": True}
PostgreSQL backend (real logout in production)
Create the table with anchor_sessions_table, then use PostgresBackend:
from sqlalchemy import MetaData
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from fastapi_anchor.backends.implementations import (
PostgresBackend,
PostgresSessionData,
anchor_sessions_table,
)
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
async_session_factory = async_sessionmaker(
engine, class_=AsyncSession, expire_on_commit=False
)
metadata = MetaData()
sessions_table = anchor_sessions_table(metadata)
# Create tables once: await engine.run_sync(metadata.create_all)
backend = PostgresBackend(async_session_factory, table=sessions_table)
Session payload for Postgres: user_id, expires_at, created_at (use PostgresSessionData or your own Pydantic model with those fields). On logout, call await backend.delete(session_id) and clear the cookie; the session is removed from the DB.
Links
License
MIT. Original fastapi-sessions by Jordan Isaacs (MIT).
Metadata
Release files for fastapi-anchor 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fastapi_anchor-0.1.1.tar.gz | 10.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_anchor-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.2 kB
Release files / fastapi_anchor-0.1.1.tar.gz
| Download URL | fastapi_anchor-0.1.1.tar.gz |
|---|---|
| Size | 10.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
31ec30ff5c6920749f0ced2a6f2ca47dbccf5efde4262fdb66f2febdf7f5b4d9
|
|
BLAKE2b-256 checksum How to use checksums |
c236400ef9439613cba80f371c0c66172c38e17277508cbd590daf38387d693d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Release files / fastapi_anchor-0.1.1-py3-none-any.whl
| Download URL | fastapi_anchor-0.1.1-py3-none-any.whl |
|---|---|
| Size | 11.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1538ec81e2714a6dddcd00b20c12447277e6d86bd5ea0cc8d2c03311754c5f9f
|
|
BLAKE2b-256 checksum How to use checksums |
ebee9bf1094ff3d8f4a7c4458dd5a1c78b21ec557bdbccc88bd31e265048c43e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.10
|
Security for fastapi-anchor 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.