did-challenge-sasl March 2026
Sabadello Informational [Page]
Workgroup:
Common Authentication Technology Next Generation
Published:
Author:
M. Sabadello
Danube Tech GmbH

The DID-CHALLENGE SASL Mechanism

Abstract

This specification defines "DID-CHALLENGE", a mechanism for the Simple Authentication and Security Layer (SASL) based on Decentralized Identifiers (DIDs). The mechanism follows a server-first challenge/response pattern in which the client authenticates by producing a cryptographic signature over a server-generated challenge, using the private key associated with its DID. Unlike password-based SASL mechanisms, no shared secret is transmitted or stored on the server; authentication is grounded entirely in asymmetric cryptography and the verifiable binding between a DID and its associated key material.

An optional extension adds support for Verifiable Credentials (VCs) and Verifiable Presentations (VPs), enabling attribute-based access control in addition to identity authentication.

Table of Contents

1. Introduction

Many Internet protocols require authentication. Common approaches include username/password schemes (as used in IMAP or XMPP), static public key authentication (as used in SSH), and federated identity protocols (as used in OpenID Connect). Each of these approaches has well-known limitations: passwords can be stolen or guessed, static public keys provide no mechanism for revocation, and federated schemes introduce a dependency on a central identity provider.

Decentralized Identifiers are a class of globally unique identifier designed to be created and controlled directly by their subjects, without requiring a central registration authority. A DID resolves to a DID Document - a machine-readable document that contains cryptographic key material and other metadata about the DID subject. DID Documents are anchored in a Verifiable Data Registry: a system - such as a distributed ledger, decentralized file system, or DNS zone - that provides a trustworthy, tamper-evident record of DID state. The controller of a DID can prove that control by signing data with the private key corresponding to a public key published in the DID Document, without needing permission from any third party.

The Simple Authentication and Security Layer is an extensible framework that decouples authentication mechanisms from the application protocols that use them. By defining a SASL mechanism, a new authentication approach can be made available to any SASL-enabled protocol - including IMAP, SMTP, LDAP, XMPP, and others - without modifying those protocols individually.

This specification defines "DID-CHALLENGE", a SASL mechanism that allows a client to authenticate using a DID. The SASL client takes the role of a DID controller; the SASL server takes the role of a DID Resolver and verifier. Authentication proceeds by the server issuing a challenge (a nonce, timestamp, and realm), the client signing that challenge with its DID's private key, and the server verifying the signature against the public key material retrieved from the client's DID Document. Because authentication is based on key ownership rather than a shared secret, a compromise of the server's credential store does not yield material that could be used to impersonate clients.

This specification also defines an optional extension that adds support for Verifiable Credentials (VCs) and Verifiable Presentations (VPs). VCs are signed statements issued by a trusted third party (an Issuer) about a subject - for example, attesting to a person's name, age, professional qualification, or membership in an organisation. After completing the initial DID-based authentication exchange, the server may issue one or more VC/VP Challenges requesting that the client present credentials of a specified type. The client responds with a Verifiable Presentation: a signed envelope containing the requested credentials and binding them to the authenticated DID. This enables the server to make fine-grained, attribute-based access-control decisions beyond simple identity verification.

Readers seeking to implement this mechanism should be familiar with the SASL framework (RFC4422), the W3C DIDs v1.1 - DID Syntax specification, and the W3C DID Resolution v1.0 specification. Familiarity with the W3C Verifiable Credentials Data Model v2.0 specification is required for implementations that use the optional VC/VP extension.

2. SASL mechanism name

The name of the DID-based SASL mechanism is "DID-CHALLENGE".

3. Authentication

This section describes the interaction between a SASL client and SASL server that use the "DID-CHALLENGE" mechanism.

3.1. The Authentication Exchange

The "DID-CHALLENGE" mechanism is a server-first mechanism: the server sends the first piece of authentication data (see Section 3.3) without waiting for any initial client message beyond the mechanism selection.

The exchange consists of the following steps:

C: Request authentication exchange
S: DID Challenge
C: DID Response
S: Outcome of authentication exchange

The mechanism is capable of transferring an authorization identity string (see Section 3.2), which the client MUST include in the DID Response (see Section 3.4).

