ANProto over ATProto -- using Bluesky PDSes to store ANProto messages and blobs
at main 38 lines 1.6 kB view raw view rendered
1# Handles vs. DIDs 2 3In the AT Protocol, users have two identifiers: a **Handle** and a **DID** (Decentralized Identifier). 4 5## Handle (`alice.bsky.social`) 6- **Human-readable**: Looks like a domain name. 7- **Mutable**: Users can change their handle at any time (e.g., `alice.bsky.social` -> `alice.com`). 8- **Usage**: Used for login input, display names, and mentions. 9- **NOT for Storage**: Never use the handle as the primary key in your database user table. 10 11## DID (`did:plc:z72...`) 12- **Machine-readable**: A unique string starting with `did:`. 13- **Immutable**: This creates a permanent identity for the user, regardless of handle changes. 14- **Usage**: Database primary keys, internal logic, and resolving data from the PDS (Personal Data Server). 15 16## The Resolution Flow 17 181. **User Input**: User types `alice.bsky.social`. 192. **Resolution**: The OAuth client (or a resolver) queries the network to find the DID associated with that handle. 203. **Authentication**: The OAuth flow proceeds using the DID. 214. **Storage**: Your app stores the DID. 225. **Display**: When showing the user, you resolve the DID back to their *current* handle (or cache it and update periodically). 23 24## Code Example 25 26When a user logs in: 27 28```typescript 29// src/index.ts logic 30const handle = req.body.handle; // "alice.bsky.social" 31 32// The client.authorize() method handles the resolution internally! 33const url = await client.authorize(handle, { ... }); 34 35// On callback, we get the session which contains the DID 36const { session } = await client.callback(params); 37const userDid = session.did; // "did:plc:123..." 38```