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

How are credential copies issued? #93

Closed
danielfett opened this issue Oct 27, 2023 · 26 comments · Fixed by #293
Closed

How are credential copies issued? #93

danielfett opened this issue Oct 27, 2023 · 26 comments · Fixed by #293

Comments

@danielfett
Copy link
Contributor

Originally posted by @danielfett in #65 (comment)

The relationship currently described is that in any issuance process, multiple "types" of credentials can be issued (*), and for each "type" there can be multiple instances. An instance is described as "contains different claim values or different subset of claims within the claimset identified by the Credential type"

(issuance process) --- 1:n --- (credential definition*) --- 1:m --- (credential instance)

How is the relationship to batch issuance for unlinkability as suggested in SD-JWT? Is this already covered or should there be a separate mechanism for that? I.e., to have something like this for k copies of the same credential:

(issuance process) --- 1:n --- (credential definition*) --- 1:m --- (credential instance) --- 1:k --- (credential instance copy)

(*) entry in the credentials_supported Credential Issuer metadata - I added a comment suggesting to find a good term for this to use instead of credential type.

@danielfett
Copy link
Contributor Author

Note: The individual credential instance copies would also need different keys.

@danielfett
Copy link
Contributor Author

I only now noticed that an issue for this exists already: #91

@danielfett danielfett closed this as not planned Won't fix, can't repro, duplicate, stale Oct 27, 2023
@Sakurann Sakurann reopened this Nov 2, 2023
@paulbastian
Copy link
Contributor

My opinions on the matter in the sibling-thread: #91 (comment)

@paulbastian
Copy link
Contributor

paulbastian commented Nov 2, 2023

---------DEPRECATED EXAMPLE------------

Token Response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

  {
    "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6Ikp..sHQ",
    "token_type": "bearer",
    "expires_in": 86400,
    "c_nonce": "tZignsnFbp",
    "c_nonce_expires_in": 86400,
    "credential_identifiers": [ "CivilEngineeringDegree-2023", "ElectricalEngineeringDegree-2023" ]
  }

---------DEPRECATED EXAMPLE------------
Credential Request

POST /credential HTTP/1.1
Host: server.example.com
Content-Type: application/json
Authorization: BEARER czZCaGRSa3F0MzpnWDFmQmF0M2JW

{
  "CivilEngineeringDegree-2023": {
    "proof": [
      {
        "proof_type": "jwt",
        "jwt": "eyJraWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEva2V5cy8xIiwiYWxnIjoiRVMyNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJzNkJoZFJrcXQzIiwiYXVkIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJpYXQiOjE1MzY5NTk5NTksIm5vbmNlIjoidFppZ25zbkZicCJ9.ewdkIkPV50iOeBUqMXCC_aZKPxgihac0aW9EkL1nOzM"
      },
      {
        "proof_type": "jwt",
        "jwt": "eyJraWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEva2V5cy8xIiwiYWxnIjoiRVMyNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJzNkJoZFJrcXQzIiwiYXVkIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJpYXQiOjE1MzY5NTk5NTksIm5vbmNlIjoidFppZ25zbkZicCJ9.ewdkIkPV50iOeBUqMXCC_aZKPxgihac0aW9EkL1nOzM"
      }
    ]
  },
  "ElectricalEngineeringDegree-2023": {
    "proof": [
      {
        "proof_type": "jwt",
        "jwt": "eyJraWQiOiJkaWQ6ZXhhbXBsZTplYmZlYjFmNzEyZWJjNmYxYzI3NmUxMmVjMjEva2V5cy8xIiwiYWxnIjoiRVMyNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJzNkJoZFJrcXQzIiwiYXVkIjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20iLCJpYXQiOjE1MzY5NTk5NTksIm5vbmNlIjoidFppZ25zbkZicCJ9.ewdkIkPV50iOeBUqMXCC_aZKPxgihac0aW9EkL1nOzM"
      }
    ]
  }
}

---------DEPRECATED EXAMPLE------------
Credential Response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "credentials": {
    "CivilEngineeringDegree-2023": {
      "credential": [
        "LUpixVCWJk0eOt4CXQe1NXK....WZwmhmn9OQp6YxX0a2L",
        "LUpixVCWJk0eOt4CXQe1NXK....WZwmhmn9OQp6YxX0a2L"
      ]
    },
    "ElectricalEngineeringDegree-2023": {
      "credential": [
        "LUpixVCWJk0eOt4CXQe1NXK....WZwmhmn9OQp6YxX0a2L"
      ]
    }
  }
}

@Sakurann
Copy link
Collaborator

Sakurann commented Nov 2, 2023

