openid / OpenID4VCI

68 stars 20 forks source link

(presentation during issuance) Native Implementation of Authorisation End Point #360

Open ranjivaprasadvisa opened 4 months ago

ranjivaprasadvisa commented 4 months ago

Problem Statement:

A user holds a financial account with a payment service provider (PSP). They also hold a European Digital Identity wallet (EUDIW). They would like to use their EUDIW instance to authenticate transactions made against their account, in line with European PSD2 Secure Customer Authentication (SCA) regulation. To do so their PSP must issue a credential into their EUDIW instance for that account. This will be presented back to the PSP when the user is requested to authenticate a transaction made against the account at a later point in time.

Before the PSP issues the credential, it may wish to verify that the wallet holder is the account holder and whether the user’s EUDIW instance has the technical capabilities to act as an authenticator.

The user may start the credential issuance flow from their EUDIW instance or from their PSP app / portal. To simplify implementation, we would like to use an authorisation code flow for both, rather than using a pre-authorised code flow when the journey starts in the PSP. In both cases, the authorisation code flow requires credential issuance with a dynamic credential request.

The PSP can only make the dynamic credential request after it receives an authorisation request from the wallet. This creates a UX challenge when the authorisation code flow starts in the PSP app / portal. In this scenario, the user has authenticated into the PSP app / portal and selected the account(s) for which they wish a credential(s) to be issued. To make the dynamic credential request, the PSP must open the EUDIW instance (by sending a credential offer) before the EUDIW instance can send the user agent to the PSP authorisation request end point. The PSP can then make the dynamic credential request by returning the user to the EUDIW instance.

In the process, the user is taken from the PSP app / portal to the EUDIW instance and then to the PSP authorisation end point before returning to the EUDIW instance. Given that the user has already authenticated to the PSP and already provided consent for the credential by selecting account(s), there is no further user action required at the PSP authorisation end point. The user may therefore be confused as to why they have returned to the PSP and so managing user expectations at the authorisation end point will be challenging. Furthermore this sequence of steps is particularly cumbersome for the user to follow in a cross-device scenario.

Possible solution approach:

This issue can be avoided by removing the requirement for the EUDIW instance to send the user agent to the authorisation end point before the PSP can make a dynamic credential request. Instead, the PSP should provide a “native” implementation of the authorisation end point that the EUDIW instance can call directly without any change to the user agent’s location. The following draft may offer such a native implementation.

https://datatracker.ietf.org/doc/html/draft-parecki-oauth-first-party-apps-01

The draft describes the concept of an intermediate request which appears to be a mechanism for implementing the dynamic credential request. In this implementation, the PSP authorisation end point returns an insufficient authorisation error that informs the EUDIW instance on which credentials are needed by the PSP. The insufficient authorisation error could contain an authorisation request object that describes the credentials required.

jogu commented 4 months ago

Hi Ranjiva, thanks for opening this.

This flow is quite difficult to follow - do you have a sequence diagram that shows it?

We are already thinking about potentially referencing https://datatracker.ietf.org/doc/html/draft-parecki-oauth-first-party-apps-01 for cases people have raised where it is only possible for a native app wallet (and not a website) to collect information that an issuer needs - e.g. an issuer website generally can't read a document such as a passport via NFC - I'm not sure if we got as far as opening an issue for that though.

ranjivaprasadvisa commented 4 months ago

Hi Joseph, please find here. I include the sequence diagram highlighting the UX challenge and a sequence diagram for the desired solution

Issue 360 Sequence Diagrams
jogu commented 4 months ago

Thanks Ranjiva! That makes sense.

I think there's quite a lot of overlap with https://github.com/openid/OpenID4VCI/issues/20 - in particular Kristina's comment from 2 weeks ago - do you agree?

ranjivaprasadvisa commented 4 months ago

