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

Protocol extensibility: where should we draw the line between what gets parsed and validated by the browser? #161

Open
samuelgoto opened this issue Aug 22, 2024 · 4 comments
Assignees

Comments

@samuelgoto
Copy link
Collaborator

samuelgoto commented Aug 22, 2024

09/04: Broke this issue into a problem statement and a proposal, to encourage better ways to address this problem.

The Problem

There is a series of ongoing conversations around #152 at the protocol layer, #58 at the registry layer and #156 (comment).

The tension is appearing at the degree of validation the browser should make: should the browser parse into a WebIDL the request field or not?

On one hand, parsing the request gives the browser full visibility/control over the request but poses a serious problem evolving the protocol: because the WebIDL parser drops every unknown field, every extension to the protocol requires changing every browser before it could be used reliably (or worse: protocols abusing DOMStrings to pass opaque parameters). In addition to protocol extensibility, I think it is reasonable to think of security incidents that may require verifiers/holders to redeploy before it can get every browser to redeploy.

On the other hand, not parsing the request gives the protocol extensibility but prevents the browser from (a) having visibility over what's being requested (and informing the user appropriately) and (b) passes a request to holders without any validation.

NOTE: I don't personally agree with (b), but wanted to summarize what I heard in the threads I mentioned above.

A big part of the problem is that it is not clear which parts and why of the request should be inspected and which part shouldn't.

From what I've seen, as far as (a) is concerned, I think it is clear to me that the browser should have "at least" visibility over "what's being requested", specifically, the presentation_definition parameter of the OpenID4VP protocol, so that the browser can build a privacy risk engine. It is also possible that client_metadata may give the browser some useful information too about the verifier that could be useful to construct prompts.

But beyond that, I think it would be harmful to parse and validate other fields. Take nonce for example: there is nothing that a browser can do to validate whether nonce is being used appropriately or not. Maybe one constructive exercise is go through the list of parameters and ask ourselves: which one of these does the browser have any reason to parse and validate?

So, the problem is: where should we draw the line of what gets parsed and validated by the browser?

@TomCJones
Copy link

TomCJones commented Aug 26, 2024

I have suggested before that the initial query should be more abstract - eg The verifier needs proof-of-age or right-to-work as different creds can be selected by the user, before even the wallet is instantiated. Here is that proposal. https://docs.google.com/document/d/1n7HobJ6QTsNld5rn1uuIiNw0A__L44ug/edit

We can certainly try to cut this down to the bear minimum to get the user the ability to make a choice

@samuelgoto samuelgoto changed the title Proposal: unbundle the request to the wallet from credential/wallet selection Proposal: unbundle the request to the wallet from credential selection Aug 26, 2024
@samuelgoto
Copy link
Collaborator Author

samuelgoto commented Sep 4, 2024

08/26: Updated to avoid the duplication of the query language between the protocol layer and the platform layer,
based on the feedback from the community in the DC CG call.

I posit that we should draw the line separating (a) credential selection and (b) wallet invocation: anything that helps (a) should be parsed, mediated and unbundled from anything that goes into (b) to remain, by design, unparsed and extensible.

I think it may be worth revisiting an early proposal: decouple the protocol's request to the wallet from the parameters that are needed for credential/wallet selection.

To be concrete, here is an example of what a JS call looks like today, with the parts that I think browsers should and should not form an opinion on:

// Gets a CBOR with specific fields out of mobile driver's license as an mdoc
const controller = new AbortController();
const {protocol, data} = await navigator.identity.get({
  signal: controller.signal,
  digital: {
    providers: [{
      protocol: 'openid4vp',
      request: {
        // what benefit do we get by validating "response_type"?
        response_type: 'vp_token',
        // what benefit do we get by validating "nonce"?
        nonce: 'gf69kepV+m5tGxUIsFtLi6pwg=',
        // same with "client_metadata"
        // NOTE(goto): it was noted on the 08/26 DC CG call that client_metadata may be something
        // that would be useful for the browser to get, e.g. terms of services and privacy policies
        client_metadata: {},
        //  on the other hand, "presentation_definition" is something that is worth looking at
        presentation_definition: {     
          // presentation exchange, the query, omitted for brevity  
        }
      }
    }],
  }
});

In this formulation, the request to the wallet (e.g. nonce, response_type) is bundled with the request to the OS (namely, presentation_definition), so it forces the browser to open the entire request and inspect parts of it.

By comparison, invoking OpenID4VP through custom schemes, aside from all of its challenges, got one thing right: the integration with the OS to do wallet selection was entirely decoupled from the invocation after that.

So, one idea, is that, if we unbundled and decoupled the parts that browsers should absolutely form an opinion on, than we could make the rest of the request entirely opaque (by design).