The server is not expected to provide additional data when indicating a successful outcome. On failure, the server MUST terminate the exchange and SHOULD provide an appropriate error indication to the client in accordance with the enclosing protocol's SASL profile.

As security layers, the mechanism provides authentication and integrity protection of the authorization identity during the exchange, by means of a cryptographic signature over the server-generated challenge (see Section 3.2). It does not provide a general-purpose security layer over the application data stream after authentication completes; confidentiality and integrity of post-authentication traffic MUST be provided by the underlying transport, such as (RFC8446).

The use of TLS is therefore strongly RECOMMENDED whenever this mechanism is employed (see Section 8.2).

3.2. Authorization Identity String

In the "DID-CHALLENGE" mechanism, the authorization identity string is a DID as defined by W3C DIDs v1.1 - DID Syntax, and percent-encoded as defined by RFC3986 - Section 2.1.

Example authorization identity string:

did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D

3.3. DID Challenge

The DID Challenge has the following format:

"<" <nonce> "." <timestamp> "@" <realm> ">"

Where:

  • <nonce> is a server-generated random string. It MUST be unique across all challenges issued by the server. The nonce MUST be generated by a cryptographically strong pseudo-random number generator and MUST contain at least 64 bits of entropy. The nonce MUST NOT contain the characters ".", "@", "<", ">", or SP, as these are used as delimiters in the challenge format.

  • <timestamp> is the number of milliseconds elapsed since the Unix epoch (1970-01-01T00:00:00Z), encoded as a decimal integer with no leading zeros. The server MUST set this field to the current time at the moment the challenge is generated.

  • <realm> is the SASL realm of the server. It identifies the service context to which the challenge belongs and is included in the signed material to prevent cross-service signature reuse. The realm MUST NOT contain the characters "@", "<", ">", or SP.

Example:

<7795631894096664932.1765144656954@java-sasl-xmpp-server>

In this example, the nonce is "7795631894096664932", the timestamp is "1741267200000" (2025-03-06T12:00:00Z in milliseconds), and the realm is "java-sasl-xmpp-server".

3.4. DID Response

The DID Response has the following format:

<did> <signature>

Where:

  • <did> is the client's Decentralized Identifier (DID), percent-encoded as defined in Section 3.2. This is the SASL authorization identity string supplied by the client. The DID MUST be resolvable to a DID Document that contains at least one verification method with an "authentication" verification relationship (see W3C DIDs v1.1 - Verification Relationships.

  • <signature> is the base64url encoding (RFC4648) of the raw bytes of the digital signature, without padding characters ("="). The signature MUST be computed over the entire DID Challenge string (including the enclosing angle brackets) as specified in Section 3.3.

The signing algorithm MUST correspond to the key type of the verification method in the DID document (e.g., Ed25519 for keys of type "Multikey" with a Multibase-encoded Ed25519 public key).

The two fields MUST be separated by exactly one space character. Leading and trailing whitespace in the DID Response MUST NOT be present.

Example:

did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D frEko8nWU-rfArpMZsMVbXpg4xChaQIv_MCmIAmHD3OCWwYvL7CDOedMbezMs4pmGGuzpkRH2QX8UMa-RFToBg

3.5. Verification

The signature in the initial response MUST cover the entire DID Challenge, and is generated using the DID's associated private key.

The server MUST perform the following verification steps:

  • Resolve the DID to its DID document, according to the W3C DID Resolution v1.0.

  • Retrieve the public keys from the DID document which have an "authentication" verification relationship, according to W3C DIDs v1.1 - Verification Relationships.

  • Using the public keys from the DID document, verify the signature in the DID Response against the DID Challenge.

  • Verify that the DID Challenge nonce has not been re-used.

  • Verify that the DID Challenge timestamp is not too long in the past or in the future, e.g. 5 minutes.

4. SASL Exchange with DIDs

This section illustrates the detailed steps of the SASL exchange.

The flow includes the DID Challenge (see Section 3.3) and DID Response (see Section 3.4) steps.

