ANProto over ATProto -- using Bluesky PDSes to store ANProto messages and blobs
Architecture#
This reference app follows a standard server-side OAuth flow suited for a backend (Node.js/Express) application.
Components#
-
Express Server (
src/index.ts)- Host web endpoints (
/,/login,/oauth/callback). - Manages the browser session (cookie-based) using
iron-session. - NOTE: The browser session is separate from the OAuth session. The browser session just remembers "Who is logged in here?" (by storing the DID).
- Host web endpoints (
-
OAuth Client (
src/client.ts)- Instance of
NodeOAuthClient. - Manages the complexity of the handshake, token exchanges, and key management (DPoP).
- Uses
client-metadatato define itself to the world (redirect URIs, etc.).
- Instance of
-
Storage Adapters (
src/storage.ts)- State Store: Temporarily stores the random
stateparameter generated during the login request to prevent CSRF. - Session Store: Persists the actual Access and Refresh tokens (the "OAuth Session") mapped to the user's DID.
- State Store: Temporarily stores the random
-
Database (
src/db.ts)- A simple SQLite database to back the Storage Adapters.
- In a real app, this would be Postgres, Redis, etc.
The Flow#
- Initiation:
- User enters Handle.
- App calls
client.authorize(handle). - App redirects User to the PDS (e.g., bsky.social login page).
- Authentication:
- User logs in at the PDS.
- User approves the app.
- Callback:
- PDS redirects User back to
/oauth/callback?code=.... - App calls
client.callback(params). clientexchangescodefortokens.clientsaves tokens toSessionStore.- App saves
session.didto the browser cookie.
- PDS redirects User back to
- Usage:
- On subsequent requests, App reads DID from browser cookie.
- App loads OAuth tokens from
SessionStoreusing the DID. - App creates an
Agentto make API calls.