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

Specification is missing examples for request objects #78

Open
paulbastian opened this issue Jan 14, 2024 · 6 comments · May be fixed by #218
Open

Specification is missing examples for request objects #78

paulbastian opened this issue Jan 14, 2024 · 6 comments · May be fixed by #218

Comments

@paulbastian
Copy link
Contributor

For the actual Authorization Request there are currently three main options:

  1. passing as URL with encoded parameters
  2. passing a request object as value
  3. passing a request object per reference (request_uri)

To my knowledge, the majority of implementations are currently favoring option 3. However, the specification does not offer examples for option 2 and three, which would be useful for new people.

Additionally, listing the three options in the start of Section 5 might be helpful.

@deshmukhrajvardhan
Copy link
Contributor

QQ: @Sakurann @paulbastian
I couldn't find references to "passing a request object as value"
For 1 and 3, are these examples right?

  1. passing as URL with encoded parameters
GET /authorize?
  response_type=vp_token
  &client_id=https%3A%2F%2Fclient.example.org%2Fcb
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  &presentation_definition=...
  &nonce=n-0S6_WzA2Mj HTTP/1.1
  1. passing a request object per reference (request_uri)
GET /authorize?
  client_id=client.example.org
  &client_id_scheme=x509_san_dns
  &client_metadata=...
  &request_uri=https%3A%2F%2Fclient.example.org%2Frequest%2Fvapof4ql2i7m41m68uep
  &request_uri_method=post HTTP/1.1

later

POST /request HTTP/1.1
Host: client.example.org
Content-Type: application/x-www-form-urlencoded

wallet_metadata=%7B%22vp_formats_supported%22%3A%7B%22jwt_vc_json%22%3A%7B%22alg_values_supported
%22%3A%5B%22ES256K%22%2C%22ES384%22%5D%7D%2C%22jwt_vp_json%22%3A%7B%22alg_values_supported%22%3A%
5B%22ES256K%22%2C%22EdDSA%22%5D%7D%7D%7D&
wallet_nonce=qPmxiNFCR3QTm19POc8u

@jogu
Copy link
Collaborator

jogu commented Jul 16, 2024

Yes, those examples are correct for cases 1 & 3.

I'd agree we are missing an example only for case '2' now.

@deshmukhrajvardhan
Copy link
Contributor

deshmukhrajvardhan commented Jul 16, 2024

@jogu Thanks for verifying!
I searched through https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#name-response-mode-direct_post and https://www.rfc-editor.org/rfc/rfc6749.html#section-4
but didn't find the use of request object by value.

I finally found it here https://openid.net/specs/openid-connect-core-1_0.html#RequestObject
in the use of request parameter in the url.

Request object

{
   "iss": "s6BhdRkqt3",
   "aud": "https://server.example.com",
   "response_type": "code id_token",
   "client_id": "s6BhdRkqt3",
   "redirect_uri": "https://client.example.org/cb",
   "scope": "openid",
   "state": "af0ifjsldkj",
   "nonce": "n-0S6_WzA2Mj",
   "max_age": 86400,
   "claims":
    {
     "userinfo":
      {
       "given_name": {"essential": true},
       "nickname": null,
       "email": {"essential": true},
       "email_verified": {"essential": true},
       "picture": null
      },
     "id_token":
      {
       "gender": null,
       "birthdate": {"essential": true},
       "acr": {"values": ["urn:mace:incommon:iap:silver"]}
      }
    }
  }

The request object is base64url-encoded and signed (in the example with RS256 algo) and that result is put into the request parameter

