A Deno-compatible AT Protocol OAuth client that serves as a drop-in replacement for @atproto/oauth-client-node
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add CLAUDE.md documentation for AI coding assistants

+138
+138
CLAUDE.md
··· 1 + # CLAUDE.md 2 + 3 + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 + 5 + ## Project Overview 6 + 7 + This is a Deno-native AT Protocol OAuth client library that provides handle-focused authentication using Web Crypto API. It's an alternative to `@atproto/oauth-client-node` built specifically to solve Node.js crypto compatibility issues in Deno environments. 8 + 9 + **Key Design Philosophy:** 10 + - Handle-focused (accepts `alice.bsky.social` only, not DIDs or URLs) 11 + - Uses Slingshot resolver by default with multiple fallbacks 12 + - Web Crypto API for cross-platform compatibility (no Node.js crypto) 13 + - DPoP (Demonstrating Proof of Possession) authentication with ES256 keys 14 + 15 + ## Development Commands 16 + 17 + ```bash 18 + # Run all tests with required permissions 19 + deno test --allow-net --allow-read 20 + 21 + # Run a specific test file 22 + deno test --allow-net --allow-read tests/session_test.ts 23 + 24 + # Type checking 25 + deno check mod.ts 26 + deno check **/*.ts 27 + 28 + # Format code 29 + deno fmt # check formatting 30 + deno fmt --check # verify formatting 31 + deno fmt <file> # format specific file 32 + 33 + # Lint code 34 + deno lint 35 + 36 + # Run full CI suite (format, lint, check, test) 37 + deno task ci 38 + ``` 39 + 40 + ## Architecture 41 + 42 + ### Core Components 43 + 44 + 1. **OAuthClient** (`src/client.ts`) - Main OAuth flow orchestration 45 + - Handles authorization URL generation with PKCE 46 + - Token exchange and refresh with DPoP 47 + - Pushed Authorization Request (PAR) support 48 + - Concurrency-safe token refresh with per-session locks 49 + 50 + 2. **Session** (`src/session.ts`) - Authenticated session management 51 + - Token lifecycle management (access + refresh tokens) 52 + - DPoP-authenticated request handling with automatic nonce retry 53 + - 5-minute expiration buffer for token refresh 54 + - Serializable session state 55 + 56 + 3. **Handle Resolvers** (`src/resolvers.ts`) - AT Protocol handle resolution 57 + - `SlingshotResolver` (default): Slingshot → Bluesky API → direct lookup fallback chain 58 + - `DirectoryResolver`: Bluesky API only 59 + - `CustomResolver`: User-provided resolution function 60 + - OAuth endpoint discovery from PDS metadata 61 + 62 + 4. **DPoP** (`src/dpop.ts`) - Proof of Possession implementation 63 + - ES256 (ECDSA P-256) key generation using Web Crypto API 64 + - JWT proof generation with `jsr:@panva/jose` (not npm version) 65 + - Automatic nonce handling on 401 challenges 66 + 67 + 5. **Storage** (`src/storage.ts`) - Session persistence abstractions 68 + - `MemoryStorage`: In-memory with TTL support 69 + - `SQLiteStorage`: Deno SQLite backend example 70 + - `LocalStorage`: Browser/localStorage compatible 71 + - All storage is async with TTL support 72 + 73 + 6. **Error Handling** (`src/errors.ts`) - Typed error hierarchy 74 + - All errors extend `OAuthError` base class 75 + - Specific error types for each failure mode 76 + - Error chaining with `cause` support 77 + 78 + ### Critical Implementation Details 79 + 80 + **Web Crypto API Usage:** 81 + - MUST use `crypto.subtle.generateKey()` with `{ name: "ECDSA", namedCurve: "P-256" }` 82 + - NEVER use Node.js crypto APIs - they don't work in Deno 83 + - Import jose from `jsr:@panva/jose` NOT `npm:jose` 84 + 85 + **DPoP Authentication:** 86 + - Every token request requires DPoP proof with ES256 signature 87 + - Access token hash (`ath` claim) required for authenticated requests 88 + - Servers may respond with 400/401 + `DPoP-Nonce` header requiring retry 89 + 90 + **Concurrency Safety:** 91 + - `OAuthClient.restore()` uses `refreshLocks` Map to prevent duplicate refresh requests 92 + - Multiple concurrent restore calls for same session wait on single refresh operation 93 + 94 + **Token Refresh:** 95 + - Sessions considered expired if token expires within 5 minutes 96 + - Refresh may or may not rotate refresh token (server-dependent) 97 + - Refresh failures throw typed errors: `RefreshTokenExpiredError`, `NetworkError`, etc. 98 + 99 + ## Testing 100 + 101 + - All tests use `Deno.test()` with nested `t.step()` for organization 102 + - Use `jsr:@std/assert@1` for assertions 103 + - Tests require `--allow-net` for resolver/OAuth endpoint tests 104 + - Tests are isolated - use helper functions like `createTestSessionData()` 105 + - NO mocking of external services - tests use real AT Protocol endpoints 106 + 107 + ## Security Considerations 108 + 109 + - OAuth state validation prevents CSRF attacks (10-minute TTL on PKCE data) 110 + - PKCE flow protects against authorization code interception 111 + - DPoP binds tokens to specific key pairs 112 + - No credentials should ever be committed to the repository 113 + 114 + ## Publishing 115 + 116 + - Package published to JSR (not npm) 117 + - Version in `deno.json` must be updated before publishing 118 + - Run `deno publish` from repository root 119 + - See `CHANGELOG.md` for version history 120 + 121 + ## Common Tasks 122 + 123 + **Adding a new error type:** 124 + 1. Create class extending appropriate base in `src/errors.ts` 125 + 2. Add JSDoc with `@example` showing usage 126 + 3. Export from `mod.ts` 127 + 4. Add test case in `tests/errors_test.ts` 128 + 129 + **Adding a new storage backend:** 130 + 1. Implement `OAuthStorage` interface in `src/storage.ts` 131 + 2. Handle TTL and expiration logic 132 + 3. Export from `mod.ts` 133 + 4. Add test coverage in `tests/storage_test.ts` 134 + 135 + **Modifying OAuth flow:** 136 + - Changes to `client.ts` likely require testing against real AT Protocol servers 137 + - Ensure PKCE data cleanup happens even on errors 138 + - Maintain per-session refresh lock semantics