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

same credential fulfilling multiple credential queries #397

Open
Sakurann opened this issue Jan 28, 2025 · 12 comments
Open

same credential fulfilling multiple credential queries #397

Sakurann opened this issue Jan 28, 2025 · 12 comments
Labels
ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API
Milestone

Comments

@Sakurann
Copy link
Collaborator

(might be a duplicate)
high-level requirement for a special (?) case: define the wallet's behavior/processing rules when the same credential can fulfill multiple credential queries in the same RP request.

example 1 - RP asks for mdoc for age_over_18 (query_id abc); and mdoc for address (query_id xyz):

option A:
vp_token: {
abc: mdoc with age_over_18
xyz: mdoc with address
}

Option B:
vp_token: {
abc: mdoc with both age_over_18 and address
xyz: mdoc with both age_over_18 and address (same as above)
}

  • concern with option A is that it can trigger multiple user authentication? and for ZKP systems might mean that ZKP has to be computed twice?

  • does this result in the limitation of returning one mdoc per deviceResponse?

@charsleysa
Copy link
Contributor

Option A would be the most straightforward option to implement and would be deterministic with regards to which claims would be present in the presented credential.

If two credential queries were used instead of one then there may be a processing requirement where they need a presented credential with only the specified claims so with option B providing more claims than asked for could violate some PII policy.

@Sakurann
Copy link
Collaborator Author

Sakurann commented Jan 28, 2025

WG discussion:

  1. don't care, don't do anything (option A in the example above)
  2. duplicate the response (option B in the example above)
    2.5 map in a map. query_id : { credential_id, credential }, or query_id : { credential_id }
  3. change the response structure (comma separate key in the VP Token map to allow multiple query_ids to match with multiple credentials?)
  • Concerns that options 3 is too complex

@c2bo
Copy link
Member

c2bo commented Jan 28, 2025

Example for the 2 map option:

{
  "response": {
    "1": "ey...",
    "2": "<some other encoded credential>"
  } 
  "dcql": {
    "abc": "1",
    "xyz": "1",
    "uvw": "2"
  }
}
  • one for id to credential
  • one for DCQL Credential Query to id

That seems like the cleanest option to me, but the whole thing becomes quite a bit more complex which we should probably try to avoid if possible.

@awoie
Copy link
Contributor

awoie commented Jan 30, 2025

Example for the 2 map options:

{
"response": {
"1": "ey...",
"2": ""
}
"dcql": {
"abc": "1",
"xyz": "1",
"uvw": "2"
}
}

  • one for id to credential
  • one for DCQL Credential Query to id

That seems like the cleanest option to me, but the whole thing becomes quite a bit more complex which we should probably try to avoid if possible.

You could do also the following that uses just one map if I understood DCQL correctly:

{
  "response": {
    "<query_id>, e.g., 1234": { 
      "credential": "ey..."
    }, 
    "<query_id, e.g., 5678>": {
      "from_query_id": <query_id, e.g., 1234>
    }
  }
} 

Or if you don't want to break existing implementations, add polymorphism:

{
  "response": {
    "<query_id, e.g., 1234>": "ey...", 
    "<query_id, e.g., 5678>": {
      "from_query_id": <query_id, e.g., 1234>
    }
  }
} 

@martijnharing
Copy link

I think it's important that we find a solution to this issue. It would be unfortunate if in the cases where a single credential can resolve multiple queries, multiple credential responses need to be created only because we don't want to change a structure and not because of an underlying security of privacy reason.
Do we also need to open an issue in HAIP because of the potential impact on the requirement that "When multiple ISO mdocs are being returned, each ISO mdoc MUST be returned in a separate DeviceResponse (as defined in 8.3.2.1.2.2 of [ISO.18013-5]), each matching to a respective DCQL query. "?

@paulbastian
Copy link
Contributor

paulbastian commented Feb 6, 2025

