Skip to content
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

OID4VP profile for the W3C Digital Credentials API #155

Merged
merged 44 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
fb86e55
added sequence diagram for request uri flow
tlodderstedt Mar 29, 2024
e6c090a
first draft oid4vp profile for dc api
tlodderstedt Apr 14, 2024
4c11ded
fixed formatting
tlodderstedt Apr 14, 2024
95a4c0f
fixed typo
tlodderstedt Apr 15, 2024
f5ba49f
changed request to object
tlodderstedt Apr 17, 2024
278c475
updated PR based on IIW discussion on 04-18
tlodderstedt Apr 17, 2024
24b0573
modified JS code examples
tlodderstedt Apr 17, 2024
25702e0
Update openid-4-verifiable-presentations-1_0.md
tlodderstedt Apr 17, 2024
144f78b
reworked examples and added signed request sequence diagram
tlodderstedt Apr 17, 2024
0cfeb87
Merge branch 'browser_api' of https://github.com/openid/OpenID4VP int…
tlodderstedt Apr 17, 2024
baf35c9
Apply editorial suggestions from code review
Sakurann May 6, 2024
4a9f607
resolve merge conflict
May 28, 2024
96bf495
Apply text improvement suggestions from code review
Sakurann May 28, 2024
8d8d9dc
response is always json
Sakurann May 28, 2024
cb18fc2
how the wallet recieves origin info is out of scope of this profile
Sakurann May 28, 2024
ec2bb01
clarify there are two types of allowed request parameters
Sakurann May 28, 2024
40c9d11
merge remote
May 28, 2024
a264071
reference example file from the text
Jun 14, 2024
c85f012
remove a redundant example and extend one of the examples.
Jun 14, 2024
242fa62
move signed and unsigned request sections and clarify JARM and respon…
Jun 14, 2024
2907e60
Apply suggestions from Sam's code review
Sakurann Jun 19, 2024
f5f199c
merge main
Jun 20, 2024
4122a95
add a history entry
Jun 20, 2024
6d58f69
change to the request member of the API and use openid4vp instead of …
Jun 20, 2024
53fb19a
fix indentation
Jun 20, 2024
72f75c4
Apply suggestions from joseph's code review
Sakurann Jun 20, 2024
d89cd9c
fix request and response examples
Jun 20, 2024
9e583fd
move examples and clarify client_id is not allowed over the unsigned …
Jun 20, 2024
fbf9fe9
JSON -> JS object
Jun 20, 2024
ec75040
update examples
Jun 20, 2024
a15c41c
Apply suggestions from code review
Sakurann Jun 20, 2024
35af423
dropping client_id and client_id_scheme with signed requests
Sakurann Jun 20, 2024
81bfbb0
Apply suggestions from joseph's code review
Sakurann Jun 20, 2024
31ef192
Merge branch 'main' into browser_api
Sakurann Jun 24, 2024
af88822
Apply editorial suggestions from code review
Sakurann Jun 24, 2024
772f537
Apply editorial suggestions from code review
Sakurann Jul 2, 2024
792010e
more editorial. combining suggestions of multiple reviewers
Sakurann Jul 2, 2024
9a160de
remove a confusing expected_origins requirements
Sakurann Jul 2, 2024
084f112
Apply editorial suggestions from code review
Sakurann Jul 8, 2024
ffe96e5
Apply editorial suggestion from code review
Sakurann Jul 8, 2024
cf6aa75
change urn:openid.net:oid4vp to openid4vp
Sakurann Jul 8, 2024
13da249
removing "MUST contain a valid" openid4vp request
Sakurann Jul 8, 2024
4dd3893
changing the error handling
Sakurann Jul 8, 2024
e42c69b
in the examples change urn:openid.net:oid4vp to openid4vp and add res…
Sakurann Jul 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions diagrams/request_uri_mode_post_through_browser_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
```plantuml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens to these files? asking for a friend

Copy link
Contributor

@marcoscaceres marcoscaceres Jul 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question (possibly same friend!) :)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this with Torsten - he would like these diagrams to be in the specification, but wasn't sure how to actually achieve that.

I've opened an issue - hopefully someone might be able to help us achieve that without any manual steps: #206

@startuml

autonumber

participant "User" as u

participant "Verifier Site" as r

participant "Web Platform" as wp

participant "App Platform" as ap

participant "Wallet" as w

u --> r : use
activate r

r -> wp: navigator.identity.get(\nprotocol="urn:openid.net:oid4vp",\nrequest="client_id,[client_id_scheme,] \nrequest_uri, request_uri_method=post, \npresentation_definition")
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

deactivate r
activate wp

wp -> ap: forward request (\norigin="example.verifier.com",\nprotocol="urn:openid.net:oid4vp",\nrequest="client_id,[client_id_scheme,] \nrequest_uri, request_uri_method=post,\n presentation_definition")
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
deactivate wp
activate ap

ap -> ap: select wallet
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
ap -> u: use this wallet?
u -> ap: confirmation

ap -> w: forward request (\norigin="example.verifier.com",\nprotocol="urn:openid.net:oid4vp",\nrequest="client_id,[client_id_scheme,] \nrequest_uri, request_uri_method=post,\n presentation_definition")
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
deactivate ap

activate w
w --> w: [optional. Check client_id with trust framework]
note over r,w
Note that the client_id is self asserted by the verifier.However as the request was dispatched through the browser API, the user consented to forward
the Verifier's request to the wallet. So even if the client_id is not trusted yet, the wallet might proceed and request the signed request object.
end note
w --> r: POST **request_uri** ([wallet_metadata][, wallet_nonce])
r -> r: create and sign (and optionally encrypt) request object
r --> w: **signed (optionally encrypted) request object** (client_id, client_id_scheme, wallet_nonce, nonce, \npresentation_definition, state)
w -> w: authenticate and\n authorize Verifier

note over u, w: User authentication and Credential selection/confirmation

w -> w: create credential presentation(s) \nassociated with nonce
w --> ap: send response \n(vp_token(credential presentation(s)),\n presentation_submission, state)
ap -> wp: send response \n(vp_token(credential presentation(s)),\n presentation_submission, state)
wp -> r: send response \n(vp_token(credential presentation(s)),\n presentation_submission, state)
r -> r: check state
activate r
r -> r: validate presentation \n(incl. nonce binding)
r -> r: use presented credential
@enduml
```
57 changes: 57 additions & 0 deletions diagrams/request_uri_mode_post_through_browser_api.plantuml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
```plantuml
@startuml

autonumber

participant "User" as u

participant "Verifier Site" as r

participant "Web Platform" as wp

participant "App Platform" as ap

participant "Wallet" as w

u --> r : use
activate r

r -> wp: navigator.identity.get(\nprotocol="urn:openid.net:oid4vp",\nrequest="client_id,[client_id_scheme,] \nrequest_uri, request_uri_method=post, \npresentation_definition")
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

deactivate r
activate wp

wp -> ap: forward request (\norigin="example.verifier.com",\nprotocol="urn:openid.net:oid4vp",\nrequest="client_id,[client_id_scheme,] \nrequest_uri, request_uri_method=post,\n presentation_definition")
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
deactivate wp
activate ap

ap -> ap: select wallet
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
ap -> u: use this wallet?
u -> ap: confirmation

ap -> w: forward request (\norigin="example.verifier.com",\nprotocol="urn:openid.net:oid4vp",\nrequest="client_id,[client_id_scheme,] \nrequest_uri, request_uri_method=post,\n presentation_definition")
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
deactivate ap

activate w
w --> w: [optional. Check client_id with trust framework]
note over r,w
Note that the client_id is self asserted by the verifier.However as the request was dispatched through the browser API, the user consented to forward
the Verifier's request to the wallet. So even if the client_id is not trusted yet, the wallet might proceed and request the signed request object.
end note
w --> r: POST **request_uri** ([wallet_metadata][, wallet_nonce])
r -> r: create and sign (and optionally encrypt) request object
r --> w: **signed (optionally encrypted) request object** (client_id, client_id_scheme, wallet_nonce, nonce, \npresentation_definition, state)
w -> w: authenticate and\n authorize Verifier

note over u, w: User authentication and Credential selection/confirmation

w -> w: create credential presentation(s) \nassociated with nonce
w --> ap: send response \n(vp_token(credential presentation(s)),\n presentation_submission, state)
ap -> wp: send response \n(vp_token(credential presentation(s)),\n presentation_submission, state)
wp -> r: send response \n(vp_token(credential presentation(s)),\n presentation_submission, state)
r -> r: check state
activate r
r -> r: validate presentation \n(incl. nonce binding)
r -> r: use presented credential
@enduml
```
10 changes: 10 additions & 0 deletions examples/digital_credentials_api/request_value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"client_id": "client.example.org",
"client_id_scheme": "web-origin",
"response_type": "vp_token",
"nonce": "n-0S6_WzA2Mj",
"client_metadata": {...
},
"presentation_definition": {...
}
}
4 changes: 4 additions & 0 deletions examples/digital_credentials_api/response_value.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presentation_submission": "...",
"vp_token": "..."
}
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
126 changes: 126 additions & 0 deletions openid-4-verifiable-presentations-1_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,132 @@ issuers in Self-Sovereign Identity ecosystems using TRAIN</title>
</front>
</reference>