Hi Joseph, I had discussed this issue with Kristina a few weeks ago and she made me aware of https://github.com/openid/OpenID4VCI/issues/20. As the issue was opened a while ago, rather than adding a comment to the issue, I had informed her that I would raise a separate issue to give more detail on how this issue arises in the context of our payment use cases for the EU Digital Identity Wallet, so that the DCP WG was clear on the problem. But yes, this is closely related to https://github.com/openid/OpenID4VCI/issues/20. Indeed it appears that Kristina in her comment has summarised the issue nicely following my conversation with her!

Sakurann commented 3 months ago

had a chat with first party app draft document editors: https://github.com/aaronpk/oauth-first-party-apps/issues/110 few questions open but direction seems clear

vincentkelleher commented 4 weeks ago

Hi 👋

We, the Gaia-X Lab Team, are currently working on Dynamic Credential Request to be able to request credentials during the issuance flow.

Managing separate authorization requests and redirections during a single issuance flow phase is very complicated from an implementer's point of view. I stumbled upon this issue as it is linked to #20 and I'm relieved to see I'm not the only one having some difficulties with this.

I'm not familiar with the OAuth 2.0 for First-Party Applications specification but from what I understand, the idea would be to respond with a 400 Bad Request status and a specific error code to require the wallet to provide additional credentials.

Did I understand this correctly ?

To give you more background about our use case, we aren't aiming for a smartphone natural person's wallet but more of a cloud legal person's wallet hosted on a server. Our goal is to enable machine-to-machine credential issuance and verification and the case in the #20 issue is the last one remaining to have a full implementation of our goal.

Thank you for your help 🙌

jogu commented 4 weeks ago

@vincentkelleher yes, your understanding matches mine.

Sakurann commented 4 weeks ago

@vincentkelleher we needed this for a German wallet project and here is our design. would love your feedback: https://bmi.usercontent.opencode.de/eudi-wallet/eidas-2.0-architekturkonzept/flows/Presentation-During-Issuance/

vincentkelleher commented 4 weeks ago

@Sakurann I had a look at your design and we have the same idea (@ranjivaprasadvisa too as mine is inspired from his) 👍 I'm not familiar with some specific elements of your design such as auth_session but the overall idea is compatible.

On my side I was imagining something like the flow below for the OID4VCI authorization flow with dynamic credential request.

mermaid-diagram-2024-10-24-172832

As you can see, my design is very specific to the solution I'm implementing, a cloud wallet with some OAuth/OID4VC extensions like RFC 9101 The OAuth 2.0 Authorization Framework: JWT-Secured Authorization Request (JAR), direct_post.jwt response mode, etc.

The idea of my flow is to be able to use the Wallet's /authorize-redirect endpoint normally unless there is a missing_credentials error.

The Issuer would have an /authorize authorization endpoint and and new /missing-credentials endpoint that would only be used to present required credentials, it would then redirect the wallet with an authorization code just like a normal authorization code flow. The missing credentials endpoint could also be the same as the authorize endpoint with a different behavior depending on the query parameters 😇

Please note that all endpoint names are arbitrary and for example purposes 😉

vincentkelleher commented 4 weeks ago

@Sakurann as I was moving on with the implementation of my design idea, I noticed that I was missing some information the missing_credentials error response and the /missing-credentials request to be able to use the same redirect URI as the initial authorization request.

image

I first thought of adding a code, state or identifier to the error response to track the redirect URI but that's when I remembered your design's auth_session additional OID4VC parameter 💡

The fact that multiple parties think of a similar solution indicates (from my point of view) that this might be the right direction to go towards 👍

Sakurann commented 3 weeks ago

@vincentkelleher the design I posted in my previous comments extends IETF OAuth First Party Apps draft and auth_session parameter is defined in that draft.

I think the design we have have slight advantage:

with our design, the wallet will have an option to send a first authorization request either through the browser or as an HTTP POST; the wallet can discover whether the issuer supports this new approach using issuer metadata and decide. we could also introduce signals (either in the credential offer or issuer metadata) that the issuer can use to indicate to the wallet that it would prefer the wallet uses authorization challenge request.

cre8 commented 3 weeks ago

I think the signal option is good, because it allows the issuer to use the current "native" auth flow and in parallel the first party apps spec with the new endpoint.