-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposed HIPE: Credential Exchange Message Family #89
Conversation
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
I'm wondering what value the attachment approach brings, as opposed to just including the contents as an attribute? |
@TelegramSam I agree, my immediate thought was what happens when we add support for attachments i.e media in credentials and proofs? @KitHat was this driven by the need to have a generic credential exchange messages that spans multiple formats the W3VC space? |
@TelegramSam @tplooker as one of the reasons -- yes. It will be easier to become compliant with W3C credential format if we will keep it as attachment. Moreover, if libindy decides to evolve its format somehow it wont break this format. |
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
"cred_name": "name", | ||
"cred_def_id": "KTwaKJkvyjKKf55uc6U8ZB:3:CL:59:tag1", | ||
"to_did": "Mie7euMJ94nrTHbx5HZEu7", | ||
"from_did": "Mie7euMJ94nrTHbx5HZEu7", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "to_did" and "from_did" seem odd and unnecessary. The cred_def
is sufficient to determine who (what DID) will issue the credential and it's unlikely to be the "from_did" in the message exchange. The two parties having the conversation know each other (they are exchanging messages) and their DIDs for one another. Is there another reason those are needed?
Same reasoning applies to the same fields in the other message types.
{ | ||
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/credential-exchange/1.0/credential-offer", | ||
"@id": "<uuid-offer>", | ||
"cred_id": "<id>", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is cred_id
needed or is this covered by the thread decorator that will be needed throughout the exchange? I think the term should be used differently later in the process on the issuer side so that they have a handle to be used for tracking and revoking the actual issued credential. It would not be part of the message exchange, but an id held by the issuer. I just don't like the idea of using the same term multiple times.
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/credential-exchange/1.0/credential-offer", | ||
"@id": "<uuid-offer>", | ||
"cred_id": "<id>", | ||
"cred_name": "name", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this field is intended to be used for an (optional) interaction with a user - e.g. for a notification on a phone. If so, I'd be tempted to use some other word - e.g. "cred_description" here and make it localized. If it is really the technical name, I'd leave it off as that can be derived from the cred_def
.
```json | ||
{ | ||
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/credential-exchange/1.0/credential", | ||
"@id": "<uuid-credential>", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uuid_credential
is just a name that was meant to refer to some particular @id
for threading. No particular credential connection here.
{ | ||
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/credential-exchange/1.0/credential", | ||
"@id": "<uuid-credential>", | ||
"rev_reg_def_id": "<rev_reg_def_id>", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this embedded in the attachment? Does it need to be called out, or does that just make it easier for the prover to handle the incoming credential?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is also a field inside of an attachment, but it is needed to save the credential (id is needed to get the json in case of libindy). If we send it in this message, messaging library won't need to parse the libindy-specific attachment.
* `cred_def_id` -- ID of Credential Definition this credential were issued to | ||
* `from_did` -- DID of Issuer | ||
* attachment `libindy-cred` -- an actual credential to store, it is a json encoded in base64 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although revocation is an operation between the Issuer and the Ledger, should we add a message that notifies the holder that a credential issued to them has been revoked?
Related; A common pattern with credentials will be that a change of information will trigger the revocation of a credential and the issuance of a new credential. Perhaps that common credential lifecycle pattern is worthy of enhancing the "credential_offer" message to have an optional, associated credential revocation indicator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this is an awesome idea!
I will add that to open questions.
|
||
### Threading | ||
|
||
All of the messages support threading. Using it we can mark what message we are responding to. This is a short set of rules that should be followed to use threading correctly: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this section needs to be adjusted to use enforcement language - e.g. "All of the messages REQUIRE the use of threading." and "...you MUST add a decorator ~thread
..."
* `from_did` -- DID of Issuer | ||
* attachment `libindy-cred` -- an actual credential to store, it is a json encoded in base64 | ||
|
||
#### Presentation Request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since credential issuance and presentation (and revocation, if/depending on how we include it) are different protocols. Should they be in separate message families? At minimum, if properly defined state-transition models for the message family are added (which I think need to be added) - it should be clear that the issuance and presentation are separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't formally prove that they should be in one message family. However, I can't go through the same process about two message families as well. The problem here is that we don't have a clear formal definition of "Message Family" in previous HIPEs.
The only definition (not formal, though) that I found is in HIPE #21. It says:
Message families provide a logical grouping for message types
All of these message types are used for operations with credentials. We can as well state that we can unite them into two groups -- one about credential issuance, and the second one about proof verification. It might be even more convenient to use them as two message families as we can make their versioning separately.
Formally, two message families are at the value level same as one here. In terms of common sense two seems to be better, but I have to think more about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a proposed HIPE that defines how to document Message Families (aka protocols) with an example (tic-tac-toe) - #69. I took a look at it as I was reading this and I think that would lead us to separating out these into several protocols. That might help as you think about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, there are two families instead of one. I had split them.
# Prior art | ||
[prior-art]: #prior-art | ||
|
||
Similar (but simplified) credential exchanged was already implemented in [von-agent](https://von-agent.readthedocs.io/en/latest/von_agent.html2). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reference should be to "von-anchor", rather than von-agent. A rename was done some time back from von-agent to von-anchor, when it was recognized that the code was not an "agent", but rather a foundation for making an agent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed that
* If you send a message in response to an already threaded message, you should add a decorator `~thread` with `pthid` field with value of original `thid` and `thid` with n `@id` of message you respond to. | ||
More details about threading you can find in the [threading and message id HIPE](https://github.com/hyperledger/indy-hipe/blob/master/text/0027-message-id-and-threading/README.md) | ||
|
||
### Previews and negotiation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like there should be more here on non-happy path handling. However, if experience with VCX indicates that this is not necessary - that's fine. Implementation experience matters!
@KitHat ok thanks for the clarification, any comment on how we would handle media in credentials? My concern with pushing the credential into an attachment is where do we then define the indy credential attachment format some where that is visible as a message spec for someone to add support for? My thinking is message families are meant to be this source of definition and also support versioning so therefore we shouldn't be pushing this message definition into an attachment. |
@tplooker what is the problem with media in credential? It is supported in libindy right now, if you can map it to integer to support ZKP-related math (hash it, for example) What about format, right now it is defined this format on libindy level. If someone wants to use it somehow, they have two options:
Maybe libindy is not the best place to define this format, and it is mentioned in HIPE that it might be created as a MIME type in W3C. I think that @dhh1128 is the best person to discuss it. |
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
@KitHat the only way I see how we can currently support media in credentials/proofs is by including the entire contents of media in a raw form as a credential attribute value. However couldn't that become burdensome especially with larger media items, wouldn't a reference like a hash (I realize the current indy-sdk doesnt support this yet) be a better solution? In that case we would need the attachments region for attachment of the actual media as a link to the hash. Personally I think if we are trying to create a generic credential exchange family, perhaps we should be using W3VC as the standard and continuing the effort for indy to become compatible with that format and in the mean time have a credential exchange family for indy based credentials that gets deprecated later? |
@tplooker Could you explain "doesnt support" more explicitly? I don't see any blockers for indy users (applications on all (issuer, proover, verifier sides) to create schema with attribute like "personal_photo_hash_ref" and use it. |
@tplooker BTW this topic more related to attachment content in some messages of proposed family, so it's related to this topic but a bit out of scope this HIPE I think. isn't it? |
It seems like the main reason for utilizing attachments is to differentiate between the format of the message and the format of data carried inside the message. This makes sense when the encoding is entirely different but carries an unnecessarily high overhead when the format of the internal data is JSON. I believe json-ld shows us a better example here, where the type of an internal block of data can be independent of the type of the outer message. I believe we should adopt that pattern here as well, and include the appropriate Thoughts? |
@TelegramSam I agree if, we want the credential exchange message family to be generic but want to preserve versioning and updating of the internal indy based credential messages we would need that support. @jovfer if we are sending say a libindy-proof that discloses a |
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Can you provide examples of what the contents of the attachments look like? |
@swcurran Could you give some clarification on your requests?
Are you asking to move to attributes
Standard messages are described in #65, right? If so, I can't see any information provided about |
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Signed-off-by: Nikita Khateev <nikita.khateev@dsr-corporation.com>
Some more feedback from the most recent Indy Agent (March 27) call about this HIPE:
We also discussed the format of the libindy data in the attachment - should it be base64, the stringified JSON returned by libindy (e.g. with escaped quotes) or JSON. I don't recall if we landed on an answer. In talking about for the 0.1 spec, the devs thought that the stringified JSON would be the best balance as it is easier for some languages we planned on using to not to have to convert it unless necessary. Again -for others on the call - please note if I have missed or misrepresented anything. Thanks! |
This has no impact on this HIPE, but was a topic that came up in the Agent Call. I've put in a JIRA to note that the "prover_did" field that is currently required on the prover.create_credential_request is (very likely) not needed and should be note accordingly - either in the docs or by eliminating it from the call. We suspect it is a carryover from earlier thinking on the credential exchange handling. |
{ | ||
"@type": "did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/credential-issuance/1.0/credential-proposal", | ||
"@id": "<uuid-credential-proposal>", | ||
"credential_proposal": <json-ld object> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking the proposal
should have a schema_id
or cred_def_d
(which implies a schema) attribute. I think it would be needed if the Issuer issues many types of credentials. Without that, it must guess what type of schema the prover is interested in receiving.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea to add these fields as optional
One of the important patterns that we have found in implementing VON is the that a service offering a credential may have pre-requisites that must be proven before it issues the credential. For example, a company must prove they are a registered entity with a legal name before they can be issued a permit (credential) for a restaurant. A typical pattern we expect to see is an entity will apply for a credential (a permit or license) by submitting proof of the prerequisite claims plus some additional service specific information. This is the same as the current "real-world" process we know as the "application", say for insurance or college admission, or for a bank loan. Should the Issue Credential protocol include a "prerequisite" message/attribute that is a presentation-request for which the holder/prover must provide a presentation? That would enable some workflow automation such as we have done with Greenlight (try City of Surrey in the demo) - where we recursively query the Issuer to find out their prerequisites to build a graph of the needed credentials to accomplish some goal. I'd like us to at least consider extending the issuance process to cover this common pattern. |
@swcurran we have discussion with @dhh1128 about presentation some credential before issuance a new one. For now we think it should be sub-protocol, not complication of issuance process. Prerequisite may not be single message but full presentation flow. One of the option here is to use message threading I think. I'm going to update the document and describe this case. |
@jovfer - Yes as I think through it, that should be sufficient. For completeness, here is the use case I'm after. I want a certain credential, but I don't know what I have to present to get the credential - the "Show us 2 out of these 3 documents..." scenario. To find out what I need to present, I send a In our GreenLight (aka dFlow) use case, a bot would do that process recursively to find the pre-requisites for the pre-requisites for the pre-requisites until there are none. That could generate a lot of threads that don't end. Not ideal, but OK. However, even if we decide to address this with an additional message pair, it would be a separate message family, or at most an addition to this one. So - good enough for now. Thanks! |
Signed-off-by: Sergey Minaev <sergey.minaev@dsr-corporation.com>
Signed-off-by: Sergey Minaev <sergey.minaev@dsr-corporation.com>
7714d14
to
2e85595
Compare
KitHat#1 draft for payments inside CX process |
@KitHat / @jovfer - we talked about this HIPE again in the call. Here is the latest feedback:
There were some other individual contributor comments that may also be submitted, but this (hopefully) represents the broad consensus of those of the call. @TelegramSam did a presentation on the payment decorator. The leaning on payments is to have a separate HIPE with the general details on payments (e.g. request, receipt, possibly negotiation) and then other HIPEs like this one would reference that and add details specific to the protocol. Hope that helps! |
Here is a comment on the presentationhttps://docs.google.com/presentation/d/14CuMJcWx-Lx6lsQsRRGy5rARgdoTUKiUV-tcfTFn1bw, specifically slides 4 and 12. (Apologies if I misunderstood the proposal.) The negotiation protocol is overly complex. This is not about human-to-human negotiation, but machine-to-machine Q&A. The iterative approach ("Do you have a USA driver's license? No? Then do you have a Canadian driver's license? No? Then do you have ...") is rather time consuming. We need a query language that specifies in a single go what credentials the Verifier needs. The query language would include at least "OR" and "AND". And the language should be such that the Holder can make derivative queries to Issuers, i.e. by identifying the Issuer and credential definition that it requires.. |
@Oskar-van-Deventer - this protocol covers human-to-human and machine-to-human and machine-to-machine interactions. The protocol is embedded in agents that people use and that machines use. In both scenarios there is a set of business rules that will drive any single execution of the protocol. How the protocol is used is up to the agent controller implementation. There does not need to be a negotiation if the "business rules" of a machine agent instance doesn't want to negotiate - they just respond with the same response regardless of how the peer responds. Agreed that in many machine-to-machine implementations there will be no negotiation. I think we've reached agreement in the working group that "proposal" message is necessary at minimum for enabling the holder to initiate the sequence vs. only the issuer initiating the process. It's useful that it also has the capability to attempt negotiation. A previous iteration of the HIPE had the "request" message used for triggering negotiation, which the working group rejected. The query question of what credentials an issuer provides is interesting. The current assumption of this protocol is that the holder/issuer already agree on the credential of interest before starting. Within the protocol, the issuer may offer (and the holder choose) the selected credential in different formats (e.g. Indy, uPort, Veres One), and the protocol enables the issuer/verifier to negotiate the claims data (values) that will go into the credential. The discovery of what types of credentials an issuer issues is considered outside the scope of this protocol and will be the subject of another protocol (and HIPE). If the issuer wants to issue, and/or the holder wants to receive, a second credential they execute the protocol again for that second credential. As an aside, the BC Gov team has implemented a prototype application that uses discovery to find out what credentials an issuer offers and what prerequisite credentials the issuer needs the holder to prove to be able to get that credential - http://greenlight.orgbook.gov.bc.ca |
It is good to have this discussion. I guess that we need these protocols.
We may have a major misunderstanding here. DIDCom and its associated protocols are agent-to-agent. It is the configuration and business logic in the agent that decides on the response, and whether it is going to involve its human party. No implementation of DIDCom should make any assumption about whether there may be a human party active behind the agent at the other side. So any human-to-human-style negotation should be out of scope. An agent (as verifier) should just tell the other agent (as holder) what it credentials requires for its business decision. That request should be specified semantically precise in machine-parsable JSON. The request can be as verbose as needed, with many AND, OR and IF. The other agent (as holder) can then decide what to do, e.g. provide a set of credentials that satisfy the request; take action to obtain the required credentials, e.g. by getting them from one of the issuers identified in the request; or involve its human party to make a decision. I hope that we all understand that DIDCom is extremely unsuited for human-to-human communication, like voice, video or VR. It is even unsuited for chat, as there exist many good chat protocols (e.g. XMPP) and we should not want to re-invent the wheel. The only reason that there may be human-readable content in a DIDCom message is for testing purposes, which should be disabled when going into production. |
@Oskar-van-Deventer I am mostly aligned with your comments, but I'd like to highlight some subtleties. The first is that we need to represent the concept of "decision points" in protocols. Protocols are not guaranteed to be fully automatable. For example, in a protocol to play chess games, communicating moves is the work of agents and is fully automatable--but deciding which chess move to make is a job for the humans behind the agents. Choosing moves is NOT part of the protocol--but a hook where choices about moves can be made must be. If that hook is used by an AI, fine. If it is used by a human, that is also fine. Protocol implementations must be capable of interfacing with humans at decision points, even if humans are not doing the communication and state management work that embodies the protocol proper. I think you are aligned with this because you mentioned that an agent could involve its human to get a decision, but I'm just checking. The second subtlety arises from the first. If the purpose of a protocol is to get a human to commit to something (e.g., terms of service), then the agent-to-agent message will include as part of its payload something that is human-friendly. The actual message structure is still parsed by agents--but the subset intended for a human can legitimately have human concerns such as localization (which is why there is a HIPE around the topic of localization in DIDComm). |
@dhh1128 Daniel, yes, we are mostly aligned. It is good that you highlight the two subtleties.
As for 1) As for 2) Oskar |
@Oskar-van-Deventer wouldn't the capability to pass human readable messages over DIDComms just be a means to an end for accomplishing what you're talking about in point one? As I understand it, you believe that adding a messaging protocol into DIDComms is redundant because there's others that exist. However, not every messaging protocol is created equal. Some like XMPP are better designed for group messaging where as others are better designed for privacy like Signal's messaging protocol. I posit that given our unique set of properties that we want out of a communication protocol, there's not another messaging protocol that sufficiently meets our needs. If there were to be one, I suspect it's MLS which is why I've been watching their work. With that said I think because we're looking for a unique set of properties in messaging as well as are not looking to explicitly tie ourselves to a single messaging protocol, it makes sense to assume we'll be baking the negotiating in for ease of use by the user. Otherwise, we end up in sticky situations where one user is looking to negotiate over a zoom video chat while the other wants to use signal messaging to negotiate a credential all so that they can come back and use a simpler credential protocol. |
No. We should definitely discuss how we can usefully combine fussy human-to-human communication (voice, video, VR, chat, sign-language, smoke signals) with clean DIDCom agent-to-agent communication.
We should not try to develop a DIDCom-based chat protocol and go into a road towards reinventing the wheel. Oskar |
It seems your view of DIDComms is much different than mine. Let's talk about this in a different thread so that we don't co-opt this discussion that's dependent on it, but not directly related. I'll send you an email so we can setup a call. |
@Oskar-van-Deventer - On the verifier asking for claims from the credentials xx AND (yy OR zz), that is handled at the Indy proof request data structure level (built into the indy-sdk). That is below the DIDComm level, so please look into the indy-sdk code for the complexity supported there - look for that here - https://github.com/hyperledger/indy-sdk/blob/57dcdae74164d1c7aa06f2cccecaae121cefac25/libindy/src/api/anoncreds.rs#L1214. You can propose PRs to the indy-sdk if you think a more complex query scheme is needed. At the DIDComm level, the attachment is simply the data structure processed by the indy-sdk. Note that my previous comments on that topic were about the issuer-holder interaction. Perhaps a good argument that this should be two HIPEs - issuance and presentation. So, since you are rejecting the need for any negotiation during a presentation interaction, I assume that if the holder doesn't have any of the combination of claims they would just send an error message saying "No" (or even return no response). Which would in turn trigger in at least some cases, the verifier starting a new presentation process with a different query string, but one still without any input from the holder on what they can prove. Have I got that right? |
Let me start by saying that I haven't read everything in this thread, so this comment may miss the point. I would like to point out that it is a good practice to keep things 'stupid' and 'small'. It seems to me that if you can leave the human interaction part that is being talked about separate from the simplest DIDComm stuff, having made sure that you can tack it on, then leave it at that. Another point I would like to make is that one of the reasons that current IT is so expensive to maintain, is that it mixes human/business related issues with technical/infrastructural stuff. This means that if business/human stuff changes (which usually is at a very much higher rate than changes required in frastructural stuff), then the infrastructure is down as well - you need to redo everything. So the asking/responding for xx AND (yyOR zz) is business stuff and IMHO should not be part of DIDComm. Rather, it should be part of a different protocol that might use DIDComm (or something else perhaps). And I can see why it might be beneficial to have hooks in DIDComm code that 'business-code' may latch on to, but I cannot judge whether or not that is actually the case. |
@KitHat - I've moved this HIPE PR into two RFC in aries (issue, present). Please take a look. The PR lists the other changes made - I tried not to change the state of the PR, just apply some things that were suggested by the community. In going through it, there is still some adjustments needed, but we can do that using the Aries RFCs process. If I am way off, I can cancel the PRs and we can try again, but I hope I'm not out of line. If all is good, can you please use the HIPE -> RFC process outlined here to close this PR. See step 16 and 17. |
This is now superseded by Aries RFCs 0036 and 0037. |
No description provided.