OID4VCI: Enable issuance of the same credential type

Issue #1923 resolved
Emmanouil Koukoularis created an issue

As per our discussion with the authors of the OpenID4VCI specification last month, we are opening this issue to formally address the challenges that were discussed.

Throughout the course of implementation of the OpenID for Verifiable Credential Issuance specification, we encountered some challenges regarding the issuance of multiple credentials with the same type and format in a single flow.

For case in point, if the Issuer presents two available Training Certificates for the end-user after Authorization Request and User Authentication have taken place, then the end-user is currently restricted to the selection of only one Training Certificate of the two in order to proceed with receiving the credentials.

Even though OpenID4VCI supports the issuance of VCs of different types, the purpose of the "types" attribute is not to uniquely and unambiguously specify each available credential of an authenticated user.

A proposed way for the Credential Issuer to uniquely and unambiguously specify each credential after the authentication step has been completed is for the Credential Issuer to provide a unique identifier for each available credential on the step of the Token Response.

The authorization_details array of the Token Response would look like the following:

[
    {
        "format": "jwt_vc_json",
        "types": ["VerifiableCredential", "AerospaceEngineering"]
        "identifiers": [ "AERO-123-FluidMechanics-II-2023", "AERO-631-SoldingMechanics-IV-2023" ]
    }
]

The credential response should also provide the different identifiers to the Credential Endpoint in order to receive the corresponding credential:

Example Credential Request Body:

{
    "format": "jwt_vc_json",
    "types": ["VerifiableCredential", "AerospaceEngineering"]
    "identifier": "AERO-123-FluidMechanics-II-2023",
    "proof": { ... }
}

Final overview:

End-User & Wallet                                  Credential Issuer

         |   (1) Authz Req (..., authorization_details)   |
         | -------------------------------------------->  |
         |                                                |
      +--+------------------------------------------------+--+
      |  |        (2) User Authentication & Consent       |  |
      +--+------------------------------------------------+--+
         |                                                |
         |      (3) Authz Res  (code)                     |
         |  <-----------------------------------------    |
         |                                                |
         |      (4) Token Req (code)                      |
         |  ------------------------------------------->  |
         |                                                |
         |                                                |
         |    (5) Token Res (..., authorization_details)  |
         |   <----------------------------------------    |
         |                                                |
         |                                                |
         |                                                |
         |                                                |
         |                                                |
         |   Credential Req (format, types, identifier)   |
         |   ---------------------------------------->    |
         |                                                |
         |                                                |