GET /authorize?
    response_type=vp_token
    &client_id=s6BhdRkqt3
    &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
    &scope=openid
    &state=af0ifjsldkj
    &nonce=n-0S6_WzA2Mj
    &request=eyJhbGciOiJSUzI1NiIsImtpZCI6ImsyYmRjIn0.ew0KICJpc3MiOiA
    iczZCaGRSa3F0MyIsDQogImF1ZCI6ICJodHRwczovL3NlcnZlci5leGFtcGxlLmN
    vbSIsDQogInJlc3BvbnNlX3R5cGUiOiAiY29kZSBpZF90b2tlbiIsDQogImNsaWV
    udF9pZCI6ICJzNkJoZFJrcXQzIiwNCiAicmVkaXJlY3RfdXJpIjogImh0dHBzOi8
    vY2xpZW50LmV4YW1wbGUub3JnL2NiIiwNCiAic2NvcGUiOiAib3BlbmlkIiwNCiA
    ic3RhdGUiOiAiYWYwaWZqc2xka2oiLA0KICJub25jZSI6ICJuLTBTNl9XekEyTWo
    iLA0KICJtYXhfYWdlIjogODY0MDAsDQogImNsYWltcyI6IA0KICB7DQogICAidXN
    lcmluZm8iOiANCiAgICB7DQogICAgICJnaXZlbl9uYW1lIjogeyJlc3NlbnRpYWw
    iOiB0cnVlfSwNCiAgICAgIm5pY2tuYW1lIjogbnVsbCwNCiAgICAgImVtYWlsIjo
    geyJlc3NlbnRpYWwiOiB0cnVlfSwNCiAgICAgImVtYWlsX3ZlcmlmaWVkIjogeyJ
    lc3NlbnRpYWwiOiB0cnVlfSwNCiAgICAgInBpY3R1cmUiOiBudWxsDQogICAgfSw
    NCiAgICJpZF90b2tlbiI6IA0KICAgIHsNCiAgICAgImdlbmRlciI6IG51bGwsDQo
    gICAgICJiaXJ0aGRhdGUiOiB7ImVzc2VudGlhbCI6IHRydWV9LA0KICAgICAiYWN
    yIjogeyJ2YWx1ZXMiOiBbInVybjptYWNlOmluY29tbW9uOmlhcDpzaWx2ZXIiXX0
    NCiAgICB9DQogIH0NCn0.nwwnNsk1-ZkbmnvsF6zTHm8CHERFMGQPhos-EJcaH4H
    h-sMgk8ePrGhw_trPYs8KQxsn6R9Emo_wHwajyFKzuMXZFSZ3p6Mb8dkxtVyjoy2
    GIzvuJT_u7PkY2t8QU9hjBcHs68PkgjDVTrG1uRTx0GxFbuPbj96tVuj11pTnmFC
    UR6IEOXKYr7iGOCRB3btfJhM0_AKQUfqKnRlrRscc8Kol-cSLWoYE9l5QqholImz
    jT_cMnNIznW9E7CDyWXTsO70xnB4SkG6pXfLSjLLlxmPGiyon_-Te111V8uE83Il
    zCYIb_NMXvtTIVc1jpspnTSD7xMbpL-2QgwUsAlMGzw

The following RSA public key, represented in JWK format, can be used to validate the Request Object signature in this and subsequent Request Object examples.

{
   "kty":"RSA",
   "kid":"k2bdc",
   "n":"y9Lqv4fCp6Ei-u2-ZCKq83YvbFEk6JMs_pSj76eMkddWRuWX2aBKGHAtKlE5P
        7_vn__PCKZWePt3vGkB6ePgzAFu08NmKemwE5bQI0e6kIChtt_6KzT5OaaXDF
        I6qCLJmk51Cc4VYFaxgqevMncYrzaW_50mZ1yGSFIQzLYP8bijAHGVjdEFgZa
        ZEN9lsn_GdWLaJpHrB3ROlS50E45wxrlg9xMncVb8qDPuXZarvghLL0HzOuYR
        adBJVoWZowDNTpKpk2RklZ7QaBO7XDv3uR7s_sf2g-bAjSYxYUGsqkNA9b3xV
        W53am_UZZ3tZbFTIh557JICWKHlWj5uzeJXaw",
   "e":"AQAB"
  }

Q How is this public key shared? My best guess is that it can be accessed via https://<server_domain>/.well-known/jwks.json. i.e. the client gets keys from the authorization server and uses it to create the content of request and authorize endpoint server verifies the signature whit its private key. Can they be included in the request too?

Q Is there a schema for attributes of the Request object?

I included the ones used in the "passing as URL with encoded parameters" case.
I intend to use this json for the Request object example in the PR:

