Authentication
The IOTA DIDComm Specification is in the RFC phase and may undergo changes. Suggestions are welcome at GitHub #464.
- Version: 0.1
- Status:
IN-PROGRESS
- Last Updated: 2021-10-29
Overview
This protocol allows two parties to mutually authenticate by disclosing and verifying the DID of each other. On successful completion of this protocol, it is expected that sender authenticated encryption may be used between the parties for continuous authentication.
Relationships
- Connection: it is RECOMMENDED to establish anonymous encryption on connection to prevent revealing the DID of either party to eavesdroppers.
Example Use-Cases
- A connected sensor wants to make sure only valid well-known parties connect to it, before allowing access.
- A customer wants to make sure they are actually connecting to their bank, before presenting information.
- An organisation wants to verify the DID of the employer before issuing access credentials.
Roles
- Requester: initiates the authentication.
- Responder: responds to the authentication request.
Interaction
Messages
1. authentication-request
- Type:
iota/authentication/0.1/authentication-request
- Role: requester
Sent to initiate the authentication process. This MUST be a signed DIDComm message to provide some level of trust to the responder. However, even when signed it is possible to replay an authentication-request, so this message alone is insufficient to prove the DID of the requester. In addition to a unique requesterChallenge
, the created_time
and expires_time
DIDComm message headers SHOULD be used to mitigate such replay attacks. Note that even a successful replay would only reveal the DID of the responder, authentication of a malicious requester will still fail without access to the original requester's private keys due to the use of challenges.
Structure
{
"did": DID, // REQUIRED
"requesterChallenge": string, // REQUIRED
"upgradeEncryption": string, // REQUIRED
}
Field | Description | Required |
---|---|---|
did | DID of the requester.1 | ✔ |
requesterChallenge | A random string unique per authentication-request by a requester to help mitigate replay attacks. | ✔ |
upgradeEncryption | A string indicating whether sender authenticated encryption should be used in the following messages. One of ["required", "optional", "unsupported"] .2 | ✔ |
1 The signing key used for the signed DIDComm envelope wrapping this message MUST be an authentication method in the DID document corresponding to did
, as per the DIDComm specification.
2 The upgradeEncryption
field allows negotiation of whether or not to use sender authenticated encryption for the authentication protocol and for all messages that follow it. It is RECOMMENDED to specify "required"
as it offers various guarantees of continuous authentication and payload integrity for every message. The available options are:
"required"
: the responder MUST initiate sender authenticated encryption, from the following authentication-response message onwards, or send a problem-report."optional"
: the responder chooses whether or not to use sender authenticated encryption."unsupported"
: the responder MUST NOT use sender authenticated encryption. A responder MAY reject authentication-requests that do not support encryption. Any other value forupgradeEncryption
is invalid and should result in an invalid-request problem-report.
Examples
- Request payload requiring encryption:
{
"did": "did:iota:9rK6DPF46MCEzgfLD8AHFsaTuMqvmRo6kbXfjqQJPJmC",
"requesterChallenge": "81285532-b72a-4a99-a9bd-b470475bc24f",
"upgradeEncryption": "required"
}
2. authentication-response
- Type:
iota/authentication/0.1/authentication-response
- Role: responder
Sent in response to an authentication-request, proving the DID of the responder. Optionally establishes sender authenticated encryption based on the value of upgradeEncryption
in the preceding authentication-request. If upgradeEncryption
was "required"
and this message is not encrypted, or "unsupported"
and this message is encrypted, the requester MUST issue a problem-report and abort the authentication.
This message MUST be a signed DIDComm message, even if sender authenticated encryption is used. This is to ensure an authentication key is used to sign the challenge, in accordance with the DID specification, and because there may be increased security controls or guarantees compared to the keyAgreement keys used for sender authenticated encryption.
Structure
{
"did": DID, // REQUIRED
"requesterChallenge": string, // REQUIRED
"responderChallenge": string, // REQUIRED
}
Field | Description | Required |
---|---|---|
did | DID of the responder.1 | ✔ |
requesterChallenge | Must match the requesterChallenge in the preceding authentication-request. | ✔ |
responderChallenge | A random string unique per authentication-response by a responder to help mitigate replay attacks. | ✔ |
1 The signing key used for the signed DIDComm envelope wrapping this message MUST be an authentication method in the DID document corresponding to the did
, as per the DIDComm specification.
Examples
- Responder presenting their DID and offering a challenge to the requester:
{
"did": "did:iota:8cU6DPF56MDEugfLF8AHFaaTuMQvmRo6kbxfjqQJpJmC",
"requesterChallenge": "81285532-b72a-4a99-a9bd-b470475bc24f",
"responderChallenge": "b1f0dc02-85a3-4438-8786-b625f11f1be4"
}
3. authentication-result
- Type:
iota/authentication/0.1/authentication-result
- Role: requester
This message finalises the mutual authentication, proving control over the DID of the requester to the responder. Similar to authentication-response, this message MUST be a signed DIDComm message.
This MUST or MUST NOT use sender authenticated encryption depending on the outcome of the upgradeEncryption
negotiation in the preceding authentication-response message, otherwise resulting in a problem-report and failure of the authentication protocol. For example, if upgradeEncryption
was optional
and the authentication-response used sender authenticated encryption, then the authentication-result MUST be encrypted to be valid.
Structure
{
"responderChallenge": string // REQUIRED
}
Field | Description | Required |
---|---|---|
responderChallenge | Must match the challenge in the preceding authentication-response.1 | ✔ |
1 The signing key used for the signed DIDComm envelope wrapping this message MUST be an authentication method in the DID document corresponding to the did
of the requester in the authentication-request, as per the DIDComm specification.
Examples
- Requester responding with the responder's challenge from the previous message:
{
"responderChallenge": "0768e82d-f498-4f38-8686-918325f9560d"
}
Problem Reports
The following problem-report codes may be raised in the course of this protocol and are expected to be recognised and handled in addition to any general problem-reports. Implementers may also introduce their own application-specific problem-reports.
For guidance on problem-reports and a list of general codes see problem reports.
Code | Message | Description |
---|---|---|
e.p.msg.iota.authentication.reject-authentication | authentication-request, authentication-response, authentication-result | The party rejects an authentication request/response/result for any reason. |
e.p.msg.iota.authentication.reject-authentication.missing-keys | authentication-request, authentication-response, authentication-result | The party rejects an authentication request/response due to the other party lacking a supported keyAgreement section in the DID document. |
e.p.msg.iota.authentication.reject-authentication.untrusted-identity | authentication-request, authentication-response | The party rejects an authentication request/response due to the claimed DID of the other party. |
e.p.msg.iota.authentication.reject-authentication.encyption-required | authentication-request, authentication-response, authentication-result | The party rejects an authentication request/response/result due to the lack of sender authenticated encryption. |
e.p.msg.iota.authentication.reject-authentication.encyption-unsupported | authentication-request, authentication-response, authentication-result | The party rejects an authentication request/response/result because it does not support sender authenticated encryption. |
Considerations
This section is non-normative.
- Trust: this authentication protocol only verifies that both parties have access to the necessary private keys (which could become compromised) associated with their DID documents. Verifying whether a DID document is bound to a physical identity may require additional interactions. Verifying whether a DID can be trusted can be achieved by, for instance:
- requesting a verifiable presentation of credentials issued by a trusted third party, such as a government,
- using the Well Known DID Configuration or embedding the DID in a DNS record to tie an identity to a website or domain,
- using an allowlist of trusted DIDs,
- exchanging DIDs out-of-band in a secure manner (note that some connection invitations could be altered by malicious parties depending on the medium).
- Authorisation: the permissions and capabilities of either party may still need to be established after authentication, either by verifiable presentation as mentioned above or other methods such as JWT tokens
- Privacy: the responder may be subject to probing whereby their DID may be revealed even with the use of sender authenticated encryption, as the
skid
message header is linked to their DID. This is possible if the responder chooses to accept the authentication-request of an unknown requester, or the requester successfully replays an authentication-request from a DID the requester trusts.
Unresolved Questions
Enforce signed DIDComm messages on top of sender-authenticated encryption or keep them optional? Usually unnecessary and DIDComm recommends against this since it's redundant and due to non-repudiation may decrease security and privacy by allowing participants to prove to third parties that authentication occurred.
How to protect the DID of the responder (
skid
field in sender-authenticated message) to prevent probing identities even with anonymous encryption?Add examples of full signed and sender-authenticated messages with headers for better illustration?
Related Work
- Aries Hyperledger:
- Jolocom: https://jolocom.github.io/jolocom-sdk/1.0.0/guides/interaction_flows/#authentication