openid / OpenID4VCI

64 stars 18 forks source link

Double user authorization #282

Closed fabrii closed 5 months ago

fabrii commented 6 months ago

Is it possible for an issuer to require double authorization?

For example:

This way, they would be able to increment the security in the process. Is this something that can be implemented with the current specification?

Thank you

jogu commented 6 months ago

Yes, this is possible, but rather than a pre-authorised code you should take the option in https://openid.github.io/OpenID4VCI/openid-4-verifiable-credential-issuance-wg-draft.html#name-credential-offer-parameters of using issuer_state and the authorization_code grant.

fabrii commented 6 months ago

Understood! Thank you @jogu !

fabrii commented 6 months ago

I have one more question related to authorization and token endpoints. What if the authorization endpoint is from an external OAuth Identity Provider that does not support issuer_state parameter. Is it possible to send the issuer_state to the token endpoint provided by the Issuer instead?

babisRoutis commented 6 months ago

I have one more question related to authorization and token endpoints. What if the authorization endpoint is from an external OAuth Identity Provider that does not support issuer_state parameter. Is it possible to send the issuer_state to the token endpoint provided by the Issuer instead?

If your OAUTH2 server doesn't support issuer_state, I don't think that it would support accepting additional parameters to token endpoint, either. Anyway, sending issuer_state to token endpoint it is not described in VCI, to answer your question.

I have the impression, though, that, irrelevant to the VCI protocol, your use case requires a VCI capable OAUTH2 server.

In the absence of such a server, typically you can use VCI with authorization code flow, probably not using issuer_state and/or authorization_details.

jogu commented 6 months ago

I have one more question related to authorization and token endpoints. What if the authorization endpoint is from an external OAuth Identity Provider that does not support issuer_state parameter. Is it possible to send the issuer_state to the token endpoint provided by the Issuer instead?

I don't think it would be advised to mix and match authorization endpoints and token endpoints like that.

If you federate out from your AS to the external AS (like a google signin), there is no need for that external AS to support issuer_state in order for your own AS to support issuer state. But in that case the authorization endpoint that external clients see if your authorisation endpoint, which then redirects to the google authorization endpoint to do the authentication before continuing on with collecting consent from the user before returning the authorization code.

Sakurann commented 6 months ago

federating to the external AS does not always work, because AS of larger companies might require the usage of a specific library by the client which does not support VCI... I am not sure about this idea yet and this behavior is not defined in VCI rn, but would it be possible to pass pre-authorized code received in credential offer in login_hint authorization request parameter defined in https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest? I don't like the mismatch of oauth and oidc, and but existing AS are probably more likely to support login_hint than issuer_state.

fabrii commented 6 months ago

I had something like this in mind:

diagrama_login drawio

Do you see any security issues with this approach? With this option, the issuer only needs the Token endpoint, without needing to implement a full OAuth2 server. Since the issuer has full control of the token endpoint, it could receive the preauthorized code as another parameter.

About OAuth2 federation, do you mean something like this?

diagrama_login2 drawio

babisRoutis commented 6 months ago

Dear @fabrii

Your 1st flow is not part of the VCI. It suggests that you can request from the token endpoint a grant_type equal to authorization_code but at the same time pass also a pre-authorized code parameter (which requires a different grant type)

Returning to your initial post: I get the impression that your use case requires some kind of higher level of assurance during authorization. IMO, this is an authorization requirement, not related to VCI per se and perhaps it can be implemented in the authorization server (for instance by requiring 2FA or federating with another IdP etc). Especially federation could be transparent for your wallet. For instance check Keycloak

jogu commented 6 months ago

Do you see any security issues with this approach? With this option, the issuer only needs the Token endpoint, without needing to implement a full OAuth2 server.

It is hard to give a full answer to that question. But I think it will ultimately become impossible to implement some features of the spec in a model like that. Fundamentally taking an authorization code from one authorization server and passing it to the token endpoint of what is essentially a different authorization server is not something OAuth2 was intended to support.

Since the issuer has full control of the token endpoint, it could receive the preauthorized code as another parameter.

As Babis says, that would be a proprietary extension and not interoperable.

About OAuth2 federation, do you mean something like this?

Yes, exactly. That is the standard model for integrating an authorization server with an external authorization server.

fabrii commented 6 months ago

In our case, the pre-authorized code would be stored in the issuer's database, associated with a business entity. In this first stage of verifiable credentials adoption, we are trying to simplify the implementation curve of issuers, so it would be easier for them to join. Adding a customized Keycloak to the architecture (of each issuer?) and validating the "pre-authorized code" at authorization level seems not to be a simple task.

Looking closer, it looks like my first flow is closer to "Google Sign-in" than OAuth2. I personally think in our case we would need to add a proprietary extension for now, to validate this code at token endpoint or credential issuance endpoint (both provided by the issuer). See also https://github.com/openid/OpenID4VCI/issues/21.

babisRoutis commented 6 months ago

Dear @fabrii I don't clearly understand what is the problem you are trying to solve.

It seems that you have identified that spec-wise in your case it is the pre-authorized flow that fits best.

To realize such an issuance process you have the following basic options:

  1. Use an OAUTH2 server that implements pre-authorized flow & implement the credential issuer yourself
  2. Use an OAUTH2 server that implements pre-authorized flow & Credential Issuer
  3. Create your own OAUTH2 server & Credential Issuer

Taking into account the present state of the spec (no implementers draft yet, but close) and the present state of OAUTH2 servers , the implementation of pre-authorized flow could be very "challenging" (depending on your time frame, of course).

Perhaps, it would be better to consider the authz code flow, instead, if possible. For instance, think the following steps:

The above will trigger two logins

Usually, this is the price that you have to pay in the absence of pre-authorized code flow, but judging from the title of this issue it seems that this could be desirable in your case.

fabrii commented 6 months ago

Hi @babisRoutis

I'll give you additional context about the scenario:

About pre-authorized flow in the spec:

It is important to note that anyone who possesses a valid Pre-Authorized Code, without further security measures, would be able to receive a VC from the Credential Issuer. Implementers MUST implement mitigations most suitable to the use case.

Given the circunstances of our case, why not asking both mechanisms? This is, pre-authorized code of issuer, plus authorization code against the identity provider.

jogu commented 6 months ago

Given the circunstances of our case, why not asking both mechanisms? This is, pre-authorized code of issuer, plus authorization code against the identity provider.

Having two authorization codes (one pre-authorised, one not) is fundamentally a violation of OAuth2. There's no sensible way I can see that we could accommodate it in the spec.

babisRoutis commented 6 months ago

Hi @fabrii Thanks for providing the additional context.

Let's assume that - during the visit to the issuer office - issuer stores in its DB an indication that the person X is indeed entitled to a specific VC. It is exactly what you describe, except that I don't use the term "pre-authorized code".

In this case, Issuer could implement just the credential issuance service protected by an ordinary OAUTH2 server, which should support delegating login to a federated IdP.

Process could be, indicatively:

For me this just a standard VCI authz code flow that happens to use a federated IdP. I just didn't use the term "pre-authorized code".

fabrii commented 6 months ago

@babisRoutis

In your flow, the issuer must trust the Identity Provider 100% to obtain the person's identity. I think that would be the case for the vast majority of issuers. I am thinking of some specific cases of very important credentials where the issuer might want to increase the security of the process by doing a double check by generating also a "security code" and offering it through a credential offer.

@jogu I get that doing this is not compatible to OAuth2. I now understand the OAuth2 perspective in this matter.

Thank you both