fix(didresolver): wrap resolved verifier as requested DID#33
Merged
Conversation
`token.VerifySignature` in `ucantone/ucan/token/token.go` compares `tok.Issuer()` against `verifier.DID()` before checking signature bytes. HTTPResolver and MapResolver previously returned an unwrapped did:key verifier when asked to resolve a did:web — so the equality check failed and signatures were rejected with `InvalidSignature` before they were ever examined. Wrap the underlying did:key verifier so its DID() matches the originally requested DID. did:key inputs to MapResolver remain unwrapped (the keys are already self-describing). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Member
|
👏 OMG good debugging |
alanshaw
approved these changes
May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ucantone/ucan/token/token.goVerifySignatureperforms an equality check between the token's issuer DID and the verifier's DID before examining signature bytes:When a token issued by
did:web:foois verified using a verifier returned by HTTPResolver or MapResolver, the resolver was previously handing back an unwrappeddid:key:verifier. The equality check failed,VerifySignaturereturnedfalse, and the validator surfaced anInvalidSignatureerror — even though the signature bytes were perfectly valid.This PR wraps the resolved
did:key:verifier so itsDID()returns the originally-requested DID (thedid:web:the caller asked for).did:key:inputs to MapResolver remain unwrapped, since they already self-describe.Origin
The bug has been present since the resolvers were ported in #17. That PR's description called it out as a known follow-up:
This PR is that follow-up. The wrapping happens at the resolver boundary (rather than inside ucantone), so it lands here in libforge.
How this was found
While debugging a UCAN admin invocation in smelt's local dev stack: sprue's
provider registerself-invocation kept failingInvalidSignaturedespite client and server loading the same key file and the published did.json publishing the matching pub key. Tracing through ucantone's validator showed the early-return on the DID mismatch, and the resolvers were the only realistic spot where that mismatch could be introduced.Test plan
go test ./didresolver/...passes locally (updated assertions reflect new behavior — resolved verifier announces requested DID; underlying did:key reachable viaUnwrap())resolver.Resolve(...).DID()returning the underlyingdid:key:— call sites in sprue/indexing-service/delegator use the verifier only to verify signatures, so the change is safe for them; other consumers should be audited.🤖 Generated with Claude Code