a quick note that a proposal that introduces any changes to the token response (like a new top level claim credential_identifier) would not work for implementations like Microsoft's that re-use existing AS and cannot make breaking changes to that AS. In general, this would limit what ASs can implement VCI which I hope we can avoid.

@Sakurann
Copy link
Collaborator

Sakurann commented Nov 2, 2023

To the question... As discussed during DCP WG call, one information that needs to be communicated between the issuer and the wallet is how many copies of credentials need to be issued.

I am not sure the issuer cares which endpoint the wallet uses for batch issuance, when the issuer supports both credential and batch credential endpoint. and i am not sure issuer can force the wallet to use either of the endpoints for batch issuance because there is no guarantee the wallet supports both endpoints. so in reality the issuers that want to do batch issuance will have to support batch issuance on both endpoints. as longs as we keep both endpoints of course. it might be simpler to have one credential endpoint and a flag whether the issuer supports batch issuance at that endpoint or not - i don't know yet.

I would imagine it is the issuer who dictates the number of copies, but I have also seen an implementation in ISO mDL world where the user can choose how many copies (not sure if this is a hard requirements though)

@jogu
Copy link
Contributor

jogu commented Nov 2, 2023

I would imagine it is the issuer who dictates the number of copies, but I have also seen an implementation in ISO mDL world where the user can choose how many copies (not sure if this is a hard requirements though)

I imagine it might be a bit of negotiation. Probably the issuer somehow tells the wallet the maximum number of copies it's willing to issue, and the wallet decides how many to actually request (by supplying the requisite number of holder proofs?). Certainly the issuer shouldn't fully dictate the number of copies as the wallet may hit limits on the number of distinct private keys it can create in the secure enclave, etc.

I firmly believe that (at least for the "average person on the street") the complexities of having multiple copies of credentials should be hidden from the user as much as possible, so if the user has any input at all on the number of copies it should be hidden deep in an "advanced settings" screen that normal users can ignore.

@paulbastian
Copy link
Contributor

paulbastian commented Nov 10, 2023

most recent ideas for Credential Request

POST /credential HTTP/1.1
Host: server.example.com
Content-Type: application/json
Authorization: BEARER czZCaGRSa3F0MzpnWDFmQmF0M2JW

{
  "credential_encryption_jwk": "...",
  "credential_response_encryption_alg": "...",
  "credential_response_encryption_enc": "...",
  "credential_requests": [
    //uses credential_identifier returned from the Token Endpoint. issues 2 copies of a credential
    {
      "credential_identifier" : "CivilEngineeringDegree-2023",
      "proofs": [
        {
          "proof_type": "jwt",
          "jwt": "..."
        },
        {
          "proof_type": "jwt",
          "jwt": "..."
        }
      ]
    },
    //issues one copy of a credential
    {
      "format" : "mdoc_mso",
      "proofs": [
        {
          "proof_type": "cwt",
          "jwt": "..."
        }
      ]
    },
    //issues 2 copies of the same credential
    {
      "format" : "sd-jwt+vc",
      "proofs": [
        {
          "proof_type": "jwt",
          "jwt": "..."
        },
        {
          "proof_type": "jwt",
          "jwt": ""
        }
      ]
    }
  ]
}

@paulbastian
Copy link
Contributor

paulbastian commented Nov 10, 2023

most recent ideas for Credential Response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "credential_responses": [
    //issuer was able to successfully issue both copies of the credential
    {
      "credentials": [
        "eyJraWQiOiJkaWQ6ZXhhbXBsZTpl...C_aZKPxgihac0aW9EkL1nOzM",
        "eyJraWQiOiJkaWQ6ZXhhbXBsZTpl...C_aZKPxgihac0aW9EkL1nOzM"
      ]
    },
   //issuer wants to defer issuance of this credential
    {
      "transaction_id": "8xLOxBtZp8"
    },
    //issuer was not able to successfully issue both copies of the credential

    {
      "error": "unsupported_credential_format",
      "error_description": "..."
    }
  ],
  "c_nonce": "fGFF7UkhLa",
  "c_nonce_expires_in": 86400
}

note: i removed the REQUIRED format from credential response, I think its unnecessary. Also single credentials are still returned as an error

@tlodderstedt
Copy link
Collaborator

most recent ideas for Credential Request

multiple proofs ask for multiple instances of the same credential?

@tlodderstedt
Copy link
Collaborator

a quick note that a proposal that introduces any changes to the token response (like a new top level claim credential_identifier) would not work for implementations like Microsoft's that re-use existing AS and cannot make breaking changes to that AS. In general, this would limit what ASs can implement VCI which I hope we can avoid.

