ANProto over ATProto -- using Bluesky PDSes to store ANProto messages and blobs
1# Architecture 2 3This reference app follows a standard server-side OAuth flow suited for a backend (Node.js/Express) application. 4 5## Components 6 71. **Express Server (`src/index.ts`)** 8 - Host web endpoints (`/`, `/login`, `/oauth/callback`). 9 - Manages the browser session (cookie-based) using `iron-session`. 10 - NOTE: The browser session is *separate* from the OAuth session. The browser session just remembers "Who is logged in here?" (by storing the DID). 11 122. **OAuth Client (`src/client.ts`)** 13 - Instance of `NodeOAuthClient`. 14 - Manages the complexity of the handshake, token exchanges, and key management (DPoP). 15 - Uses `client-metadata` to define itself to the world (redirect URIs, etc.). 16 173. **Storage Adapters (`src/storage.ts`)** 18 - **State Store**: Temporarily stores the random `state` parameter generated during the login request to prevent CSRF. 19 - **Session Store**: Persists the actual Access and Refresh tokens (the "OAuth Session") mapped to the user's DID. 20 214. **Database (`src/db.ts`)** 22 - A simple SQLite database to back the Storage Adapters. 23 - In a real app, this would be Postgres, Redis, etc. 24 25## The Flow 26 271. **Initiation**: 28 - User enters Handle. 29 - App calls `client.authorize(handle)`. 30 - App redirects User to the PDS (e.g., bsky.social login page). 312. **Authentication**: 32 - User logs in at the PDS. 33 - User approves the app. 343. **Callback**: 35 - PDS redirects User back to `/oauth/callback?code=...`. 36 - App calls `client.callback(params)`. 37 - `client` exchanges `code` for `tokens`. 38 - `client` saves tokens to `SessionStore`. 39 - App saves `session.did` to the browser cookie. 404. **Usage**: 41 - On subsequent requests, App reads DID from browser cookie. 42 - App loads OAuth tokens from `SessionStore` using the DID. 43 - App creates an `Agent` to make API calls.