I prefer option "don't care, don't do anything"

  • the scenario that a single credential can fulfil multiple requests and the RP doesn't forumlate it as a single request seems like an edge case
  • DC-API implementaitons right now seem to only allow a single request anyway
  • many implementations will still be able to have a single user authentication for this
  • KISS

@Sakurann
Copy link
Collaborator Author

Sakurann commented Feb 6, 2025

WG discussion
summary of the options:

option 1: don't do anything (you can vote with this emoji 🎉)

what we have now:

{
  "response": {
    "<query_id>, e.g., 1234": ""/{}
   }
}

option 2.5 - A (you can vote with this emoji 🚀 )
changing value in the map to the object

{
  "response": {
    "<query_id>, e.g., 1234": { 
      "credential": "ey..."
    }, 
    "<query_id, e.g., 5678>": {
      "from_query_id": <query_id, e.g., 1234>
    }
  }
} 

option 2.5 - B (you can vote with this emoji 👀 )
changing key in the map to be multiple strings (less breaking change option)

{
  "response": {
    "<query_id, e.g., 1234>": "ey...", 
    "<query_id, e.g., 5678>": {
      "from_query_id": <query_id, e.g., 1234>
    }
  }
}

option 3 (you can vote with this emoji 😁 )
changing the entire response structure

{
  "response": {
    "1": "ey...",
    "2": "<some other encoded credential>"
  } 
  "dcql": {
    "abc": "1",
    "xyz": "1",
    "uvw": "2"
  }
}

Discussion

  • doing this needs processing logic needs to be clarified.
  • composite proofs will benefit from this change, all modification options will work with those proofs.

Next steps:

  • ask @martijnharing to document the limitations of keeping things as-is
  • gave the WG time to think and choose which option is preferred (please indicate if you would like to modify the structure and if yes, how) - you can use emojis to vote too

@charsleysa
Copy link
Contributor

I'd just like to raise the complication of option 2.5 A and B not quite working if/when #398 is merged.

Multiple presentations can be returned for a single credential query (query A) which may not all match the requirements for a second credential query (query B).

This means that you can't simply refer to the query A response in the from_query_id for the query B response as you'd have possible violations of query B.

The wallet could check to make sure that all presentations for query A match requirements for query B before trying to reuse, but if any of the presentations don't match then the entire deduplication effort fails.

You also run into the problem that query A may accept multiple credentials while query B does not, so again it would be a violation if you tried to refer to the query A response in the from_query_id for the query B response.

The number of edge cases and complexities is much higher with these two options.

In light of this, my opinion is that only option 1 and option 3 would be compatible.

@babisRoutis
Copy link

I prefer option "don't care, don't do anything"

* the scenario that a single credential can fulfil multiple requests and the RP doesn't forumlate it as a single request seems like an edge case

* DC-API implementaitons right now seem to only allow a single request anyway

* many implementations will still be able to have a single user authentication for this

* KISS

Completely agree with this, especially for the first argument

@martijnharing
Copy link

The limitation of keeping things as-is, means that in the situations where a single credential is used to satisfy multiple queries, the credential needs to be returned multiple times.
The consequences depend on implementation, but they can include:

  • Require the use of multiple single-use credentials.
  • Require multiple revocation checks
  • Require multiple key signing operations, examples of what this can mean:
    • Require multiple confirmation dialogs
    • Require multiple authentication steps (pin, biometrics etc)
    • Require request of multiple just-in-time created credentials

None of these are critical problems, but they have do have a security and usability cost and could lead to needing to make trade-offs between usability and security, which we can prevent by making changes to the structure. Fixing it now seems to be much easier than fixing it a year from now.

@babisRoutis
Copy link

RP asks for mdoc for age_over_18 (query_id abc); and mdoc for address (query_id xyz)

To my understanding when a verifier is using Presentation Exchange and mso_mdoc, it cannot express the query described above given that :

  • input_descriptor.id is equal to doctype and
  • each input_descriptor.id should be unique within a presentation definition.

The concerns expressed for this (corner?) case by @martijnharing sound reasonable.