<reference anchor="w3c.digital_credentials_api" target="https://wicg.github.io/digital-identities/">
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
<front>
<title>Digital Credentials API</title>
<author fullname="Marcos Caceres">
<organization>Apple Inc.</organization>
</author>
<author fullname="Sam Goto">
<organization>Google</organization>
</author>
</front>
</reference>

# OID4VP profile for the W3C Digital Credentials API

This section defines a profile of OID4VP for use with the W3C Digital Credentials API [@!w3c.digital_credentials_api].

The W3C Digital Credentials API defines a Browser API, which allows web sites acting as Verifiers to request the presentation of Verifiable Credentials. The API itself does not define a credential exchange protocol but can be used with different such protocols. The Browser in concert with other layers of the platform/operating system and based on the decision of the user will select the Wallet the request is sent to and provide this Wallet with the request data along with the web origin of the Verifier.
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

The design of this OIDVP profile utilizes the mechanisms of the W3C Digital Credentials API while also allowing to leverage advanced security features of OID4VP, if needed.

This is a non-normative example of a OID4VP request through the W3C Digital Credentials API,

```JavaScipt
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
const credential = await navigator.identity.get({
digital: {
providers: [{
protocol: "urn:openid.net:oid4vp",
request: JSON.stringify({
"client_id": "client.example.org",
"client_id_scheme": "web-origin",
"response_type": "vp_token",
"nonce": "n-0S6_WzA2Mj",
"client_metadata": {...},
"presentation_definition": {...}
})
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved
}]
}
});
```

