CLI app for developers prototyping atproto functionality
1
fork

Configure Feed

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

Add `verificationMethod` to synthetic DID document

atproto's identity spec requires every DID document to include a
`verificationMethod` entry with id `#atproto` and type `Multikey`.
The synthetic DID document was missing it, so strict atproto
identity resolvers (atrium, `@atproto/identity`, etc.) rejected
the document during handle resolution and the OAuth flow never
reached the fake AS.

The DID document now publishes a Multikey derived from a fixed
secp256k1 seed and adds the matching suite contexts
(`multikey/v1` and `suites/secp256k1-2019/v1`) to `@context`. The
fake AS never signs anything with the key — it is published only
to satisfy the spec — and the seed is fixed so the key is stable
across runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

+28 -1
+28 -1
src/commands/test/oauth/client/fake_as/identity.rs
··· 1 + use k256::ecdsa::SigningKey as K256SigningKey; 1 2 use serde_json::json; 2 3 use url::Url; 4 + 5 + use crate::common::identity::{AnySigningKey, encode_multikey}; 6 + 7 + /// Fixed seed for the synthetic atproto rotation key. The fake AS 8 + /// never signs anything with this key — we only publish the 9 + /// corresponding `verificationMethod` so the synthetic DID document 10 + /// satisfies the atproto identity spec, which requires a `#atproto` 11 + /// Multikey entry. A fixed seed keeps the published key stable 12 + /// across runs. 13 + const ATPROTO_KEY_SEED: [u8; 32] = *b"atproto-devtool fake-as synth-01"; 3 14 4 15 /// A synthetic atproto identity chain — handle, DID, DID document, 5 16 /// PRM and AS metadata — all bound to a base URL. `did:web` resolves ··· 41 52 let authorize_endpoint = format!("{base_with_slash}oauth/authorize"); 42 53 let token_endpoint = format!("{base_with_slash}oauth/token"); 43 54 55 + let signing_key = 56 + K256SigningKey::from_slice(&ATPROTO_KEY_SEED).expect("fixed seed is a valid K256 key"); 57 + let multikey = encode_multikey(&AnySigningKey::K256(signing_key).verifying_key()); 58 + 44 59 let did_document = json!({ 45 - "@context": ["https://www.w3.org/ns/did/v1"], 60 + "@context": [ 61 + "https://www.w3.org/ns/did/v1", 62 + "https://w3id.org/security/multikey/v1", 63 + "https://w3id.org/security/suites/secp256k1-2019/v1", 64 + ], 46 65 "id": did, 47 66 "alsoKnownAs": [at_url], 67 + "verificationMethod": [ 68 + { 69 + "id": format!("{did}#atproto"), 70 + "type": "Multikey", 71 + "controller": did, 72 + "publicKeyMultibase": multikey, 73 + } 74 + ], 48 75 "service": [ 49 76 { 50 77 "id": "#atproto_pds",