- Authors: Daniel Hardman, Sam Curren, Stephen Curran, Tobias Looker, George Aristy
- Status: PROPOSED
- Since: 2019-04-15
- Status Note: Referenced in some discussions about the peer DID method spec and n-wise DIDs, but not yet implemented.
- Start Date: 2019-03-27
- Tags: feature, protocol
Describes how a go-between can introduce two parties that it already knows, but that do not know each other.
- 20240320: Clarification removing references to retired
~please_ack
decorator and RFC.
Introductions are a fundamental activity in human relationships. They allow us to bootstrap contact information and trust. They are also a source of virality. We need a standard way to do introductions in an SSI ecosystem, and it needs to be flexible, secure, privacy-respecting, and well documented.
This is the Introduce 1.0 protocol. It is uniquely identified by the URI:
"https://didcomm.org/introduce/1.0"
Introductions target scenarios like this:
Alice knows Bob and Carol, and can talk to each of them. She wants to introduce them in a way that allows a relationship to form.
This use case is worded carefully; it is far more adaptable than it may appear at first glance. The Advanced Use Cases section later in the doc explores many variations. But the early part of this document focuses on the simplest reading of the use case.
When we introduce two friends, we may hope that a new friendship ensues. But technically, the introduction is complete when we provide the opportunity for a relationship--what the parties do with that opportunity is a separate question.
Likewise, the goal of our formal introduction protocol should be crisply constrained. Alice wants to gather consent and contact information from Bob and Carol; then she wants to invite them to connect. What they do with her invitation after that is not under her control, and is outside the scope of the introduction.
This suggests an important insight about the relationship between the introduce protocol and the Out-Of-Band protocols: they overlap. The invitation to form a relationship, which begins the Out-Of-Band protocols, is also the final step in an introduction.
Said differently, the goal of the introduce protocol is to start the Out-Of-Band protocols.
[TODO: talk about how humans do introductions instead of just introducing themselves to strangers because it raises trust. Example of Delta Airlines introducing you to Heathrow Airport; you trust that you're really talking to Heathrow based on Delta's asertion.]
There are three [TODO:do we want to support introducing more than 2 at a time?] participants in the protocol, but only two roles.
The introducer begins the process and must know the other two parties. Alice is the introducer in the diagram above. The other two participants are both introducees.
In a successful introduction, the introducer state progresses from
[start] -> arranging -> delivering -> confirming (optional) -> [done]
. Confirming is accomplished with an ACK to an introducee to let them know that their out-of-band message was forwarded.
Meanwhile, each introducee progresses from [start] -> deciding -> waiting -> [done]
.
Of course, errors and optional choices complicate the possibilities. The full state machine for each party are:
The subtleties are explored in the Advanced Use Cases section.
This message informs an introducee that an introducer wants to perform an introduction, and requests approval to do so. It works the same way that proposals do in double-opt-in introductions in the non-agent world:
The DIDComm message looks like this:
{
"@type": "https://didcomm.org/introduce/1.0/proposal",
"@id": "df3b699d-3aa9-4fd0-bb67-49594da545bd",
"to": {
"name": "Bob"
}
}
The to
field contains an introducee descriptor that provides
context about the introduction, helping the party receiving the proposal
to evaluate whether they wish to accept it. Depending on how much context
is available between introducer and introducee independent of the formal
proposal message, this can be as simple as a name, or something fancier (see
Advanced Use Cases below).
A standard example of the message that an introducee sends in response to an introduction proposal would be:
{
"@type": "https://didcomm.org/introduce/1.0/response",
"@id": "283e15b5-a3f7-43e7-bac8-b75e4e7a0a25",
"~thread": {"thid": "df3b699d-3aa9-4fd0-bb67-49594da545bd"},
"approve": true,
"oob-message": {
"@type": "https://didcomm.org/out-of-band/1.0/invitation",
"@id": "12345678900987654321",
"label": "Robert",
"goal": "To issue a Faber College Graduate credential",
"goal_code": "issue-vc",
"handshake_protocols": [
"https://didcomm.org/didexchange/1.0",
"https://didcomm.org/connections/1.0"
],
"service": ["did:sov:LjgpST2rjsoxYegQDRm7EL"]
}
}
A simpler response, also valid, might look like this:
{
"@type": "https://didcomm.org/introduce/1.0/response",
"@id": "283e15b5-a3f7-43e7-bac8-b75e4e7a0a25",
"~thread": {"thid": "df3b699d-3aa9-4fd0-bb67-49594da545bd"},
"approve": true
}
The difference between the two forms is whether the response contains a valid out-of-band message (see RFC 0434). Normally, it should--but sometimes, an introducee may not be able to (or may not want to) share a DIDComm endpoint to facilitate the introduction. In such cases, the stripped-down variant may be the right choice. See the Advanced Use Cases section for more details.
At least one of the more complete variants must be received by an introducer to successfully complete the introduction, because the final step in the protocol is to begin one of the Out-Of-Band protocols by forwarding the message from one introducee to the other.
These messages are not a member of the introductions/1.0
protocol;
they are not even adopted. They belong to the out-of-band protocols, and
are no different from the message that two parties would generate when one
invites the other with no intermediary, except that:
- It is delivered by the introducer, not by either of the introducees.
- It has a
~thread
decorator that identifies the introduction as its parent thread. - If introducees already have DIDComm capabilities, it can be delivered over standard DIDComm channels. If one of the introducees does NOT have a DID-based channel with the introducer, then the message must be delivered to that introducee using the non-DIDComm channel. [TODO: is there a way for the introducer, rather than the other introducee, to "sponsor" the introducee that needs SSI onboarding?]
- If the message is delivered over a DIDComm channel, it is unusual in that it is from a party other than the one that owns the channel.
This message asks for an introduction to be made. This message also uses the
introducee descriptor
block, to tell the potential introducer which
introducee is the object of the sender's interest:
{
"@type": "https://didcomm.org/introduce/1.0/request",
"@id": "df3b699d-3aa9-4fd0-bb67-49594da545bd",
"please_introduce_to": {
"name": "Carol",
"description": "The woman who spoke after you at the PTA meeting last night.",
"expected": true
},
"nwise": false,
"~timing": { "expires_time": "2019-04-23 18:00Z" }
}
The recipient can choose whether or not to honor it in their own way, on
their own schedule. However, a problem_report
could be returned if the
recipient chooses not to honor it.
Any of the parties can be an organization or thing instead of a person.
Bob and Carol may actually know each other already, without Alice realizing it. The introduction may be rejected. It may create a new pairwise relationship between Bob and Carol that is entirely invisible to Alice. Or it may create an n-wise relationship in which Alice, Bob, and Carol know one another by the same identifiers.
Some specific examples follow.
The Out-Of-Band Protocols allow the invited party to be onboarded (acquire software and an agent) as part of the workflow.
Introductions support this use case, too. In such a case, the introducer
sends a standard proposal
to the introducee that DOES have DIDComm
capabilities, but conveys the equivalent of a proposal
over a
non-DIDComm channel to the other introducee. The response
from the
DIDComm-capable introducee must include an out-of-band message with
a deep link for onboarding, and this is sent to the introducee that needs
onboarding.
In this case, the introducer first goes through onboarding via one of the Out-Of-Band protocols with one introducee. Once that introducee can do DIDComm, the previous workflow is used.
This might happen if AliceCorp wants to connect two of its customers. AliceCorp may not be able to talk to either of its customers over DIDComm channels, but it doesn't know whether they can talk to each other that way.
In this case, the introducer conveys the same information that a
proposal
would contain, using non-DIDComm channels. As long as one
of the introducees sends back some kind of response that includes
approval and an out-of-band message, the message can be
delivered. The entire interaction is DIDComm-less.
This might happen if Alice wants to introduce Bob to CarolCorp, and
CarolCorp has published a connection-invitation
for general use.
As introducer, Alice simply has to forward CarolCorp's connection-invitation
to Bob. No proposal
message needs to be sent to CarolCorp;
this is the skip proposal
event shown in the introducer's
state machine.
Alice still acts as the introducer, but Bob now asks Alice to introduce him to a candidate introducee discovered a priori with the help-me-discover
protocol:
{
"@type": "https://didcomm.org/introduce/1.0/request",
"@id": "df3b699d-3aa9-4fd0-bb67-49594da545bd",
"please_introduce_to": {
"discovered": "didcomm:///5f2396b5-d84e-689e-78a1-2fa2248f03e4/.candidates%7B.id+%3D%3D%3D+%22Carol%22%7D"
},
"~timing": { "expires_time": "2019-04-23 18:00Z" }
}
This request
message includes a discovered
property with a linkable message path that uniquely identifies the candidate introducee.
[TODO: A field in the response
where an introducee asks to be notified
that the introduction has been made?]
- Using acks to report status of introduction efforts.
- Timeouts.
- Introducing multiple parties at the same time?
[TODO: What if Alice is introducing Bob, a public entity with no connection to her, to Carol, a private person? Can she just relay Bob's invitation that he published on his website? Are there security or privacy implications? What if she is introducing 2 public entities and has a connection to neither?]
In the tutorial narrative, only a simple proposal was presented. A fancier version might be:
{
"@type": "https://didcomm.org/introduce/1.0/proposal",
"@id": "df3b699d-3aa9-4fd0-bb67-49594da545bd",
"to": {
"name": "Kaiser Hospital",
"description": "Where I want to schedule your MRI. NOTE: NOT the one downtown!",
"description~l10n": { "locale": "en", "es": "Donde se toma el MRI; no en el centro"},
"where": "@34.0291739,-118.3589892,12z",
"img~attach": {
"description": "view from Marina Blvd",
"mime-type": "image/png",
"filename": "kaiser_culver_google.jpg",
"content": {
"link": "http://bit.ly/2FKkby3",
"byte_count": 47738,
"sha256": "cd5f24949f453385c89180207ddb1523640ac8565a214d1d37c4014910a4593e"
}
},
"proposed": false
},
"nwise": true,
"~timing": { "expires_time": "2019-04-23 18:00Z" }
}
This adds a number of fields to the introducee descriptor. Each is optional
and may be appropriate in certain circumstances. Most should be self-explanatory,
but the proposed
field deserves special comment. This tells whether the
described introducee has received a proposal of their own, or will be
introduced without that step.
This example also adds the nwise
field to the proposal. When nwise
is
present and its value is true
, the proposal is to establish an nwise
relationship in which the introducer participates, as opposed to a pairwise
relationship in which only the introducees participate.
[TODO: do we care about having a response signed? Security? MITM?]
[TODO: What can go wrong.]
[TODO: the description
field in an introducee descriptor. Error codes/catalog.]
Why should we not do this?
- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not choosing them?
- What is the impact of not doing this?
Discuss prior art, both the good and the bad, in relation to this proposal. A few examples of what this can include are:
- Does this feature exist in other SSI ecosystems and what experience have their community had?
- For other teams: What lessons can we learn from other attempts?
- Papers: Are there any published papers or great posts that discuss this? If you have some relevant papers to refer to, this can serve as a more detailed theoretical background.
This section is intended to encourage you as an author to think about the lessons from other implementers, provide readers of your proposal with a fuller picture. If there is no prior art, that is fine - your ideas are interesting to us whether they are brand new or if they are an adaptation from other communities.
Note that while precedent set by other communities is some motivation, it does not on its own motivate an enhancement proposal here. Please also take into consideration that Indy sometimes intentionally diverges from common identity features.
- What parts of the design do you expect to resolve through the enhancement proposal process before this gets merged?
- What parts of the design do you expect to resolve through the implementation of this feature before stabilization?
- What related issues do you consider out of scope for this proposal that could be addressed in the future independently of the solution that comes out of this doc?
The following lists the implementations (if any) of this RFC. Please do a pull request to add your implementation. If the implementation is open source, include a link to the repo or to the implementation within the repo. Please be consistent in the "Name" field so that a mechanical processing of the RFCs can generate a list of all RFCs supported by an Aries implementation.
Name / Link | Implementation Notes |
---|---|