Just want one protected handler? Start with the [aiohttp quickstart](/docs/quickstarts?sdk=aiohttp).

`authdog.aiohttp` is middleware plus a `require_auth` wrapper for aiohttp handlers. Other Python frameworks: [FastAPI](/docs/backend/fastapi), [Django](/docs/backend/django), [Flask](/docs/backend/flask), [Starlette](/docs/backend/starlette). Hub: [Python](/docs/backend/python).

## Availability and install

**Unreleased on PyPI.** Source-only in [`packages/python`](https://github.com/authdog/web-sdk/tree/main/packages/python). Python 3.10+, aiohttp 3.9+, `httpx` 0.27+.

```bash
python -m pip install "./packages/python[aiohttp]"
```

## Configure

```python
import os
from authdog.aiohttp import Authdog

authdog = Authdog(public_key=os.environ["PK_AUTHDOG"])
```

Add `authdog.middleware` to the aiohttp application. The public key is publishable. Construction rejects malformed keys and identity hosts outside the trusted HTTPS allowlist.

## Session and gate

Bindings are **async**. `await session(request)` is optional context. `@require_auth` is the 401 boundary.

```python
from aiohttp import web

async def index(request):
    ctx = await authdog.session(request)
    return web.json_response({"authenticated": ctx.is_authenticated})

@authdog.require_auth
async def me(request):
    ctx = await authdog.session(request)
    return web.json_response(ctx.user)

async def logout(request):
    return authdog.logout(request)

app = web.Application(middlewares=[authdog.middleware])
app.router.add_get("/", index)
app.router.add_get("/me", me)
app.router.add_get("/logout", logout)
```

`logout` raises aiohttp `HTTPFound`, following that framework’s redirect convention.

## Shared rules

The resolver prefers `authdog-session`, then `Authorization: Bearer <token>`. `fetch_user=False` leaves `is_authenticated` false, so the wrapper rejects. Apply [authorization](/docs/concepts/authorization) after the gate.

Self-hosted identity hosts need `AUTHDOG_ALLOWED_IDENTITY_HOSTS`.
