Documentation
¶
Overview ¶
Package didresolver provides the two port.DIDResolver adapters:
- Noop — zero-I/O quickstart resolver; synthesizes the DID document from the submitted proofs' embedded keys.
- Web — the real thing: hardened HTTPS fetch of did.json with WebPKI validation and SSRF dialer guards.
Selected by `identity.resolver.type` ("noop" | "web") in the RA config — the same pattern as the DNS verifier's `dns.type` ("noop" | "lookup").
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Noop ¶
type Noop struct{}
Noop is the quickstart resolver. It never dials anywhere: the DID document is synthesized from the hints — the kid → public-JWK pairs the service extracted from the submitted proofs' `jwk` protected headers.
What this preserves and what it waives, stated precisely (the noop DNS verifier precedent — real crypto, waived external-world binding):
- PRESERVED: every JWS still genuinely verifies against the embedded key, the proof input still binds identityId / nonce / purpose / raId, and the sealed event remains self-verifying.
- WAIVED: the binding "the live did.json at the DID's host really lists this key". Anyone can mint a keypair and claim any did:web value.
Strictly for local development and the demo scripts. NOT for production.
func NewNoopResolver ¶
func NewNoopResolver() *Noop
NewNoopResolver returns the quickstart resolver.
func (*Noop) Resolve ¶
func (n *Noop) Resolve(_ context.Context, did string, hints []port.KeyHint) (*port.DIDDocument, error)
Resolve synthesizes a DID document listing exactly the hinted keys as assertionMethod entries of the requested DID. With no hints (the register-time advisory fetch) the document is valid and empty — the 202 challenge list then carries a single unkeyed entry, and the registrant names keys via the JWS `kid` + `jwk` headers at verify time.
The synthesized Raw entry embeds the registrant's submitted jwk VERBATIM (json.RawMessage passes through marshalling untouched), so the sealed verification method quotes the registrant's exact key bytes — the same no-derived-values rule the web resolver satisfies by quoting the live document.
type Web ¶
type Web struct {
// contains filtered or unexported fields
}
Web is the production did:web resolver: an HTTPS GET of the DID document at the DID's resolution URL, through one hardened fetcher.
The fetch target is registrant-steered (any host the DID names), so SSRF is a first-class control (design §3.7):
- Egress IP denylist enforced at connect time, post-DNS: RFC 1918, loopback, link-local (which covers cloud metadata addresses), ULA, and unspecified addresses are rejected at the dialer, never by hostname string inspection.
- The resolved IP is pinned per host for the duration of one Resolve call — a DNS rebind between redirect hops cannot slip an internal target past check 1.
- Full WebPKI validation (chain to a trusted root + hostname verification) on every fetch — Go's default TLS behavior, left fully enabled.
- Bounded: hard timeout (default 5 s, parity with the DNS verifier), response-size cap (default 1 MiB), ≤5 redirects constrained to the original host's registrable domain.
- Error details never echo resolved IPs, ports, or redirect chains (no SSRF oracle).
func NewWebResolver ¶
NewWebResolver constructs the production resolver.
type WebOption ¶
type WebOption func(*Web)
WebOption customizes the Web resolver.
func WithAllowPrivateNetworks ¶
func WithAllowPrivateNetworks() WebOption
WithAllowPrivateNetworks disables the egress IP denylist. FOR TESTS ONLY — it exists so the full real fetch path (dialer included) is exercisable against a loopback TLS server. Never reachable from configuration.
func WithLogger ¶
WithLogger attaches a server-side logger (default: no-op). It records the failure CATEGORY (the underlying error) plus the DID and elapsed time so an on-call engineer can distinguish a denylist rejection from a DNS-rebind block, a TLS failure, a timeout, or a refused connection — none of which ever reach the API caller (the wire error stays deliberately coarse, no SSRF oracle).
func WithMaxBodyBytes ¶
WithMaxBodyBytes overrides the response-size cap (default 1 MiB).
func WithRootCAs ¶
WithRootCAs overrides the trusted root pool (default: system roots). Deployments with private PKI inject their pool here; tests inject the httptest server's certificate.
func WithTimeout ¶
WithTimeout overrides the per-resolve hard timeout (default 5s).