"The DID-CHALLENGE SASL mechanism" Protocol Client Protocol Client SASL Client SASL Client SASL Server SASL Server Protocol Server Protocol Server DID Resolver DID Resolver Network Connection Start login NameCallback for DID DID did%3Akey%3A<..did..> JWKCallback for DID private key DID private key { "kty": "OKP", "crv": "Ed25519", "x": "..", "d": ".." } Start SASL authentication List of authn mechanisms Selected authn mechanism "DID-CHALLENGE" Generate DID Challenge <1809528678543235072.1724868615672@java-sasl-xmpp-server> DID Challenge (nonce, timestamp, realm) Generate DID Response with signature <..signature..> DID Response (DID, signature) did%3Akey%3A<..did..> frEko8nWU<..signature..> Resolve DID DID document with DID public key Verify DID Response with signature true NameCallback with DID (empty) AuthorizeCallback authorized=true with DID Completed SASL authentication

5. (Optional) Authentication with VCs/VPs

This section defines an optional extension of the "DID-CHALLENGE" SASL mechanism which adds support for Verifiable Credentials (VCs) and Verifiable Presentations (VPs).

5.1. The Authentication Exchange (with VC/VP support)

The exchange consists of the following steps (expanding on Section 3):

C: Request authentication exchange
S: DID Challenge
C: DID Response
S: VC/VP Challenge
C: VC/VP Response
S: Outcome of authentication exchange

The steps VC/VP Challenge and VC/VP Response may be repeated multiple times.

5.2. VC-VP Challenge

The VC/VP Challenge follows the following format:

"<" <nonce> "." <timestamp> "." <vc.type> "@" <realm> ">"

Where:

Example:

<7795631894096664932.1765144656954.DegreeCredential@java-sasl-xmpp-server>

5.3. VC-VP Response

The VC/VP Response follows the following format:

<vp>

Where:

Example:

{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://www.w3.org/ns/credentials/examples/v2"
  ],
  "id": "urn:uuid:3978344f-8596-4c3a-a978-8fcaba3903c5",
  "type": ["VerifiablePresentation"],
  "verifiableCredential": [{
    "id": "did:key:z6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D"
    "type": ["DegreeCredential"]
  }]
}

5.4. Verification

The signature in the Verifiable Presentation MUST be generated using the DID's associated private key.

The server MUST perform the following verification steps, in addition to the steps in Section 3.5.

  • Retrieve the public keys from the DID document which have an "assertionMethod" verification relationship, according to W3C DIDs v1.1 - Assertion.

  • Using the public keys from the DID document, verify the proof in the VC/VP Response against the VC/VP Challenge.

  • Verify that the VC/VP Challenge nonce has not been re-used.

  • Verify that the VC/VP Challenge timestamp is not too long in the past or in the future, e.g. 5 minutes.

  • Verify that the "holder" property of the VC/VP Response matches the DID.

  • Verify that the "type" property of the VC/VP Response matches the requested VC type in the VC/VP Challenge.

6. (Optional) SASL Exchange with DIDs and VCs/VPs

This section illustrates the detailed steps of the SASL exchange with DIDs and VCs/VPs, building on Section 4.

The flow includes the DID Challenge (see Section 3.3), DID Response (see Section 3.4), VC/VP Challenge (see Section 5.2), and VC/VP Response (see Section 5.3).

"The DID-CHALLENGE SASL mechanism with VCs" Protocol Client Protocol Client SASL Client SASL Client SASL Server SASL Server Protocol Server Protocol Server DID Resolver DID Resolver Network Connection Start login NameCallback for DID DID did%3Akey%3A<..did..> JWKCallback for DID private key DID private key { "kty": "OKP", "crv": "Ed25519", "x": "..", "d": ".." } opt [Authentication with VCs/VPs] VCCallback for Verifiable Credentials Verifiable Credentials { ... VCs ... } Start SASL authentication List of authn mechanisms Selected authn mechanism "DID-CHALLENGE" Generate DID Challenge <1809528678543235072.1724868615672@java-sasl-xmpp-server> DID Challenge (nonce, timestamp, realm) Generate DID Response with signature <..signature..> DID Response (DID, signature) did%3Akey%3A<..did..> 2mJ4tBo6H<..signature..> Resolve DID DID document with DID public key Verify DID Response with signature true opt [Authentication with VCs/VPs] Generate VC/VP Challenge <1809528678543235072.1724868615672.DegreeCredential@java-sasl-xmpp-server> VC/VP Challenge (nonce, timestamp, vc.type, realm) Generate VC/VP Response with proof <..vp..> VC/VP Response (VP) <..vp..> Verify VC/VP Response with proof true NameCallback with DID (empty) AuthorizeCallback authorized=true with DID Completed SASL authentication

