Metadata-Version: 2.5
Name: atproto-oauth
Version: 0.1.0
Summary: OAuth 2.1 client for the AT Protocol: PAR, PKCE, DPoP, and scope parsing.
Project-URL: Repository, https://github.com/zzstoatzz/atproto-oauth
Project-URL: Upstream, https://github.com/MarshalX/atproto/pull/636
Author: zzstoatzz
License-Expression: MIT
License-File: LICENSE
Keywords: atproto,bluesky,dpop,oauth
Requires-Python: >=3.9
Requires-Dist: atproto<0.1,>=0.0.72
Requires-Dist: cryptography>=41
Requires-Dist: httpx>=0.27
Description-Content-Type: text/markdown

# atproto-oauth

OAuth 2.1 client for the [AT Protocol](https://atproto.com/specs/oauth): pushed authorization requests, PKCE, DPoP with nonce rotation, token refresh and revocation, and scope parsing. It works with any account on any PDS, and re-verifies the DID → PDS → authorization server chain after every token exchange.

It builds on the [`atproto`](https://pypi.org/project/atproto/) SDK for identity resolution. The same code is proposed for the SDK itself in [MarshalX/atproto#636](https://github.com/MarshalX/atproto/pull/636); this package exists so projects can depend on it from PyPI until the SDK ships OAuth.

```bash
uv add atproto-oauth
```

```python
from atproto_oauth import OAuthClient
from atproto_oauth.stores import MemorySessionStore, MemoryStateStore

client = OAuthClient(
    client_id="https://app.example.com/oauth-client-metadata.json",
    redirect_uri="https://app.example.com/oauth/callback",
    scope="atproto",
    state_store=MemoryStateStore(),
    session_store=MemorySessionStore(),
)

# send the user to auth_url; your callback receives code, state and iss
auth_url, state = await client.start_authorization("alice.example.com")
session = await client.handle_callback(code=code, state=state, iss=iss)

response = await client.make_authenticated_request(
    session=session,
    method="GET",
    url=f"{session.pds_url}/xrpc/com.atproto.repo.describeRepo?repo={session.did}",
)
```

For local development, a client ID of `http://localhost` makes it a loopback client with no hosted metadata; use `http://127.0.0.1` in the redirect URI.

Set `ATPROTO_USER_AGENT` to replace httpx's default User-Agent for the whole process.
