Open samuelgoto opened 2 months ago
In presentations, the verifier wants to select claims for the holder to disclose and be protected against replays with nonces / pops.
In issuance, the issuer wants to be assured the holder controls a key, and has consented to the claims that will be bound to that key... The holder wants to know which media types are supported, and what credential types are supported.
So there is some symmetry around proof of possession, media types, and credential schemas / types (known structures).
There is also: https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html
Are you asking what are the essential parameters a browser API would need to collect in order to submit an issuance request to some backend?
What is the threat model you have in mind for issuance?
Is it necessary for the holder to encrypt their pop key or other credential information to the issuer?
Should the browser or OS be able to observe specific claims or credential types, or should they just see an encrypted request for issuance?
I've been thinking about issuance in the Web Platform API as very similar to a presentation (pass the OID4VCI request to the app platform), except that there isn't really a response back through the web platform outside of some form of "ack". We should think about what that "ack" actually contains (e.g. what would an issuer's web frontend need/want).
Much of the complexity lives in the app platforms wallet selector.
Ok, here is something to get the discussion started. WDYT?
// Prompts the user to select a wallet to have the digital credential issued, and sends the request to the wallet
// Throws an exception if the user denied the request or didn't have an accepting wallet installed indistinguishably
const credential = await navigator.credentials.create({
digital: {
protocol: "openid4vci",
data: {
// the openid4vci request body, omitted for brevity
},
}
});
// TODO(goto): should we use the navigator.credentials.store(new DigitalCredential()) instead of create()?
~@samuelgoto what's the reasoning for .store
? The ultimate result is the creation of a digital credential in an external container. I think it should be .create
, similar to WebAuthn.~
@samuelgoto what's the reasoning for .store? The ultimate result is the creation of a digital credential in an external container. I think it should be .create, similar to WebAuthn.
Are you referring to this TODO
that I left [1]? The code snippet I proposed uses create()
rather than store()
, right?
[1]
// TODO(goto): should we use the navigator.credentials.store(new DigitalCredential()) instead of create()?
Sorry, looks like I saw an earlier version before it was edited.
Question: is there an equivalent of a "un-issuance"? Can a wallet create
and then invalidate / delete it?
@marcoscaceres what's the difference between the credential manager's store()
and create()
call?
it seems like PublicKeyCredential
uses create()
, but PasswordCredential
and FederatedCredential
use store()
instead (example).
Which one should we use here for issuance?
Question: is there an equivalent of a "un-issuance"? Can a wallet create and then invalidate / delete it?
Not typically via the front channel. WebAuthn will soon have some new methods that allow signaling to the client that credentials are no longer valid, but it's a background / opportunistic thing. Identity wallets will typically have out of band methods for credential revocation / status.
@marcoscaceres what's the difference between the credential manager's store() and create() call? it seems like PublicKeyCredential uses create(), but PasswordCredential and FederatedCredential use store() instead > (example).
Which one should we use here for issuance?
Architecturally, digital credentials and wallets are the same as public key credentials and authenticators. Store is used with user agent internal credential stores. Like authenticators, digital wallets are external, and should use create
.
I've been trying to inform myself on how issuance works, and it seems like there is a pretty tight connection between Issuers and Holders ... meaning, it seems some (enough? all?) Issuers have an out-of-band agreement with Holders and only allow a certain set of enumerated and approved holders ...
That is, am I reading this correctly in that a "wallet chooser" isn't quite correct? -- or only to the extent that the issuer can pick the specific wallets that are offered to the user.
I've been trying to inform myself on how issuance works, and it seems like there is a pretty tight connection between Issuers and Holders ... meaning, it seems some (enough? all?) Issuers have an out-of-band agreement with Holders and only allow a certain set of enumerated and approved holders ...
No, this is certainly not true across the ecosystem. Open wallet choice (no prior agreement with issuers and no permission from issuers required) is important in many areas. In these cases, an issuer may not know or care which wallet a user happens to use. That particular subsets of the ecosystem are more closed does not mean that others aren't more open (they are).
But it is worth noting that even in the open case, some issuers will want to make suggestions to users about which wallets they can use, to enable "just in time" wallet acquisition to receive one or more credentials, etc.
That particular subsets of the ecosystem are more closed does not mean that others aren't more open (they are).
Yeah, that makes sense. I guess, maybe the point that I was trying to make here is that the closed wallet choice is necessary (rather than, as you said, sufficient), and I think we don't yet know how to address that necessity.
I guess, maybe the point that I was trying to make here is that the closed wallet choice is necessary (rather than, as you said, sufficient), and I think we don't yet know how to address that necessity.
One way this sort of thing can be done with the VC API is for the issuer to ask for a VC from the wallet (where that VC is about the wallet itself) during an exchange, prior to (gating) issuance. Perhaps something similar can be modeled or "announced" in an issuance call via the browser API -- whereby a request is included in the issuance parameters (somewhere in store()
) that could be evaluated in a similar way that requests in get()
are / may be to determine applicability.
Something occurred to us as we started to prototype this, and it is whether we'd need to support multiple protocols (e.g. so that wallets that speak one or the other can be shown in the wallet selector) or not, like we do for presentation.
Concretely, I'm wondering if the API should look like the following:
const credential = await navigator.credentials.create({
digital: {
requests: [{
protocol: "openid4vci",
data: {
// the openid4vci request body, omitted for brevity
}
}, {
protocol: "some-other-issuance-protocol",
data: {
// the request body, omitted for brevity
}
}],
}
});
Or what we wrote in https://github.com/WICG/digital-credentials/issues/167#issuecomment-2400478430.
We deliberately left issuance aside while we were trying to figure out presentation, so kicking this issue off just to make sure it doesn't fall through the cracks :)
As thing start to settle with presentation, we should starting thinking how to go about issuance. There are a lot of things and a lot of considerations, so we'll likely want to break this into smaller steps, but kicking this off just to get the ball rolling.