7. Example Exchange

7.1. Step 1: Client NameCallback for DID

When the client is initialized, it obtains a DID to be used for authentication.

-- CLIENT CALLBACK: NameCallback

>C Client DID:  --- defaultName: null, name: null
getName() -> did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D
C> DID:  --- defaultName: null, name: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D

7.2. Step 2: Client JWKCallback for Private Key

When the client is initialized, it obtains a private key that will be used for signing challenges.

-- CLIENT CALLBACK: JWKCallback

>C Client private key:  --- defaultText: (JWK), text: null
getTextInputJWK() -> {
    "kid": "did:key:z6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D#z6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D",
    "kty": "OKP",
    "crv": "Ed25519",
    "x": "EbV6-hVmDiD3DKTUgsf2SjjnO7t0ttwMhStQ5JyCFhw",
    "d": "vGjHIZzZxS3R4mo-V0I_S72ULXDqa2INqkAtuvqJUN8"
}
C> Private key:  --- defaultText: (JWK), text: {
  "kid": "did:key:z6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D#z6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D",
  "kty": "OKP",
  "crv": "Ed25519",
  "x": "EbV6-hVmDiD3DKTUgsf2SjjnO7t0ttwMhStQ5JyCFhw",
  "d": "vGjHIZzZxS3R4mo-V0I_S72ULXDqa2INqkAtuvqJUN8"
}

7.3. Step 3: Server -> Client Challenge

The server initiates the authentication flow by generating and sending a challenge. The challenge contains a none, timestamp, and realm.

-- SERVER -> CLIENT: Challenge
<4513455346757278126.1757192932938@java-sasl-xmpp-server>

7.4. Step 4: Client Signature

The client signs the challenge using the DID's private key.

-- CLIENT
Created signature for challenge <4513455346757278126.1757192932938@java-sasl-xmpp-server>: frEko8nWU-rfArpMZsMVbXpg4xChaQIv_MCmIAmHD3OCWwYvL7CDOedMbezMs4pmGGuzpkRH2QX8UMa-RFToBg

7.5. Step 5: Client -> Server Response

The client response to the server with the DID and the signed challenge.

-- CLIENT -> SERVER: Response
did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D frEko8nWU-rfArpMZsMVbXpg4xChaQIv_MCmIAmHD3OCWwYvL7CDOedMbezMs4pmGGuzpkRH2QX8UMa-RFToBg

7.6. Step 6: Server NameCallback with DID

The server obtains the DID from the client's response.

-- SERVER CALLBACK: NameCallback

>S DID:  --- defaultName: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, name: null
checkName(did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D) --> did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D
S> DID:  --- defaultName: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, name: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D

7.7. Step 7: Server Verification

The server verifies the signature in the client's response by resolving the client's DID to a DID document, which contains public keys need for the verification.

-- SERVER
Verified signature frEko8nWU-rfArpMZsMVbXpg4xChaQIv_MCmIAmHD3OCWwYvL7CDOedMbezMs4pmGGuzpkRH2QX8UMa-RFToBg for challenge <4513455346757278126.1757192932938@java-sasl-xmpp-server>: true

7.8. Step 8: Server AuthorizeCallback with authorization ID

The server determines the DID as the "authorized ID", concluding the authentication flow.

-- SERVER CALLBACK: AuthorizeCallback

>S --- authenticationID: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, authorizationID: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, authorizedID: null, isAuthorized: false
S> --- authenticationID: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, authorizationID: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, authorizedID: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D, isAuthorized: true

authorizationId: did%3Akey%3Az6MkfePUhxLV6cM54cgZ4bGmnEdTNm3WDf4arwh5kR3dH51D

8. Security Considerations

This section addresses the security properties of the DID-CHALLENGE SASL mechanism and the threats it is, and is not, designed to counter. Implementers SHOULD also consult the security considerations of the SASL framework (RFC4422), the W3C Decentralized Identifiers v1.1 specification, and, when the optional VC/VP extension is used, the W3C Verifiable Credentials Data Model 2.0 specification.