For example:

// Gets a CBOR with specific fields out of mobile driver's license as an mdoc
const controller = new AbortController();
const {protocol, data} = await navigator.identity.get({
  signal: controller.signal,
  digital: {
    providers: [{
      protocol: 'openid4vp',
      // request is opaque to the browser and doesn't get introspected
      request: `__the__openid4vp__that_we_dont_introspect__asjjlkfsa__3920s__jklsfs__`,
      // selector, on the other hand, is understood by the browser and affects credential selection
      selector: {     
        // the query language that allows the OS to do credential selection   
      }
    }],
  }
});

There is probably a point to be made about making the selector a query language that is browser-specific but protocol-agnostic, but that's a separate argument from the one I'd like to make (which is to create a clear delineation between what gets inspected and what doesn't).

NOTE: OpenID4VP's query language is currently Presentation Exchange, which in fact protocol agnostic. A new query language is being developed, which could also be adopted here.

selector would also need to be extensible, since so much of the innovation is going to happen there, but the benefit here is that it makes it clear that the browser shouldn't get on the way of the protocol.

An immediate criticism here to this framing is that it is possible that selector would duplicate presentation_definition, and in doing so could be either wasteful (extra bytes) and/or attackable (e.g. what if the OS credential selector was inconsistent with later the permission that the wallet would gather?). Not having the duplicate would involve working with the OpenID4VP community to figure out how to avoid it.

The selector would be passed to the wallet along with the request.

The immediate benefit of this proposal, IMHO, is that it would make it very clear the delineation between the layers, with the OS doing credential selection but then getting out of way beyond that.

@samuelgoto samuelgoto changed the title Proposal: unbundle the request to the wallet from credential selection Where should we draw the line between what gets parsed and validated by the browser? Sep 4, 2024
@samuelgoto samuelgoto changed the title Where should we draw the line between what gets parsed and validated by the browser? Protocol extensibility: where should we draw the line between what gets parsed and validated by the browser? Sep 4, 2024
@jogu
Copy link

jogu commented Sep 6, 2024

It's an interesting proposal.

Some initial thoughts:

  1. I'm not immediately clear how it would work with signed requests (which currently sign over both the oid4vp bits and the selector bits), if we just remove selector from the scope of the signature that might need some consideration as to how it changes the security posture (there have been separate suggestions that it should be possible to send signed requests where the query language part isn't signed but I don't think the DCP WG has formed a position on that yet).

  2. I'm not sure if in some ecosystems more than the query language might be needed (or at least desirable) to do credential matching. At a minimum I'm not sure OID4VP makes it clear to people adopting & profiling the spec that any extensions that affect credential matching have to go in the query language.

@TomCJones
Copy link

TomCJones commented Sep 7, 2024

Smart Digital Credential (SDC:)
This is a suggestion to follow in the path of the Smart Health Card (SHC:) and allow for mobile credentials in the most inclusive manner possible. Here are the salient points:

  1. The SHC can be scanned by the camera or downloaded from a web site.
  2. The SHC can be created and used without an internet connection.
  3. A mobile device with a camera that costs $30 can be used to get an SHC.
  4. Nearly all smartphones currently accept store and display an SHC.
  5. It can also be considered to be a Scanned Health Certificate.
  6. Also called an EU Digital COVID Certificate.
    Physical Reality:
  7. There are 251 credit card transactions per person per year in the us (https://capitaloneshopping.com/research/number-of-credit-card-transactions/#:~:text=Highlights.,minute.%20or%201%2C708%20per%20second.)
  8. Anecdotally there are 1-3 ID transactions per week, say 100 per year.
  9. Identity transactions are a minority of user in-person transactions today.
  10. Online might be different, but cached credentials make it hard to estimate.
  11. To succeed, wallets need to be best at the type of transaction most often made.
  12. Digital wallets were not well accepted until the point-of-sale terminals worked.
  13. Digital wallets are being accepted now without ID capabilities.
    Proposal:
  14. Determine what can be demanded of verifiers that they are willing to accept.
  15. Create a single request format that can be generated by small (POS) verifiers.
  16. Accommodate inclusively all users that have any need to access digital services.
  17. Allow expansion to enable more complex transactions that are fully optional.
  18. KISS = keep it simple for the basic needs of the small POS verifiers.
  19. Enable the needs of privacy legislation (admittedly a moving target.)
    Specifics of request:
  20. Verifier ID in a form that the user can approve
  21. Purpose(s) of the request in a form that the user can approve.
  22. Date/time
  23. Acceptable feedback formats
  24. Optional details
  25. signature

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

No branches or pull requests

3 participants