openid / OpenID4VCI

68 stars 19 forks source link

Clarification about passing issuer and authorization server state #379

Open edouardhue opened 2 months ago

edouardhue commented 2 months ago

Authorization Code flow defines an issuer_state parameter that is to be sent back by the Wallet to the AS in an Authorization Request and Pre-Authorized Code flow defines a pre-authorized_code parameter to be sent back by the Wallet to the AS in a Token Request.

issuer_state: OPTIONAL. String value identifying a certain processing context at the Credential Issuer. A value for this parameter is typically passed in a Credential Offer from the Credential Issuer to the Wallet (see Section 4.1). This request parameter is used to pass the issuer_state value back to the Credential Issuer. pre-authorized_code: REQUIRED. The code representing the Credential Issuer's authorization for the Wallet to obtain Credentials of a certain type. This code MUST be short lived and single use. If the Wallet decides to use the Pre-Authorized Code Flow, this parameter value MUST be included in the subsequent Token Request with the Pre-Authorized Code Flow.

While it seems logical that the pre-authorized code is handled by the AS, it is not so obvious why the issuer state is to be sent to the AS in an Authorization Request instead of to the Issuer itself.

Also, it is surprising that there is no way for the Issuer to provide an issuer_state in the Pre-Authorized Code flow. One could think of the pre-authorized code as a handle to some kind of a pre-authorized Authorization Request that itself holds an issuer state, but the spec makes no mention of this and the way for the Issuer to obtain the code is unspecified.

I think the state references carried through Credential Offer parameters should be clarified and reworked:

Maybe this would clarify and separate the roles of the AS and the Issuer.

jogu commented 2 months ago

Hi @edouardhue

Thanks for raising this! I had a check and can't find a contribution agreement on record for you, if you have completed one could you confirm when and under what name, and if not please complete one at https://openid.net/intellectual-property/openid-foundation-contribution-agreements/

I believe the reason there's no issuer_state in the pre-auth code flow is that it's assumed any required state is embedded in or accessible via looking up the pre authorised code.

The reason the issuer state is sent in the authorization is I believe that it's required by the authorization server to collect correct user consent and/or to know what permissions/other info to include in the access token, and because it can be embedded in the access token it's then not required to be passed to the credential issuer (and in fact to pass it there introduces new possible security issues).

fabrii commented 2 months ago

Hi @jogu and @edouardhue

I have one more related question to this topic.

I believe the reason there's no issuer_state in the pre-auth code flow is that it's assumed any required state is embedded in or accessible via looking up the pre authorised code.

In the specification we can see the following:

This specification enables deployments where the Credential Issuer API and the Authorization Server are different services, perhaps even provided by different entities.

The pre-authorised code is by definition generated by the issuer. What if the AS is provided by a different entity? How can this AS validate the pre-authorized code if it does not have access to the issuer's data?

Thank you

jogu commented 2 months ago

@fabrii

What if the AS is provided by a different entity? How can this AS validate the pre-authorized code if it does not have access to the issuer's data?

For the most part the answer is the same as with classic OAuth - there needs to be some kind of agreement in place between the AS and the RS, e.g. the AS has to be aware of the capabilities of the RS in terms having some 'scope' values defined that have the same meaning to both the AS & the RS so the AS can meaningfully ask the user for consent, and the RS has to know how to validate access tokens issued by the AS.

To the particular question you asked, if the AS used for the authorization code flow doesn't have support for pre-authorised codes (which would generally necessitate it having a way for the credential issuer to generate or be issued with pre authorised codes) the solution I believe other implementors have solved this by having a second separate AS for handling pre-authorised codes.

fabrii commented 2 months ago

If I understand correctly, the following approach would be allowed by the standard for this use-case:

The issuer_state and/or pre-authorised code should be embedded inside the access tokens generated by both AS. Then, this state/code can be used in the Credential Request method.

Validating tokens generated by a third party AS is simple from the issuer's perspective, as they only need access to the jwks endpoint. Doing some kind of integration between a third party AS and N issuers for validating pre-authorised codes does not seem to scale well.

edouardhue commented 2 months ago

Hi @jogu and @fabrii,

I confirm there is no contribution agreement from me yet. This might take time to complete as corporate bureaucracy is involved :wink:

The approach we are considering is one shared, general-purpose Issuer and several "delegated" custom AS that should be able to engage in both "classic" Authz Code and new Pre-Authz Code flows. Hence we are concerned about strong coupling, state-sharing and implicit data flows between Issuer and AS.

I'll get back with proposals as soon as IPR issues are solved…

jogu commented 2 months ago

Great, thanks @edouardhue

FYI there was a previous dicussion on a topic I think is similar that it might be worth reading: https://github.com/openid/OpenID4VCI/issues/79