I think this is why we came up with the idea back in MV to only issue credential identifiers with authorization details, right?

@jogu
Copy link
Contributor

jogu commented Nov 14, 2023

most recent ideas for Credential Request

multiple proofs ask for multiple instances of the same credential?

Correct.

@Sakurann
Copy link
Collaborator

Sakurann commented Nov 16, 2023

One of the ways forward that minimizes breaking changes would be

  • keep Credential Endpoint as-is
  • modify the proof structure in the batch endpoint
  • add metadata for how many copies of the credentials the issuer supports issuance
  • modify error condition of the batch endpoint

It would be important to reach out to the current implementers of a Batch Endpoint. I reached out to an ISO WG working on 23220-3 (profile of VCI to issue mdocs) and does not look like anyone has implemented a Batch Endpoint, yet.

Few remaining questions I have are

  • does the structure of Deferred endpoint change? probably not.
  • what if the wallet requested 2 copies and one was successful, but another was not?

@tplooker
Copy link
Contributor

tplooker commented Nov 16, 2023

IMO as an alternative perspective on this topic, I've always been of the opinion that the credential endpoint as it stands can be used to issue multiple copies of a credential by simply making multiple requests. This may appear as less efficient in some usecases, but it also keeps implementations simple in the event single credentials are being issued and avoids the significant possible draw backs which come with batch endpoints in general (such as partial failures and maintaining transactional integrity). I would recommend reading my original break down of #8 I still believe a solution that uses the credential endpoint alone but also returning a credential version from each response is the easiest way for a wallet to obtain multiple copies AND refresh copies over time.

@tplooker
Copy link
Contributor

add metadata for how many copies of the credentials the issuer supports issuance

Can you elaborate on the usecase here?

@jogu
Copy link
Contributor

jogu commented Nov 16, 2023

Can you elaborate on the usecase here?

When using an endpoint that allows the wallet to request many copies of a credential at the same time, it's really helpful if the wallet has an idea how many copies the issuer is willing to issue in a single call so the wallet has an idea on the number of proofs to include.

@bc-pi
Copy link
Member

bc-pi commented Nov 16, 2023

@tplooker's alternative perspective that the credential endpoint can be used to issue multiple copies of a credential by simply making multiple requests resonates.

@tplooker
Copy link
Contributor

Can you elaborate on the usecase here?

When using an endpoint that allows the wallet to request many copies of a credential at the same time, it's really helpful if the wallet has an idea how many copies the issuer is willing to issue in a single call so the wallet has an idea on the number of proofs to include.

Thanks I understand that part, I guess I'm trying to understand why an issuer would want to cap this number and communicate this cap to a wallet, for example why does an authorization server not do this with access tokens?

@jogu
Copy link
Contributor

jogu commented Nov 16, 2023

I guess I'm trying to understand why an issuer would want to cap this number and communicate this cap to a wallet, for example why does an authorization server not do this with access tokens?

Basic OAuth2 pretty much hardcodes the number of valid access tokens the client can obtain per authentication at 1 so that's a major difference :-)

I think that this mechanism is trying to avoid generating unnecessary proofs. One proof is needed per credential instance/copy that the wallet wants to obtain, and they're potentially expensive to generate (creating a new key, signing with that key - potentially at a remote HSM), i.e. consume various resources (entropy, time, HSM storage, battery, network transmission). It seems best to me not to generate proofs in the case that the issuer will definitely discard/ignore them.