8.1. Mechanism Strength

The DID-CHALLENGE mechanism authenticates clients by asymmetric cryptography rather than by transmitting a password or a password- derived value. This eliminates an entire class of server-side risks present in password-based SASL mechanisms such as PLAIN or DIGEST- MD5: a compromise of the server's credential store yields no material that can be used to impersonate clients.

The security of the mechanism depends on the following properties holding simultaneously: (a) the signature algorithm is computationally infeasible to forge; (b) the client's private key has not been compromised; (c) the DID resolver consulted by the server returns an authentic DID document (see Section 8.6; and (d) the authentication exchange is protected from observation and tampering by a lower-layer security protocol (see Section 8.2). If any of these properties fails to hold, the security guarantees of the mechanism are reduced or eliminated entirely.

8.2. Requirement for a Confidential Channel

The DID-CHALLENGE mechanism does not itself provide a security layer (confidentiality or integrity protection of the application- layer data stream after authentication). The client transmits its DID and a cryptographic signature in the clear at the SASL layer. An eavesdropper learns the client's DID, which may be linkable to the client's real-world identity, and obtains a valid signature over a server-chosen challenge string.

The DID-CHALLENGE mechanism MUST NOT be used over an unprotected channel. Implementations MUST employ TLS (RFC8446) or an equivalent protocol providing both confidentiality and integrity before initiating a DID-CHALLENGE exchange.

When the optional VC/VP extension (see Section 5) is used, this requirement is especially critical. Verifiable Presentations may contain sensitive personal attributes — such as name, date of birth, or professional credentials — that are transmitted in the clear at the SASL layer and MUST be protected by the underlying confidentiality layer.

8.3. Replay Attacks

The DID Challenge includes a nonce and a timestamp to prevent replay attacks. The nonce MUST be generated by a cryptographically strong pseudo-random number generator and MUST be unique per challenge. The server MUST maintain a record of all nonces issued within the active timestamp window and MUST reject any DID Response whose nonce has already been accepted. A server that reuses nonces or fails to track them renders the replay defence ineffective.

The timestamp provides a complementary time-bounded validity window. The server MUST reject any DID Response whose challenge timestamp lies outside a configured acceptance window, with a RECOMMENDED default of no more than 5 minutes. Server clocks SHOULD be synchronized via NTP or an equivalent mechanism, since excessive clock skew will cause legitimate authentications to be rejected or, if compensated by widening the window, increase replay exposure.

Both controls apply equally to the VC/VP Challenge and VC/VP Response defined in Section 5. Servers MUST track VC/VP nonces independently and apply the same timestamp validation.

8.4. Man-in-the-Middle Attacks and Channel Binding

Because the client signs a server-supplied challenge, a man-in-the- middle adversary who can intercept and substitute the challenge could induce the client to produce a signature the adversary then uses to authenticate to the real server. Running the exchange over TLS substantially raises the bar for this attack. To eliminate it entirely, implementations SHOULD incorporate a TLS channel binding value (see RFC5929) into the signed material, so that a signature produced within one TLS session cannot be transferred to another.

The realm field in the challenge binds the signature to a specific service context. Clients MUST verify that the realm in the received challenge matches the service they intend to authenticate to before computing the DID Response, and MUST abort the exchange on a mismatch.

8.5. Server Spoofing and Mutual Authentication

The DID-CHALLENGE mechanism provides unilateral authentication: the client proves its identity to the server, but the server does not prove its identity to the client beyond what is provided by the underlying transport. A malicious server can issue a legitimate- looking challenge and collect a valid DID Response.

Clients MUST validate the server's TLS certificate against a trusted certification authority or equivalent trust anchor before initiating a DID-CHALLENGE exchange. Clients MUST NOT proceed if certificate validation fails. Deployments with stronger mutual- authentication requirements MAY combine DID-CHALLENGE with a DID- based server-authentication step at the application layer, though this is outside the scope of this specification.

8.6. Choosing and Trusting DID Resolvers

