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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
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
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.

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

My naive feeling that using a GET to get some data is the most straightforward way to get some data remained unchanged by that discussion over the course of the last two weeks.

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.

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)).
Copy link
Member

Choose a reason for hiding this comment

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

I suggest to rename c_nonce to nonce, making the nonce endpoint of general purpose. A nonce is issued by an entity for a specific scope known to its issuer, we don't need to use a particular member name to say that it is a credential nonce, it's a only nonce

nonce and nonce_expires_in would be enough from my perspective, allowing the nonce endpoint to be a general and reusable endpoint within the OAuth framework

Copy link
Member Author

@bc-pi bc-pi Sep 19, 2024

Choose a reason for hiding this comment

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

A general and reusable endpoint within the OAuth framework was in no way a goal of this work. Not at all.

And I used c_nonce (a name that I honestly think is terrible for many reasons) to allow for this PR to fit into the broader document more easily and with less risk.

Copy link
Member

Choose a reason for hiding this comment

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

Okay, since this Nonce Endpoint is specifically tailored for credential issuance within the sole scope of the OpenID4VCI specs, it would make sense to rename the endpoint metadata parameter from nonce_endpoint to credential_nonce_endpoint.

In this way, other nonce endpoints created for other OpenID/IETF specs will not collide with this one.
The related section should therefore be renamed to "Credential Nonce Endpoint," adding "Credential" as a prefix to contextualize its scope.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't have any opinion on the metadata name yet, but:

In this way, other nonce endpoints created for other OpenID/IETF specs will not collide with this one.

I'm not sure I see any danger of collision with IETF specs - the new endpoint is only present in the credential issuer metadata, so I can't imagine IETF would ever start defining values in there.

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 @jogu points out (thanks @jogu!) there is no problem with collision because this endpoint is at the credential issuer.

This seems to be in the same vein of what I said about this in slack to you @peppelinux yesterday but bears repenting, "the context is totally different."

Copy link
Member

Choose a reason for hiding this comment

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

bo-ring :-)

Copy link
Member

Choose a reason for hiding this comment

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

I menat IANA metadata registry

https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml

OAuth Authorization Server Metadata

nonce_endpoint might collide over there, yes different contexts (openid != IETF) but if this endpoint is specialized for credential issuance it would be better to give to it a name pointing exactly and esplicitly in this way

Copy link
Member Author

Choose a reason for hiding this comment

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

that context is still totally different

Copy link
Member Author

@bc-pi bc-pi Sep 24, 2024

Choose a reason for hiding this comment

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

after a maybe productive but definitely not appropriate side discussion about this over in slack - I think Giuseppe and I can agree to disagree

Copy link
Contributor

Choose a reason for hiding this comment

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

I menat IANA metadata registry

https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml

OAuth Authorization Server Metadata

nonce_endpoint might collide over there, yes different contexts (openid != IETF) but if this endpoint is specialized for credential issuance it would be better to give to it a name pointing exactly and esplicitly in this way

Just to try to clarify, the nonce endpoint here is part of the issuer metadata. We will not be making an IANA registration for nonce_endpoint in the OAuth Authorization Server Metadata because we're not defining a nonce endpoint for the authorization server. The suggested nonce_endpoint is (technically) a resource server endpoint as that's how we define the credential issuer.

Adding nonce_endpoint here would not prevent the OAuth WG defining a nonce endpoint for authorization servers, nor would it conflict with any such endpoint. It also wouldn't stop the OAuth WG defining a general nonce endpoint for resource servers should they choose to do so, as resource server metadata would also not have a name space that overlaps with credential issuer metadata (i.e. you could have a nonce endpoint defined in .well-known/oauth-resource server and a potentially different nonce endpoint defined in /.well-known/openid-credential-issuer.

* `c_nonce_expires_in`: OPTIONAL. Number denoting the lifetime in seconds of the `c_nonce`. This value serves only as a hint to the client, indicating how long the Credential Issuer is likely to accept the `c_nonce` as valid.
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`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps this text could be a bit more lenient, namely to allow cases where the same c_nonce can be cached for a small amount of time (via the max-age value on the Cache-Control).

Suggested change
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`.
Due to the temporal and contextually sensitive nature of the `c_nonce` value, the Credential Issuer MUST explicitly define the allowed caching for the response, for instance by adding the `Cache-Control` header with the `no-store` value, if the response must be uncacheable.

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 don't think that should be accounted for at the HTTP layer of cache.

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 mean, sure the client will hold onto the thing so it can use it on a subsequent credential request but that's not something that should be conveyed at the HTTP cache level.

Copy link
Contributor

@nemqe nemqe Sep 20, 2024

Choose a reason for hiding this comment

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

if we allow max-age I think we just define the nonce_expires_in on an HTTP level

Copy link
Member Author

Choose a reason for hiding this comment

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

or not at any level #394

Copy link
Member Author

Choose a reason for hiding this comment

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

by which i mean, it's not appropriate at the HTTP layer and it's not needed at the application layer so why have it at all?


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