and here is an non-normative example of how a response is received:

```JavaScipt
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
const { data } = response;
const response = new URLSearchParams(data);
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved
```

There are a couple of benefits for OID4VP implementers (both Verifiers as well as Wallets) to adopt OID4VP with the Digital Credentials API. To start with, the API is a privacy-preserving alternative to the invocation of Wallets through URLs, especially custom schemes. The browser will ensure the invocation of a Wallet is only performed if confirmed by the user based on contextual information of the request and the sender. It also allows to select Wallets based on the credential types being requested and supported, respectively. As request and responses are sent and received through the API, the user will always return to the browser tab where she had started, which results in an improved user experience. And the security of OID4VP implenentations can also be enhanced signficantly. Cross-device requests benefit from the use of proximity checks through a combined use of BLE and a QR Code (similar to Passkeys). Furthermore, the Wallet is provided with information about the Verifier's URL as authenticated by the browser to the request as an additional signal, which can be used for phishing detection.
c2bo marked this conversation as resolved.
Show resolved Hide resolved
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

## Protocol

The value of the `protocol` parameter of the W3C Digital Credentials API MUST be set to `urn:openid.net:oid4vp' for this profile.
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

## Request

The `request` parameter of the W3C Digital Credentials API MUST contain a valid OID4VP Authorization Request, where every Authorization Request parameters is represented as top-level JSON claim as shown in the following non-normative example:
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved

```json
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
{
"client_id": "client.example.org",
...
"response_type": "vp_token",
"nonce": "n-0S6_WzA2Mj",
"presentation_definition": {...}
}
```

Any Authorization Requests as defined in OID4VP can be used except `redirect_uri`. If present, `redirect_uri` MUST be ignored.
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved

NOTE: Implementations MAY use the `request_uri` request parameter as well as the response mode `direct_post` if deeemd necessary. If the `request_uri` parameter is used, the `request` value MUST nevertheless contain the `presentation_definition` parameter in order to enable wallet selection. The signed request object, fetched from the `request_uri` MUST contain a `presentation_definition` that is compatible with the `presentation_definition` in the `request` parameter of the W3C Digital Credentials API.

### Client ID Scheme web-origin

This profile defines the new Client ID Scheme `web-origin`. If this scheme is used, the Client Identifier is the origin of the Verifier web site as asserted by the browser towards the Wallet.

## Response

Every OID4VP request MUST result in a response being provided through the W3C Digital Credentials API. In all cases, except if the response mode `direct_post` is used, the response MUST be follow the rules specified for OID4VP Authorization Responses. If the response model `direct_post` is used, the Wallet will return the URL the Direct Post Endpoint of the Verifier has returned.

The following is an example of an OID4VP Authorization Response through the API:

```json
{
"presentation_submission": "...",
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
"vp_token": "..."
}
```

Note: All mechanisms for cryptographically protecting the OID4VP response MAY be utilized with the W3C Digital Credentials API, too.

## Example Flows
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

As OID4VP is pretty flexible, this section shall shed some light on what flows the authors deem especially useful.

### Default Flow

In the Default flow, the Verifier sends all the OID4VP request data in the `request` parameter and reveices the result in the `result` parameter. In this case, the Wallet will use the Verifier origin as asserted by the Browser as the Verifers's Client Identifier.

### Request URI Flow

In this flow, the Verifier sends a `request` with enough data to select the Wallet but the full OID4VP Authorization Request is fetched by the Wallet from an endpoint hosted by the Verifier. This allows the Verifier to sign and optionally encrypt the request data.

The Verifier should use the `request_uri` parameter in conjunction with the `request_uri_method` parameter with a value of `post`. This will cause the Wallet to send a HTTPS POST request to the endpoint determined by `request_uri`. The request should also contain the `client_metadata` parameter with the Verifier's capabilities in order to allow the Wallet to only offer the capabilities common between both parties to the Verifier.

This is a example of such a request:
Sakurann marked this conversation as resolved.
Show resolved Hide resolved

```JavaScript
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
const credential = await navigator.identity.get({
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved
digital: {
providers: [{
protocol: "urn:openid.net:oid4vp",
Sakurann marked this conversation as resolved.
Show resolved Hide resolved
request: JSON.stringify({
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved
"client_id":"https//client.example.org",
"client_id_scheme":"entity_id",
"presentation_definition":"...",
"request_uri":"https://client.example.org/request",
"request_uri_method":"post"})
tlodderstedt marked this conversation as resolved.
Show resolved Hide resolved
}]
}
});
```

Sakurann marked this conversation as resolved.
Show resolved Hide resolved
The wallet should add a fresh `wallet_nonce` parameter to this request and check whether the resulting signed request object contains this value.

This flows allows the Wallet to authenticate the Verifier using a trust management other than the Web PKI utilized by the browser. An example of such a trust management is the Verifier (RP) management infrastructure set up in the context of the eIDAS regulation in the European Union. The signature over the wallet-provided nonce is a counter-measure against replay as the Wallet can no longer only rely on the web origin of the Verifier. This web origin MAY still be used to further strengthen the security of the flow. The external trust management could, for example, map the Client Identifier to registered web origins.

# Examples with Credentials in Various Formats {#alternative_credential_formats}

OpenID for Verifiable Presentations is Credential format agnostic, i.e., it is designed to allow applications to request and receive Verifiable Presentations and Verifiable Credentials in any format, not limited to the formats defined in [@!VC_DATA]. This section aims to illustrate this with examples utilizing different Credential formats. Customization of OpenID for Verifiable Presentation for Credential formats other than those defined in [@!VC_DATA] uses extension points of Presentation Exchange [@!DIF.PresentationExchange].
Expand Down
Loading