`XrpcIdentityResolver` #670

Closed ngerakines.me
Closed opened by ngerakines.me

An alternative IdentityResolver that goes through a service (e.g. Slingshot, AppView) using com.atproto.identity.resolveDid or com.atproto.identity.resolveHandle. The only problem I can see with this is attempting to resolve a DID document over Slingshot which is not currently supported. Perhaps which endpoints it uses should be configured and an UnsupportedEndpointError could be returned and an extra resolve_handle method could be added to IdentityResolver for just resolving the DID from a handle.

I would also suggest pulling the resolve_subject part out and requiring a DID for resolve (maybe renaming it to resolve_did?) for consistency.

Thanks, this is a good idea and I'd like to roll with it. A couple of adjustments to the shape:

I'd rather not make resolve DID-only. Most callers pass handles, resolve_verified depends on that, and DidResolver already covers the DID-only case. Instead I'm splitting the trait into a HandleResolver and a DID-document resolver that combine into an IdentityResolver. Then "handles from Slingshot, documents from the PLC directory" is just a pairing, with no runtime UnsupportedEndpointError.

The XRPC resolver itself will use com.atproto.identity.resolveIdentity where the service has it, and resolveHandle for handle-only services. It'll still check that the document's id matches and that alsoKnownAs lists the handle, because the documents carry signing keys and I don't want to trust the service's answer blindly.

This is on main now (2c9a6968), in atproto-identity:

  • HandleResolver and DidDocumentResolver are the two halves of IdentityResolver, and ComposedResolver::new(handles, documents) puts a pair back together.
  • atproto_identity::xrpc::XrpcIdentityResolver implements all three traits: resolveIdentity for IdentityResolver, resolveHandle for HandleResolver, and resolveDid for DidDocumentResolver. For a handle-only service like Slingshot, pair it with DidResolver: ComposedResolver::new(XrpcIdentityResolver::new(client, "https://…")?, DidResolver { … }).

It still checks that the answered DID and the document's id match what was asked for, and resolve_verified checks alsoKnownAs itself. The service's HandleNotFound, DidNotFound and DidDeactivated errors come back as their own ResolveError variants.

Sign up or Sign in to add to the discussion.