[It's probably not such a problem if we follow your one http request == issue one credential copy suggestion.]

@tplooker
Copy link
Contributor

Basic OAuth2 pretty much hardcodes the number of valid access tokens the client can obtain per authentication at 1 so that's a major difference :-)

Well it somewhat depends on the grant type as to whether a token request is repeat-able for example 'client_credentals' you can just make repeated requests to get new tokens.

I think that this mechanism is trying to avoid generating unnecessary proofs. One proof is needed per credential instance/copy that the wallet wants to obtain, and they're potentially expensive to generate (creating a new key, signing with that key - potentially at a remote HSM), i.e. consume various resources (entropy, time, HSM storage, battery, network transmission). It seems best to me not to generate proofs in the case that the issuer will definitely discard/ignore them.

That makes sense and personally I dont think we want to limit issuers from applying these sorts of policies to protect themselves I guess Im just wary as to whether we need an interoperable piece of metadata to communicate this constraint yet, feels like complexity we could avoid to begin with until we validate it is actually an issue.

[It's probably not such a problem if we follow your one http request == issue one credential copy suggestion.]

Agreed

@jogu
Copy link
Contributor

jogu commented Nov 16, 2023

@tplooker's alternative perspective that the credential endpoint can be used to issue multiple copies of a credential by simply making multiple requests resonates.

I definitely appreciate the simplicity of that solution.

It is a tradeoff, and I believe there would be a notable difference in the time it takes to issue 10 credential copies in a single API call vs the time to do so by doing 10 API calls (both in terms of round trips and the amount of processing/data retrieval on the backend). I don't have any actual empirical data to back up that believe though. We heard on the call today that at least one real deployed systems do use the "multiple copies in a single API call" but I guess we didn't probe into why they decided the extra complexity was worth it.

@tplooker
Copy link
Contributor

It is a tradeoff, and I believe there would be a notable difference in the time it takes to issue 10 credential copies in a single API call vs the time to do so by doing 10 API calls (both in terms of round trips and the amount of processing/data retrieval on the backend). I don't have any actual empirical data to back up that believe though. We heard on the call today that at least one real deployed systems do use the "multiple copies in a single API call" but I guess we didn't probe into why they decided the extra complexity was worth it.

Agreed there are tradeoffs here but as I said above conversely batch endpoints aren't without issue too, for example what if I requested 10 credentials and the 8th fails to generate? Do I retry generating it, what if the error isn't recoverable? Do I return 8 or an error, if I return an error what do I do with the 8 credentials I generated? Throw them away, revoke them perhaps both?

@paulbastian
Copy link
Contributor

paulbastian commented Nov 17, 2023

To give the prespective what is drafted in ISO currently, this is the issuer metadata:

{
    "format": "mdoc",
    "doctype": "org.iso.18013.5.1.mDL",
    "policy": {
        "one_time_use": true,
        "batch_size": 10
    },
    "cryptographic_suites_supported": [
        "ES256"
    ],
    "cryptographic_curves_supported": [
        1
    ],
    "claims": {
        "org.iso.18013.5.1": {
            "given_name": {
                "display": [
                    {
                        "name": "Given Name",
                        "locale": "en-US"
                    },
                    {
                        "name": "名前",
                        "locale": "ja-JP"
                    }
                ]
            }
        }
    }
}

Look for the policy claim

@jogu
Copy link
Contributor

jogu commented Nov 17, 2023

Agreed there are tradeoffs here but as I said above conversely batch endpoints aren't without issue too, for example what if I requested 10 credentials and the 8th fails to generate? Do I retry generating it, what if the error isn't recoverable? Do I return 8 or an error, if I return an error what do I do with the 8 credentials I generated? Throw them away, revoke them perhaps both?

Yeah, I think/hope we're in agreement - it's mainly a complexity vs speed tradeoff? (And my understanding of the suggestion is that it would probably be optional for the issuer to support an endpoint that generates more than one credential, and it would be optional for the wallet to request more than one credential, so the complexity only comes into play when both parties have opted into it - although we also can't ignore the difficultly of getting the design of the batch request/response right in the specification.)

To answer your question based on the latest suggested respsonse format (Paul's #93 (comment) ) I think the answer varies depending on if it's 10 different credentials or 10 credential instances.

If 10 different credentials: you can return 7 credentials and 3 errors (or 9 and 1 error, depending on what happens with credentials 9 and 10).

If 10 credential instances/copies: you could just return 7 successfully created instances. (Or I guess you could error out if that was your preference. I can't currently think of a reason you wouldn't return the 7 instances - especially as trying to revoke them might also fail, but I guess there could be one.)

@tplooker
Copy link
Contributor

tplooker commented Nov 17, 2023

To give the prespective what is drafted in ISO currently, this is the issuer metadata:

I might be missing some detail here, for example where this policy is described. But in any case it doesn't come across that intuitively to me what the purpose is, for example is this metadata saying wallets MUST only request in batches of 10 or up to? The "one_time_use" flag i assume means a wallet can present a credential only once to an RP, how does an issuer enforce this? Or does it simply rely on the wallet to do so.

It feels too early or a premature optimisation to have metadata like this IMO as its not critical to get interoperability between a wallet and an issuer which is the primary intent of this metadata document.

@jogu
Copy link
Contributor

jogu commented Feb 29, 2024

This was discussed on the EU friendly DCP WG call today.

Participants seemed happy with updating the batch credential endpoint to use the request/response proposals in Paul's comments here: #93 (comment) hence I'll mark this as ready for PR.

The issue of issuer metadata for the maximum number of copies the issuer is willing to issue in a single call was brought up again. It seems sensible to me to have some metadata somewhere that indicates this - without that the wallet may prepare more and send more proofs than can ever be used, which wastes battery / network resource / time / etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants