Universal DID Native Addressing (UDNA) defines a lightweight, extensible addressing
scheme that makes Decentralized Identifiers (DIDs) native
to resource location and service discovery on the Web. UDNA extends DID from identity resolution to
resource addressing, providing a uniform udna:// URI scheme that encodes a DID and a resource
path, enabling secure, cryptographically verifiable interactions across decentralized systems.
This specification builds on W3C Recommendations ([[DID-CORE]], [[VC-DATA-MODEL]]) and the DIDComm v2
messaging protocol ([[DIDCOMM]]). It is an incubation deliverable of the
UDNA W3C Community Group and does not represent consensus of the broader
W3C Membership.
UDNA completes the addressing stack for decentralized identity: where DNS maps names to IP addresses, and DIDs map identifiers to DID Documents, UDNA maps identity to resources.
This document is a Community Group Draft produced by the W3C Community Group for DID Native Addressing. It is not a W3C Standard nor on the W3C Standards Track. Publication by the W3C does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This specification is being developed to explore the intersection of decentralized identifiers, native addressing, and universal service discovery. The goal is to mature the proposal toward a future W3C Working Group deliverable. The CG welcomes issues and pull requests on GitHub. Before contributing, please review the W3C Community Contributor License Agreement.
The CG has received early reviews from implementers of Solid, DIDComm, and Hyperledger Aries, and expects to conduct multiple interoperability events during 2026.
This section is informative.
UDNA operates as a bridge layer between URI-based resource addressing and decentralized identity infrastructure. It completes the addressing stack for decentralized identity:
The following diagrams illustrate the core resolution flow from a UDNA address to a concrete resource endpoint, and the component relationships within the UDNA ecosystem.
The Web's addressing model is built on URLs that bind authority to domain names, which in turn rely on centralized DNS and certificate authorities. While this has enabled massive growth, it introduces identity silos, privacy leaks, and intermediary dependency. Decentralized Identifiers (DIDs) offer self-sovereign, cryptographically verifiable identities, but they lack a native addressing scheme to directly locate resources, APIs, or services tied to a DID.
UDNA fills this gap. UDNA extends DID from identity resolution to resource addressing.
By introducing the udna:// URI scheme and a deterministic resolution mechanism, UDNA allows
any entity with a DID to publish service endpoints, resources, and sub-paths that can be resolved in a
secure, privacy-preserving way. Conceptually:
UDNA leverages [[DID-CORE]] for identity, [[DIDCOMM]] for secure messaging, and [[VC-DATA-MODEL]] for authorization policies.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, OPTIONAL, RECOMMENDED, REQUIRED, SHALL, SHALL NOT, SHOULD, and SHOULD NOT in this document are to be interpreted as described in BCP 14 [[RFC2119]] [[RFC8174]] when, and only when, they appear in all capitals, as shown here.
This specification defines the following conformance classes:
targetUrl and MUST preserve all path, query, and fragment components
from the original UDNA address. Gateways are defined further in
.
This section defines the terms used throughout this specification.
udna scheme, composed of a DID component, an optional
service segment, and a resource path. Formally specified in .
service array property,
expressed as a URI string, a set of URI strings, or a DIDComm endpoint object.
type: "UDNARoot" or the fragment identifier #udna-root
in the DID Document. A DID Document MUST contain at most one UDNARoot service entry.
The udna URI scheme follows the ABNF syntax below (extending [[RFC3986]]):
udna-URI = "udna://" did-string [ "/" service-id ] path [ "?" query ] [ "#" fragment ]
did-string = scheme ":" method-specific-id
; a valid DID per [[DID-CORE]]
service-id = *( unreserved / pct-encoded )
path = *( "/" segment )
query = *( pchar / "/" / "?" )
fragment = *( pchar / "/" / "?" )
A complete example illustrating all components:
udna://did:example:123456/service/api/resource?version=1#section
did:key:z6Mkp… or
did:web:example.com. The DID forms the authority component of the
[=UDNA Address=].
id fragment of
a service entry in the resolved DID Document. If omitted, the resolver selects the
[=UDNARoot Service=].
This section defines the normative processing steps that a [=UDNA Resolver=] MUST execute. It is separated from the data model to enable independent evolution of processing logic and output structures.
To resolve a [=UDNA Address=], a conformant [=UDNA Resolver=] MUST perform the following steps in order:
invalidUri.
invalidDid.
methodNotSupported. If resolution fails, return a [=ResolutionError=]
of type notFound.
service array whose id fragment matches the given
segment. If no match is found, return a [=ResolutionError=] of type
serviceNotFound.
type
contains "UDNARoot" or whose id fragment equals
udna-root. If neither is found, return a [=ResolutionError=] of type
defaultServiceNotFound.
serviceEndpoint value from the selected service entry.
This value MAY be a URI string, a set of URI strings, or a DIDComm endpoint object.
If the value is unsupported or malformed, return a [=ResolutionError=] of type
invalidEndpoint.
templateExpansionFailed.
targetUrl,
didDocument, didDocumentMetadata,
service, and verificationMethods.
Resolvers SHOULD implement caching with appropriate TTL derived from DID Document
metadata (created, updated). Resolvers MUST respect HTTP
cache headers when resolving did:web identifiers.
A [=ResolutionResult=] is considered valid if and only if ALL of the following conditions are satisfied:
targetUrl MUST be a valid absolute URI as defined
by [[RFC3986]].
didDocument MUST conform to the DID Document data
model defined in [[DID-CORE]], Section 4.
service MUST correspond to an entry present in the
didDocument.service array, matched by id fragment.
didDocumentMetadata MUST include the
created or updated timestamp fields as specified in
[[DID-CORE]].
verificationMethods MUST be a subset of the
verification methods present in the didDocument, filtered to those
relevant to the selected service or DID subject.
A resolver that produces an invalid ResolutionResult SHALL report the violation as an internal error and MUST NOT return the invalid result to the caller.
Conformant [=UDNA Resolvers=] MUST return resolution results conforming to the following structure. The data model extends DID Resolution metadata ([[DID-CORE]]) with UDNA-specific fields.
{
"@context": "https://w3c-cg.github.io/udna/contexts/udna-v1.jsonld",
"type": "UDNAResolutionResult",
"targetUrl": "https://api.example.com/udna/app/profile#me",
"didDocument": {
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:web:example.com",
"service": [ ... ]
},
"didDocumentMetadata": {
"created": "2025-01-01T00:00:00Z",
"updated": "2025-06-01T00:00:00Z",
"deactivated": false
},
"service": {
"id": "#udna-root",
"type": "UDNARoot",
"serviceEndpoint": "https://api.example.com/udna"
},
"verificationMethods": [
{
"id": "did:web:example.com#keys-1",
"type": "Ed25519VerificationKey2020",
"controller": "did:web:example.com",
"publicKeyMultibase": "zH3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
}
]
}
@contexttype"UDNAResolutionResult".
targetUrldidDocumentdidDocumentMetadataserviceverificationMethodsWhen resolution fails, a conformant [=UDNA Resolver=] MUST return a [=ResolutionError=] object using the following structure:
{
"error": "serviceNotFound",
"errorDescription": "No matching service entry found for 'api'",
"did": "did:web:example.com",
"serviceSegment": "api"
}
errorerrorDescriptiondidserviceSegment| Error Code | Description |
|---|---|
notFound |
The DID could not be resolved to a DID Document. |
serviceNotFound |
A service segment was provided but no matching service entry exists. |
defaultServiceNotFound |
No service segment was provided and no UDNARoot service is declared. |
invalidUri |
The provided UDNA address could not be parsed. |
invalidDid |
The DID string extracted from the UDNA address is not a valid DID. |
methodNotSupported |
The DID method is not supported by this resolver. |
invalidEndpoint |
The selected service endpoint is malformed or unsupported. |
templateExpansionFailed |
URI template expansion failed for the selected endpoint. |
When UDNA resolution produces an HTTP-based targetUrl, clients MAY
use standard HTTP content negotiation ([[RFC9110]], Section 12) when interacting
with the resolved endpoint. This section defines content types relevant to UDNA
interactions.
Services exposed via UDNA SHOULD support the following media types:
application/json — Generic JSON responses for
RESTful service interactions.
application/ld+json — JSON-LD formatted responses
for linked data interactions, including credential verification.
application/didcomm-envelope+json — DIDComm v2
encrypted envelopes when the resolved endpoint is a DIDComm service
([[DIDCOMM]]).
Clients MAY include an Accept header to indicate preferred content types.
Services SHOULD respond with an appropriate Content-Type header and
SHOULD return HTTP status 406 Not Acceptable if unable to satisfy the
client's content type preferences.
To promote interoperability across implementations, a conformant [=UDNA Resolver=] MUST expose at minimum the following function signature:
function resolve(udnaURI: string): Promise<ResolutionResult | ResolutionError>;
Implementations MAY additionally provide:
resolveSync(udnaURI): ResolutionResult | ResolutionError
for environments where asynchronous resolution is not required.
resolveBatch(udnaURIs: string[]): Promise<(ResolutionResult | ResolutionError)[]>
for resolving multiple UDNA addresses in a single operation.
watch(udnaURI, callback): Subscription
for observing resolution changes over time.
The canonical reference implementation in JavaScript is available at github.com/w3c-cg/udna.
UDNA resolution can be exposed through an HTTP gateway, enabling clients that do not implement native UDNA resolution to dereference UDNA addresses via standard HTTP requests. This pattern is similar to IPFS gateways and Solid pod access patterns.
A conformant [=UDNA Gateway=] MUST satisfy the following normative constraint:
GW-1: Gateways MUST NOT modify the semantics of the resolved
targetUrl. The path, query, and fragment components from the original
UDNA address MUST be preserved in the final constructed URL without alteration
or filtering.
The canonical gateway resolution pattern is:
GET https://udna-gateway.example/resolve?uri=udna://did:web:example.com/app/profile
→ 302 Redirect to: https://api.example.com/udna/app/profile
Gateways serve as a progressive adoption path, allowing existing Web infrastructure to participate in UDNA resolution without native protocol support. The full gateway behavior is defined in a separate extension specification ("Gateway Forwarding").
This section is informative.
UDNA addresses are designed for eventual native support in browser environments. The following integration model provides a concrete direction for browser vendors and extension developers:
udna:// as a recognized URI scheme.
udna:// URIs using an internal or system-configured
[=UDNA Resolver=].
udna://, enabling user-selected resolution
strategies.
This model ensures UDNA addresses remain resolvable even in environments without native DID infrastructure, while preserving the option for fully decentralized resolution when available.
This section is informative.
Some DID methods introduce significant resolution latency. The UDNA CG is exploring an OPTIONAL "resolution hints" mechanism that allows UDNA addresses to carry lightweight metadata to accelerate resolution.
Resolution hints, if adopted in a future version of this specification, MUST satisfy the following invariants:
This section provides deterministic test vectors to validate inter-implementation consistency of the Processing Model. All vectors assume the DID Document specified in each case.
Context DID Document:
{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:web:example.com",
"service": [{
"id": "#udna-root",
"type": "UDNARoot",
"serviceEndpoint": "https://api.example.com/udna"
}]
}
udna://did:web:example.com/app/profile
https://api.example.com/udna/app/profile
Context DID Document:
{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:example:123",
"service": [
{
"id": "#udna-root",
"type": "UDNARoot",
"serviceEndpoint": "https://example.com/default"
},
{
"id": "#api",
"type": "UDNAApiService",
"serviceEndpoint": "https://api.example.com/v2"
}
]
}
udna://did:example:123/api/users
https://api.example.com/v2/users
Context DID Document: Same as TV-1.
udna://did:web:example.com/docs/spec?version=1.0#section-5
https://api.example.com/udna/docs/spec?version=1.0#section-5
Context DID Document: Same as TV-2.
udna://did:example:123/chat/messages
serviceNotFound
Context DID Document:
{
"@context": "https://www.w3.org/ns/did/v1",
"id": "did:example:456",
"service": [
{
"id": "#custom",
"type": "CustomService",
"serviceEndpoint": "https://custom.example.com"
}
]
}
udna://did:example:456/app
defaultServiceNotFound
UDNA inherits the security properties of the underlying DID methods and DIDComm. The following considerations apply specifically to the UDNA addressing layer.
The UDNA resolution process is subject to the following threat categories:
| Threat | Severity | Mitigation |
|---|---|---|
| Malicious DID Document injection | High | DID method authentication; cryptographic verification of DID Document integrity |
| Service endpoint impersonation | High | Clients MUST verify endpoint ownership via DID-linked verification methods |
| Resolver cache poisoning | Medium | Resolvers SHOULD respect DID Document TTL and HTTP cache-control headers |
| Service confusion attacks | Medium | Resolvers MUST match service segments against exact id fragments |
| Replay of stale DID Documents | Low | Resolvers SHOULD check updated and deactivated metadata |
| Correlation via DID reuse | Medium | Clients SHOULD use pairwise DIDs where strong unlinkability is required |
| Gateway interception | High | Gateways MUST NOT modify targetUrl semantics; clients SHOULD verify resolution independently when possible |
UDNA addresses may expose service endpoints in plaintext within the resolved DID Document.
For private services, implementers SHOULD use DIDComm-based routing or encrypted
serviceEndpoint values.
When accessing resolved endpoints, clients SHOULD demonstrate proof-of-possession of a private key associated with the resolving DID, or delegate access via a Verifiable Credential issued under [[VC-DATA-MODEL]].
UDNA addresses do not inherently create persistent trackable identifiers because DIDs can be rotated. However, repeated resolution of the same DID across different network contexts could enable correlation. To mitigate this, implementers SHOULD use pairwise DIDs per relationship where strong privacy is required.
Resolvers SHOULD enforce rate limiting on DID resolution requests and employ aggressive caching policies to mitigate amplification attacks against DID method infrastructure.
UDNA follows a minimal core + extension model. Core behavior is defined
by this specification; optional capabilities are registered via the udna-ext
query parameter (?udna-ext=https://…). The following extensions are known
at the time of publication:
Versioning of the core scheme is indicated via the udna-version query
parameter. The default value for this specification is 1.0. Future versions
MUST be backward-compatible at the resolution layer unless a breaking version increment
is declared.
UDNA is not intended to replace the following protocols but to unify them under a common addressing layer that respects decentralized identity. Implementations MAY embed UDNA support as a complementary naming and discovery mechanism.
| Framework / Protocol | Focus | UDNA Role |
|---|---|---|
| [[DID-CORE]] | Identifier and DID Document | UDNA uses DID as the naming authority and cryptographic trust anchor. |
| [[DIDCOMM]] | Secure encrypted messaging | UDNA addresses can resolve to DIDComm service endpoints for encrypted channel establishment. UDNA does not require DIDComm, but MAY resolve to DIDComm endpoints. |
| Solid (WebID) [[SOLID]] | Personal linked-data pods | UDNA MAY be used as an alternative addressing mechanism alongside WebID URLs, enabling DID-based access control for Solid pods. |
| ActivityPub | Federated social web | UDNA provides identity-native addressing for actors and objects, removing dependency on domain-based actor URIs. |
| IPFS / IPNS | Content-addressed distributed storage | UDNA addresses can reference IPFS resources and supply DID identity context for access control. |
The UDNA Community Group is actively incubating this specification. The following are current priorities for the 2026 incubation cycle:
did:web,
did:key, and did:tdw to correctly expose UDNA service
endpoints in their DID Documents.
udna:// links, including gateway fallback and extension-based
resolution. See .
This appendix is informative.
This document requests registration of the udna URI scheme with IANA. The
scheme syntax conforms to the rules defined in and the URI
generic syntax of [[RFC3986]]. The CG will submit a formal registration request to IANA
upon reaching draft stability and completing at least two interoperability events.
udnaThe UDNA JSON-LD context is hosted at:
https://w3c-cg.github.io/udna/contexts/udna-v1.jsonld
The current content of the context is:
{
"@context": {
"@version": 1.1,
"@protected": true,
"id": "@id",
"type": "@type",
"UDNAResolutionResult": {
"@id": "https://w3c-cg.github.io/udna/vocab#UDNAResolutionResult",
"@context": {
"@protected": true,
"targetUrl": {
"@id": "https://w3c-cg.github.io/udna/vocab#targetUrl",
"@type": "@id"
},
"didDocument": {
"@id": "https://w3c-cg.github.io/udna/vocab#didDocument",
"@type": "@json"
},
"didDocumentMetadata": {
"@id": "https://w3c-cg.github.io/udna/vocab#didDocumentMetadata",
"@type": "@json"
},
"service": {
"@id": "https://w3c-cg.github.io/udna/vocab#service",
"@type": "@json"
},
"verificationMethods": {
"@id": "https://w3c-cg.github.io/udna/vocab#verificationMethods",
"@container": "@set"
}
}
}
}
}
The editor, Amir Hameed Mir, and the UDNA Community Group thank contributors from the Decentralized Identity Foundation (DIF), W3C DID Working Group alumni, and participants of the Solid and ActivityPub communities. Special thanks to the early implementers who stress-tested the addressing model and provided interoperability feedback during the initial incubation phase.