I have the impression though, that to address them we are going to need some kind of rule that prohibits to have multiple queries requesting the same credential (type/format) within a DCQL. In turn, IMHO, such a rule could limit the ability to use options/alternatives for different purposes.

@tplooker
Copy link
Contributor

I think we need to consider some variation of option 3 because of the arguments that have already been made. However, it might also make sense to also consider how to make it more explicit whether a returned credential fulfils not only a credential query but also a credential set query. If we don't, it might be quite difficult for an RP to figure this out.

Take for instance.

{
  "credentials": [
    {
      "id": "pid",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://credentials.example.com/identity_credential"]
      },
      "claims": [
        {"path": ["given_name"]},
        {"path": ["family_name"]},
        {"path": ["address", "street_address"]}
      ]
    },
    {
      "id": "other_pid",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://othercredentials.example/pid"]
      },
      "claims": [
        {"path": ["given_name"]},
        {"path": ["family_name"]},
        {"path": ["address", "street_address"]}
      ]
    },
    {
      "id": "pid_reduced_cred_1",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://credentials.example.com/reduced_identity_credential"]
      },
      "claims": [
        {"path": ["family_name"]},
        {"path": ["given_name"]}
      ]
    },
    {
      "id": "pid_reduced_cred_2",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://cred.example/residence_credential"]
      },
      "claims": [
        {"path": ["postal_code"]},
        {"path": ["locality"]},
        {"path": ["region"]}
      ]
    },
    {
      "id": "nice_to_have",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://company.example/company_rewards"]
      },
      "claims": [
        {"path": ["rewards_number"]}
      ]
    }
  ],
  "credential_sets": [
    {
      "purpose": "Identification",
      "options": [
        [ "pid" ],
        [ "other_pid" ],
        [ "pid_reduced_cred_1", "pid_reduced_cred_2" ]
      ]
    },
    {
      "purpose": "Show your rewards card",
      "required": false,
      "options": [
        [ "nice_to_have" ]
      ]
    }
  ]
}

With a response

{
  "response": {
    "pid_reduced_cred_1": "",
    "pid_reduced_cred_2": "",
    "nice_to_have": ""
   }
}

In order for an RP to conclude that the "Identification" and "Show your rewards card" credential set queries have both been satisfied they have to iterate through the options of both credential set queries and match by the credential query id's returned looking for a match. Maybe this is acceptable but it does in essence rely upon the credential query ID not being re-used across credential_set queries otherwise we get into even more ambiguous states like.

{
  "credentials": [
    {
      "id": "pid",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://credentials.example.com/identity_credential"]
      },
      "claims": [
        {"path": ["given_name"]},
        {"path": ["family_name"]},
        {"path": ["address", "street_address"]}
      ]
    },
    {
      "id": "other_id",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://othercredentials.example/pid"]
      },
      "claims": [
        {"path": ["given_name"]},
        {"path": ["family_name"]},
        {"path": ["address", "street_address"]}
      ]
    },
    {
      "id": "passport",
      "format": "dc+sd-jwt",
      "meta": {
        "vct_values": ["https://othercredentials.example/passport"]
      },
      "claims": [
        {"path": ["given_name"]},
        {"path": ["family_name"]},
        {"path": ["address", "street_address"]}
      ]
    },
  ],
  "credential_sets": [
    {
      "purpose": "Identification",
      "options": [
        [ "pid" ],
        [ "other_id" ]
      ]
    },
    {
      "purpose": "Prove citizenship",
      "required": false,
      "options": [
        [ "pid" ],
        [ "passport" ]
      ]
    }
  ]
}

With a response of

{
  "response": {
    "pid": "",
    "passport": ""
   }
}

Basically as an RP I would have to conclude that this response was meant to satisfy both the "Identification" and "Prove citizenship" cases even though there is technically two ways to do this via the response. Maybe thats an issue or maybe not?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ISO_VirtualMeeting relevant for ISO OID4VP mdoc profile over DC API
Projects
None yet
Development

No branches or pull requests

8 participants