The server verifies the client's signature using public key material obtained by resolving the client's DID. A malicious or compromised DID resolver that returns a fraudulent DID document could substitute attacker-controlled key material, allowing impersonation of an arbitrary DID. As discussed in W3C DIDs v1.1 - Choosing DID Resolvers, there is no universal authority that mandates a correct resolver implementation for a given DID method; server implementers MUST select DID resolver software they have independently verified and trust.

The network path between the server and its DID resolver SHOULD be protected by TLS. Where the DID method supports it, the integrity of the retrieved DID document SHOULD be verified using content integrity mechanisms before its key material is used. Servers SHOULD restrict the set of accepted DID methods to those whose resolver implementations and underlying registries have undergone independent security review.

8.7. Key Revocation, Rotation, and DID Method Properties

A DID controller who suspects key compromise SHOULD immediately update the DID document to revoke or rotate the affected verification method. There is an inherent window of exposure between the moment of compromise and the moment the revocation propagates to the server's resolver; its duration depends on registry propagation speed and the server's cache refresh policy. Servers MUST NOT rely indefinitely on cached DID documents, and SHOULD treat a DID resolution failure as an authentication failure rather than silently falling back to stale cached data.

DID methods differ significantly in their security properties. Methods such as "did:key" encode the public key directly in the identifier and support neither revocation nor rotation; a compromised private key cannot be remediated and the DID must be abandoned entirely. Methods anchored in distributed ledgers or similar registries support revocation but introduce availability and integrity dependencies on that infrastructure. Methods based on DNS (such as "did:web") inherit the DNS attack surface, including susceptibility to hijacking.

Servers SHOULD maintain an explicit list of accepted DID methods and SHOULD prefer those whose specifications have undergone independent security review, as required by W3C DIDs v1.1 - Security Requirements.

8.8. Non-Repudiation

The DID Response is a cryptographic signature over a challenge that encodes a unique nonce, a timestamp, and the server's realm. Provided the client's private key is used exclusively by the DID controller and has not been compromised, this signature constitutes evidence that the DID controller authenticated to the specified server at approximately the time encoded in the challenge. This property, discussed in W3C DIDs v1.1 - Non-Repudiation, supports non- repudiation of authentication events. Deployments that require non-repudiation for compliance or forensic purposes SHOULD log and archive authentication exchanges accordingly.

8.9. Authentication vs. Authorization

Successful completion of the DID-CHALLENGE exchange proves that the client controls a private key corresponding to a verification method listed under the "authentication" relationship in its DID document. This proves control of the DID; it does not by itself confer any authorization to access resources on the server. Servers MUST maintain and enforce an authorization policy that maps authenticated DIDs to permitted operations, independently of the authentication outcome.

8.10. Private Key Protection

The security of DID-CHALLENGE rests entirely on the secrecy of the client's private key. An adversary who obtains the private key can authenticate as the corresponding DID until the DID document is updated to revoke the associated verification method — and, for DID methods that do not support revocation, indefinitely.

Client implementations MUST protect private keys in a manner commensurate with the sensitivity of the resources being accessed. Suitable measures include hardware security modules (HSMs), operating-system-provided secure key storage, or encrypted software key stores protected by a strong passphrase. Private keys MUST NOT be stored in plaintext. Implementers MUST ensure that the JWKCallback interface does not expose the private key to unauthorized processes or log files.

8.11. Security of the Optional VC/VP Extension

When the optional VC/VP extension is used, the server MUST additionally verify: that the VP proof is valid and was produced using a key with an "assertionMethod" relationship in the client's DID document; that the VP "holder" property matches the authenticated DID; that each credential's issuer signature is valid; that no credential has expired or been revoked; and that the credential type matches the type requested in the VC/VP Challenge.

Servers MUST implement credential status checking to detect revoked credentials, and MUST maintain an explicit issuer trust policy, rejecting credentials from issuers not covered by that policy. The trustworthiness of a credential issuer cannot be inferred from the credential itself. Finally, servers SHOULD request only the credential types strictly necessary for the access-control decision being made, to minimise unnecessary disclosure of personal information, particularly given that VPs are transmitted in the clear at the SASL layer (see Section 8.2).

9. Implementations

The following repositories contain various parts of an example implementation:

Author's Address

Markus Sabadello
Danube Tech GmbH
Margaretenstraße 70/1/7
A-1050 Wien
Austria