It seems that a similar change has been proposed by another issue (Issue #1922)

Comments (20)

  1. Torsten Lodderstedt

    Hi, thanks for explaining the challenge and a solution.

    I support extension of the specification to cater for this situation.

    I’m assuming the same could happen in the pre-authorized code flow and in situations where the request is done using scopes. I think we need solutions there as well. As the AS can return the access token without an authorization_details object, I’m not sure whether we should introduce a new response structure for those cases.

    Another question: Do you think it is sufficient to just have the identifier? I’m asking since I assume there could be the need to describe the credentials to the user in the wallet.

  2. Kristina Yasuda

    I would like to clarify the problem/goal first…

    is the purpose of an issuer-assigned identifier to help Issuer keep track of the credentials it has issued, including status management of that credential?

    Is the problem here that if the wallet sends the following request (without an identifier), with the same access token, the Issuer cannot differentiate between re-issuance and issuance of the copy of the same credential (just bound to a different key)? But then is there really a difference between those two? Does the issuer really track the proofs to which it is binding the credentials to?

    {
        "format": "jwt_vc_json",
        "types": ["VerifiableCredential", "AerospaceEngineering"]
        "proof": { ... }
    }
    

  3. Kristina Yasuda

    Do you think it is sufficient to just have the identifier? I’m asking since I assume there could be the need to describe the credentials to the user in the wallet.

    It’s the same credential just bound to a different key… what are you imagining the wallet will display to the user?

  4. Torsten Lodderstedt

    It’s the same credential just bound to a different key… what are you imagining the wallet will display to the user?

    The question is related to the original cases Emmanouil raised, where there are identifiers for different credentials of the same type.

    [
        {
            "format": "jwt_vc_json",
            "types": ["VerifiableCredential", "AerospaceEngineering"]
            "identifiers": [ "AERO-123-FluidMechanics-II-2023", "AERO-631-SoldingMechanics-IV-2023" ]
        }
    ]
    

    I don’t know whether the identifiers "AERO-123-FluidMechanics-II-2023" and "AERO-631-SoldingMechanics-IV-2023" are clear enough for the user to understand. I guess both could be enriched with descriptions for display purposes.

  5. Emmanouil Koukoularis reporter

    Our current issue is that, when the wallet first sends an Authorization Request to the Authorization Server, the potential credential identifiers are still unknown.

    After the user has selected the credentials to be received from the Consent Page on the Issuer's website, the wallet should receive an updated authorization_details array, containing unique identifiers, which are ambiguous and cannot be interpreted by the wallet, as they have just been generated by the Issuer.

    If the wallet is required to have full knowledge of the differences between the credentials of the same type, then these identifiers cannot be ambiguous.

    Do you think that such a case in which no further context than the type is provided for a specific credential, is feasible?

  6. Torsten Lodderstedt

    Hi, all I was thinking of that the user should be able to understand the nature of the credentials. That’s why I asked whether the identifier should come with a description, a human readable description. So if the user has to chooser or differentiate, she can tell the difference.

  7. Emmanouil Koukoularis reporter

    Hi,
    if it is necessary for the user to tell the difference between two credentials of the same type, then we suggest extending the concept of the identifiers in the authorization_details object of the Token Response by providing a display object.

    A non-normative example of an authorization_details array following this is provided below:

    [
        {
            "format": "jwt_vc_json",
            "types": ["VerifiableCredential", "AerospaceEngineering"]
            "identifiers": [ 
              { "id": "AERO-123-FluidMechanics-II-2023", "display": [ { "name": "Fluid Mechanics II" } ] },
              { "id": "AERO-631-SolidMechanics-IV-2023", "display": [ { "name": "Solid Mechanics IV" } ] }
            ]
        }
    ]
    
  8. Timo Glastra

    In this case, it could also work I think to create different entries in the credentials_supported list of the issuer? Let’s say you have an Event credential that can be issued for a specific event. Different events have the same @context, types, format etc.., but the branding is different and thus different display metadata is used.

    So the issuer metadata could look like this:

    {
      "credential_supported": [
        {
          "format": "jwt_vc_json",
          "id": "AERO-123-FluidMechanics-II-2023",
          "types": ["VerifiableCredential", "AerospaceEngineering"],
          "display": {
            "name": "Fluid Mechanics",
            /* ... other display properties ... */
          }
        },
        {
          "format": "jwt_vc_json",
          "id": "AERO-631-SoldingMechanics-IV-2023",
          "types": ["VerifiableCredential", "AerospaceEngineering"],
          "display": {
            "name": "Solid Mechanics",
            /* ... other display properties ... */
          }
        }
      ]
    }
    

    and the authorization details or request could then include an identifier that points to a credential from the credentials_supported array.

  9. Andres Olave

    Our preferred use of credentialOffers is only available for authenticated users. We would like to suggest including a credentialSubject property to enable an issuer to give a person a full preview of the credential that is being offered to them, enabling them to reject it before it gets issued due to incorrect details (eg. incorrect name).

  10. Torsten Lodderstedt

    @Andres Olave: we appreciate your input. However, this issue is about a different topic. May I ask you to file a separate issue for your proposal?

  11. Kristina Yasuda

    user can always delete a credential if the issuer has issued a credential with wrong claim values, and re-request issuance, too.

  12. Andres Olave

    @Andres Olave: we appreciate your input. However, this issue is about a different topic. May I ask you to file a separate issue for your proposal?

    Sure, no worries

  13. Mark Dobrinic

    When reading this, to get some more perspective, I’m thinking:

    Given that a verifier requires a particular AerospaceEngineering credential,
    then the verifier will ask for that particular type (e.g. SolidMechanicsAerospaceEngineering). It doesn’t care about a FluidMechanicsAerospaceEngineering type.

    Given that a verifier requires any AerospaceEngineering credential,
    then couldn’t it explicitly ask for any type that it requires (and knows – how it learns about those is another problem)?

    Given that a verifier requires an AerospaceEngineering credential, and there are different “subtypes” that fit this credential type,
    then couldn’t the AerospaceEngineering credential be modelled, such that inside the credential there is a structure that can contain the different “subtypes” ? (this doesn’t fit well along the minimal-disclosure principle, I know, but the verifier is not very specific in what it wants).

    If a credential-id concept is introduced, why wouldn’t a SolidMechanics type not also be made up of WoodMechanics and IronMechanics , repeating the initial problem?

    On the other hand, if the issued credential is delegating to another identity (e.g. in the case of a birthday credential for a parent’s children), there is something to say on differentiating the response. This however can not be done through metadata, but on a per instance basis:
    Given that a parent interacts with a verifier that requires a birth certificate of a child,
    then the verifier asks for a BirthCertificate credential
    the wallet will ask the issuer for a credential of this type
    and the issuer can return multiple BirthCertificate credentials, one for each child of the authenticated user (parent).
    The wallet must be able to hold multiple credentials of the same type.

    Should this be solved through a wallet’s UX?

  14. Alen Horvat

    This is how I understand the issue

    University is running a programme: AerospaceEngineering

    It consists of several courses

    • SolidMechanicsAerospaceEngineering
    • FluidMechanicsAerospaceEngineering

    “course credential” type and format will always be the same. Course name is something that would (at least in Europass) appear inside of the credential subject (e.g., courseName=….; actual claim name is different)

    Imagine that the student is entitled only to:

    • SolidMechanicsAerospaceEngineering

    The information about the actual detailed credentials you’re entitled to obtain should be in the authorisation response (somewhere after authentication and before calling the credential endpoint).

    a) Issuer knows who’s the user

    b) Issuer can check which VCs of a given type the holder can request

    c) issuer sends, in the response, either one or several identifiers and the wallet can fetch VC metadata (with additional options)

    In fact, user could come and say: issue me all VCs I’m entitled to obtain.

    Even if the issuer lists all the credentials and the wallet fetches them, the user won’t know which VCs it can request.

    WDYT?

  15. Log in to comment