{
   "iss": "s6BhdRkqt3",
   "aud": "https://server.example.com",
   "response_type": "vp_token",
   "client_id": "https://client.example.org/cb",
   "redirect_uri": "https://client.example.org/cb",
   "scope": "openid",
   "state": "af0ifjsldkj",
   "nonce": "n-0S6_WzA2Mj",
   "max_age": 86400,
   "presentation_definition":{...},
  }

Reasons request object by value isn't popular make sense to me https://openid.net/specs/openid-connect-core-1_0.html#RequestUriRationale , I might point to this and mention it while describing the example.

@jogu
Copy link
Collaborator

jogu commented Jul 17, 2024

It's generally better to use https://www.rfc-editor.org/rfc/rfc9101.html as the reference rather than the OpenID Connect specification - RFC9101 is an updated newer version of what's in OpenID Connect. In particular in the OAuth version there is much less data passed outside the signed request object, so the example would become:

GET /authorize?
    client_id=s6BhdRkqt3
    &request=eyJhbGc<...>

Q How is this public key shared? My best guess is that it can be accessed via https://<server_domain>/.well-known/jwks.json. i.e. the client gets keys from the authorization server and uses it to create the content of request and authorize endpoint server verifies the signature whit its private key. Can they be included in the request too?

Including the public keys in the request (without some way to confirm their authenticity) would not result in any benefit to using a signed request.

The way the keys can be obtained/passed varies depending on which client_id_scheme is in used, see https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#client_metadata_management

In the above case, as there is no client_id_scheme passed it is assumed the keys/clientid have been pre-registered with the wallet. (This isn't a likely case in the real world. For example when you use mobile driving licenses you always use client_id_scheme=x509_san_dns)

(The mechanism you describe of getting a public key from the AS jwks uri [which would be found via .well-known/openid-configuration or .well-known/oauth-authorization-server] would only be applicable for encryption - for signing the client must communicate it's own public key to the AS somehow)

Q Is there a schema for attributes of the Request object?

In general it's the same attributes that you could use in an unsigned request, plus the standard JWT claims (iss, aud, exp). https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#parameters is the definitive list (but doesn't contain VP specific items like presentation_definition yet), in particular the items tagged with 'authorization request' as the location.

For the example it makes sense to work from one we already have. So taking this example:

GET /authorize?
  response_type=vp_token
  &client_id=https%3A%2F%2Fclient.example.org%2Fcb
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  &presentation_definition=...
  &nonce=n-0S6_WzA2Mj HTTP/1.1

turning this into a request object the payload would be:

{
  "iss": "s6BhdRkqt3",
  "aud": "https://self-issued.me/v2",
  "response_type": "vp_token",
  "client_id": "https://client.example.org/cb",
  "redirect_uri": "https%3A%2F%2Fclient.example.org%2Fcb",
  "presentation_definition": "...",
  "nonce": "n-0S6_WzA2Mj"
}

(and probably iat / exp too)

@deshmukhrajvardhan deshmukhrajvardhan linked a pull request Jul 17, 2024 that will close this issue
4 tasks
@deshmukhrajvardhan
Copy link
Contributor

Observation:

  1. response_type is REQUIRED in Authorization request as per https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.1
    I plan to follow that and set them to vp_token in the 3 examples.

  2. There are 2 stray examples at the end of https://openid.github.io/OpenID4VP/openid-4-verifiable-presentations-wg-draft.html#name-authorization-request , i plan to remove them as they will be duplicates.

Thanks!

Here is the PR #218
I used https://jwt.io/ to create the signed and encoded payload for request.
Paste the payload in there to decode it and verify the signature

@jogu
Copy link
Collaborator

jogu commented Jul 18, 2024

response_type is REQUIRED in Authorization request as per https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.1
I plan to follow that and set them to vp_token in the 3 examples.

I can see how you got there, but response_type must be present inside the request object and as per https://www.rfc-editor.org/rfc/rfc9101.html#section-5 does not need to be present outside the request object. Only client_id and request/request_uri (and by inference optionally client_id_scheme I think) are passed in the query parameters.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants