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

remove c_nonce from the token endpoint response #381

Merged
merged 12 commits into from
Oct 8, 2024
66 changes: 48 additions & 18 deletions openid-4-verifiable-credential-issuance-1_0.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ keyword = ["security", "openid", "ssi"]

[seriesInfo]
name = "Internet-Draft"
value = "openid-4-verifiable-credential-issuance-1_0-14"
value = "openid-4-verifiable-credential-issuance-1_0-15"
status = "standard"

[[author]]
Expand Down Expand Up @@ -118,6 +118,7 @@ Deferred Credential Issuance:
This specification defines an API for Credential issuance provided by a Credential Issuer. The API is comprised of the following endpoints:

* A mandatory Credential Endpoint from which Credentials can be issued (see (#credential-endpoint)). From this endpoint, one Credential, or multiple Credentials with the same Credential Dataset can be issued in one request.
* An optional Nonce Endpoint from which a fresh a `c_nonce` value can be obtained to be used in proof of possession of key material in a subsequent request to the Credential Endpoint (see (#nonce-endpoint)).
bc-pi marked this conversation as resolved.
Show resolved Hide resolved
* An optional Deferred Credential Endpoint to allow for the deferred delivery of Credentials (see (#deferred-credential-issuance)).
* An optional mechanism for the Credential Issuer to make a Credential Offer to the Wallet to encourage the Wallet to start the issuance flow (see (#credential-offer-endpoint)).
* An optional mechanism for the Credential Issuer to receive from the Wallet notification(s) of the status of the Credential(s) that have been issued.
Expand All @@ -137,7 +138,6 @@ Existing OAuth 2.0 mechanisms are extended as following:
* A new authorization details [@!RFC9396] type `openid_credential` is defined to convey the details about the Credentials (including Credential Dataset, Credential Formats, and Credential types) the Wallet wants to obtain (see (#authorization-details)).
* Client metadata is used to convey the Wallet's metadata. The new Client metadata parameter `credential_offer_endpoint` is added to allow a Wallet (acting as OAuth 2.0 client) to publish its Credential Offer Endpoint (see (#client-metadata)).
* Authorization Endpoint: The additional parameter `issuer_state` is added to convey state in the context of processing an issuer-initiated Credential Offer (see (#credential-authz-request)). Additional parameters `wallet_issuer` and `user_hint` are added to enable the Credential Issuer to request Verifiable Presentations from the calling Wallet during Authorization Request processing.
* Token Endpoint: Optional response parameters `c_nonce` and `c_nonce_expires_in` are added to the Token Endpoint, and Credential Endpoint to provide the Client with a nonce to be used for proof of possession of key material in a subsequent request to the Credential Endpoint (see (#token-response)).
bc-pi marked this conversation as resolved.
Show resolved Hide resolved

## Core Concepts

Expand Down Expand Up @@ -648,8 +648,6 @@ The Authorization Server might decide to authorize issuance of multiple instance

In addition to the response parameters defined in [@!RFC6749], the Authorization Server MAY return the following parameters:

* `c_nonce`: OPTIONAL. String containing a nonce to be used when creating a proof of possession of the key proof (see (#credential-request)). When received, the Wallet MUST use this nonce value for its subsequent requests until the Credential Issuer provides a fresh nonce.
* `c_nonce_expires_in`: OPTIONAL. Number denoting the lifetime in seconds of the `c_nonce`.
* `authorization_details`: REQUIRED when the `authorization_details` parameter is used to request issuance of a certain Credential Configuration as defined in (#authorization-details). It MUST NOT be used otherwise. It is an array of objects, as defined in Section 7 of [@!RFC9396]. In addition to the parameters defined in (#authorization-details), this specification defines the following parameter to be used with the authorization details type `openid_credential` in the Token Response:
* `credential_identifiers`: REQUIRED. Array of strings, each uniquely identifying a Credential Dataset that can be issued using the Access Token returned in this response. Each of these Credential Datasets corresponds to the same Credential Configuration in the `credential_configurations_supported` parameter of the Credential Issuer metadata. The Wallet MUST use these identifiers together with an Access Token in subsequent Credential Requests.

Expand All @@ -666,8 +664,6 @@ Cache-Control: no-store
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..sHQ",
"token_type": "bearer",
"expires_in": 86400,
"c_nonce": "tZignsnFbp",
"c_nonce_expires_in": 86400,
"authorization_details": [
{
"type": "openid_credential",
Expand Down Expand Up @@ -710,6 +706,47 @@ Cache-Control: no-store
}
```

# Nonce Endpoint {#nonce-endpoint}

This endpoint allows a Client to acquire a fresh `c_nonce` value without the overhead of a full Credential Request. A Credential Issuer that requires `c_nonce` values to be incorporated into proofs in the Credential Request (see (#credential-request)) MUST offer a Nonce Endpoint.
bc-pi marked this conversation as resolved.
Show resolved Hide resolved
nemqe marked this conversation as resolved.
Show resolved Hide resolved

The `nonce_endpoint` Credential Issuer Metadata parameter, as defined in (#credential-issuer-parameters), contains the URL of the Credential Issuer's Nonce Endpoint.
bc-pi marked this conversation as resolved.
Show resolved Hide resolved


## Nonce Request {#nonce-request}

A request for a nonce is made by sending an HTTP GET request to the URL provided in the `nonce_endpoint` Credential Issuer Metadata parameter.
bc-pi marked this conversation as resolved.
Show resolved Hide resolved

bc-pi marked this conversation as resolved.
Show resolved Hide resolved
Below is a non-normative example of a Nonce Request:

```
GET /nonce HTTP/1.1
Copy link
Collaborator

@tlodderstedt tlodderstedt Sep 26, 2024

Choose a reason for hiding this comment

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

Wouldn't a POST request be more appropriate? I mean the endpoint is supposed to provide a new/different value with every response and the result should not be cached (in my opinion).

Copy link
Contributor

Choose a reason for hiding this comment

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

+1, I tried to push in this direction as well: #381 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I didn't realize this was GET. my suggestion has been POST. In german wallet project we have been prototyping with POST and it works well https://bmi.usercontent.opencode.de/eudi-wallet/eidas-2.0-architekturkonzept/flows/PID-IssuerSigned-cloud/#issuer-session-endpoint-at-the-pid-provider

Copy link
Member Author

@bc-pi bc-pi Sep 26, 2024

Choose a reason for hiding this comment

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

Other than describing the media type of content that doesn't exist as JSON, which is semantically invalid and maybe syntactically wrong too, what value does the German wallet project get from using POST?

=== Screenshot of the previously cited german wallet project ===
Screenshot 2024-09-26 at 10 22 06 AM

Copy link
Member Author

@bc-pi bc-pi Sep 26, 2024

Choose a reason for hiding this comment

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

Wouldn't a POST request be more appropriate?

No.

I mean the endpoint is supposed to provide a new/different value with every response and the result should not be cached (in my opinion).

That's why it was made not cacheable in the example https://github.com/openid/OpenID4VCI/pull/381/files#diff-1f424614b35a9899813079f1b1f6218631a2aedd993368ccb89bb81a9eda0289R741 and text https://github.com/openid/OpenID4VCI/pull/381/files#diff-1f424614b35a9899813079f1b1f6218631a2aedd993368ccb89bb81a9eda0289R734 using the Cache-Control construct that HTTP gives for control of caching.

Copy link
Contributor

@nemqe nemqe Sep 27, 2024

Choose a reason for hiding this comment

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

My 2 cents for what they are worth,

If we asked the question "is this call safe (i.e. is it read-only)" I think the answer would be "maybe". Safe calls shouldn't alter the state of the server in any way but without knowing how the server implements the nonce endpoint we would not know the answer to the question.

If we asked the question "is this call idempotent" I think we would also get a "maybe". Client could do this call just to "fetch a value" which might not assume any intention of a side-effect, and from the perspective of the server it would depend on the implementation.

I do see the point in making it a GET because it is technically just fetching a random value, so semantically if fits, but there might be an embedded assumption here that this random value is a prerequisite for some other steps, and that getting a nonce can be viewed as setting up a state that needs to be validated by the server.

One could argue that it might be safer to make this a POST because this would communicate that the call might not be safe or idempotent and that subsequent calls could cause load, burden, and side-effects for the server.

But this is just philosophizing, I personally do not have a clear preference, I see arguments for both GET and POST.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can see arguments for both as well but was really trying to avoid them entirely with a simple (maybe simplistic) approach.

Copy link
Member Author

Choose a reason for hiding this comment

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

but avoidance didn't work and so f7b4dc8 Removed the HTTP method specificity from the Nonce Request text and change the example from GET to POST

Copy link
Collaborator

Choose a reason for hiding this comment

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

After reading the comments and listening to the discussions, I'm ok with GET or POST, but we need to pick one.

Copy link
Member Author

Choose a reason for hiding this comment

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

as discussed on the call - it's POST now 55c8388

Host: credential-issuer.example.com
```

## Nonce Response {#nonce-response}

The Credential Issuer provides a nonce value in the HTTP response with a 2xx status code and the following parameters included as top-level members in the message body of the HTTP response using the application/json media type:
bc-pi marked this conversation as resolved.
Show resolved Hide resolved

* `c_nonce`: REQUIRED. String containing a nonce to be used when creating a proof of possession of the key proof (see (#credential-request)).
bc-pi marked this conversation as resolved.
Show resolved Hide resolved
* `c_nonce_expires_in`: OPTIONAL. Number denoting the lifetime in seconds of the `c_nonce`.
bc-pi marked this conversation as resolved.
Show resolved Hide resolved

Due to the temporal and contextually sensitive nature of the `c_nonce` value, the Credential Issuer MUST make the response uncacheable by adding a `Cache-Control` header field including the value `no-store`.
bc-pi marked this conversation as resolved.
Show resolved Hide resolved

Below is a non-normative example of a Nonce Response:

```
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
bc-pi marked this conversation as resolved.
Show resolved Hide resolved

{
"c_nonce": "wKI4LT17ac15ES9bw8ac4",
"c_nonce_expires_in": 120
}
```


# Credential Endpoint {#credential-endpoint}

The Credential Endpoint issues one or more Credentials of the same Credential Configuration and Credential Dataset (as approved by the End-User) upon presentation of a valid Access Token representing this approval. Support for this endpoint is REQUIRED.
Expand Down Expand Up @@ -750,9 +787,9 @@ A Client makes a Credential Request to the Credential Endpoint by sending the fo

The `proof_type` parameter is an extension point that enables the use of different types of proofs for different cryptographic schemes.

The proof(s) in the `proof` or `proofs` parameter MUST incorporate the Credential Issuer Identifier (audience), and optionally a `c_nonce` value generated by the Authorization Server or the Credential Issuer to allow the Credential Issuer to detect replay. The way that data is incorporated depends on the key proof type. In a JWT, for example, the `c_nonce` value is conveyed in the `nonce` claim, whereas the audience is conveyed in the `aud` claim. In a Linked Data proof, for example, the `c_nonce` is included as the `challenge` element in the key proof object and the Credential Issuer (the intended audience) is included as the `domain` element.
The proof(s) in the `proof` or `proofs` parameter MUST incorporate the Credential Issuer Identifier (audience), and optionally a `c_nonce` value generated by the Credential Issuer to allow the Credential Issuer to detect replay. The way that data is incorporated depends on the key proof type. In a JWT, for example, the `c_nonce` value is conveyed in the `nonce` claim, whereas the audience is conveyed in the `aud` claim. In a Linked Data proof, for example, the `c_nonce` is included as the `challenge` element in the key proof object and the Credential Issuer (the intended audience) is included as the `domain` element.

The initial `c_nonce` value can be returned in a successful Token Response as defined in (#token-response), or in a Credential Error Response as defined in (#issuer-provided-nonce).
The initial `c_nonce` value can be returned in a Nonce Response as defined in (#nonce-response), or in a Credential Error Response as defined in (#issuer-provided-nonce).
nemqe marked this conversation as resolved.
Show resolved Hide resolved

Below is a non-normative example of a Credential Request for a Credential in [@ISO.18013-5] format using Credential Format-specific parameters and a key proof type `jwt`:

Expand Down Expand Up @@ -1258,6 +1295,7 @@ This specification defines the following Credential Issuer Metadata parameters:
* `credential_issuer`: REQUIRED. The Credential Issuer's identifier, as defined in (#credential-issuer-identifier).
* `authorization_servers`: OPTIONAL. Array of strings, where each string is an identifier of the OAuth 2.0 Authorization Server (as defined in [@!RFC8414]) the Credential Issuer relies on for authorization. If this parameter is omitted, the entity providing the Credential Issuer is also acting as the Authorization Server, i.e., the Credential Issuer's identifier is used to obtain the Authorization Server metadata. The actual OAuth 2.0 Authorization Server metadata is obtained from the `oauth-authorization-server` well-known location as defined in Section 3 of [@!RFC8414]. When there are multiple entries in the array, the Wallet may be able to determine which Authorization Server to use by querying the metadata; for example, by examining the `grant_types_supported` values, the Wallet can filter the server to use based on the grant type it plans to use. When the Wallet is using `authorization_server` parameter in the Credential Offer as a hint to determine which Authorization Server to use out of multiple, the Wallet MUST NOT proceed with the flow if the `authorization_server` Credential Offer parameter value does not match any of the entries in the `authorization_servers` array.
* `credential_endpoint`: REQUIRED. URL of the Credential Issuer's Credential Endpoint, as defined in (#credential-request). This URL MUST use the `https` scheme and MAY contain port, path, and query parameter components.
* `nonce_endpoint`: OPTIONAL. URL of the Credential Issuer's Nonce Endpoint, as defined in (#nonce-endpoint). This URL MUST use the `https` scheme and MAY contain port, path, and query parameter components. If omitted, the Credential Issuer does not support the Nonce Endpoint.
* `deferred_credential_endpoint`: OPTIONAL. URL of the Credential Issuer's Deferred Credential Endpoint, as defined in (#deferred-credential-issuance). This URL MUST use the `https` scheme and MAY contain port, path, and query parameter components. If omitted, the Credential Issuer does not support the Deferred Credential Endpoint.
* `notification_endpoint`: OPTIONAL. URL of the Credential Issuer's Notification Endpoint, as defined in (#notification-endpoint). This URL MUST use the `https` scheme and MAY contain port, path, and query parameter components. If omitted, the Credential Issuer does not support the Notification Endpoint.
* `credential_response_encryption`: OPTIONAL. Object containing information about whether the Credential Issuer supports encryption of the Credential Credential Response on top of TLS.
Expand Down Expand Up @@ -2206,16 +2244,6 @@ This specification registers the following parameter names in the IANA "OAuth Pa
* Change Controller: OpenID Foundation Digital Credentials Protocols Working Group - [email protected]
* Reference: (#token-request) of this specification

* Parameter Name: c_nonce
* Parameter Usage Location: token response
* Change Controller: OpenID Foundation Digital Credentials Protocols Working Group - [email protected]
* Reference: (#token-response) of this specification

* Parameter Name: c_nonce_expires_in
* Parameter Usage Location: token response
* Change Controller: OpenID Foundation Digital Credentials Protocols Working Group - [email protected]
* Reference: (#token-response) of this specification

## OAuth Dynamic Client Registration Metadata Registry

This specification registers the following client metadata name in the IANA "OAuth Dynamic Client Registration Metadata" registry [@!IANA.OAuth.Parameters] established by [@!RFC7591].
Expand Down Expand Up @@ -2327,6 +2355,8 @@ The technology described in this specification was made available from contribut
* Define Credential Dataset as a term
* Define Credential Configuration as a term
* remove use of the `authorization_pending` and `slow_down` error codes
* removed `c_nonce` and `c_nonce_expires_in` from the token endpoint response
* added a Nonce Endpoint where a Client can acquire a fresh c_nonce value without the overhead of a full Credential Request

-13

Expand Down