- From: Adrian Gropper <agropper@healthurl.com>
- Date: Wed, 21 Jul 2021 11:33:40 -0400
- To: Mahmoud Alkhraishi <mahmoud@mavennet.com>
- Cc: Orie Steele <orie@transmute.industries>, Justin Richer <jricher@mit.edu>, W3C Credentials CG <public-credentials@w3.org>
- Message-ID: <CANYRo8iT7hbsjkWVEi_owAdeRuuVa=tzD829CjtfNcXb568ADQ@mail.gmail.com>
I appreciate Justin's explanation. I have some experience with sophisticated and extensible APIs in the form of the HL7 FHIR standards for health records https://www.hl7.org/fhir/ . This represents a huge investment by a particular industry and it is then adopted as part of regulation https://www.healthit.gov/isa/united-states-core-data-interoperability-uscdi Please try to imagine the difficulty in achieving interoperability as well as security through data minimization and least-privilege using OAuth scopes. My point with respect to VC-HTTP API and SSI standards in general, is that our work is not industry-specific to healthcare or education. It is not specific to VCs that have no expiration date like a medical license and will be presented hundreds of times or that become irrelevant in a day like a boarding pass and will be presented twice. These are the reasons why Justin and I, from rather different real-world experience, are working on GNAP and hoping this work will be adopted by the SSI community. - Adrian On Wed, Jul 21, 2021 at 11:18 AM Mahmoud Alkhraishi <mahmoud@mavennet.com> wrote: > Thanks Justin. > I feel like I thought I got your points during your initial presentation > but this email really made it click, I appreciate that you keep driving > this. > > > > On Jul 21, 2021, at 10:59 AM, Orie Steele <orie@transmute.industries> > wrote: > > > Thanks Justin, these examples are very helpful. It seems like the primary > value of RAR is extensibility. Objects are easier to extend than strings. > > I want to understand the security tradeoffs by leveraging these > extensibility features. Your identifier security parameter example is very > helpful. > > In that case, are you not exposing that identifier to the AS? Why does the > AS need to know which DIDs a resource server can issue/present on behalf of? > > It would seem safe to make use of the extensibility as long as you don't > leak subject identifiers to the AS, can you comment on these design > considerations? > > I'm on my phone sorry for any spelling. > > OS > > On Wed, Jul 21, 2021, 9:42 AM Justin Richer <jricher@mit.edu> wrote: > >> On yesterday’s call, we briefly discussed the applicability of RAR for >> the VC HTTP API, and I wanted to continue that conversation with some >> additional concrete points. Apologies in advance for the long email, but >> there’s a lot to untangle here as it seems a number of people have the >> wrong idea. >> >> First, what are we proposing? I am suggesting, strongly, that when >> defining this API, the group also define the different ways to control >> access to it. Which is to say, what actions can you do, what kinds of data >> do you want to switch on — in short, we’ve got an API, how do we want to >> slice it? I am explicitly saying that we do not define anything about the >> process of getting a token (so, specifying client credentials is a terrible >> idea) or how to process the token (so specifying token formats is also a >> terrible idea) because these don’t affect the API. What does affect the API >> is the availability of different kinds of actions for a specific call. What >> are the things that I can DO here? >> >> This is what OAuth 2 invented scopes for, instead of the OAuth 1 or HTTP >> Basic method of “you just get everything”. So, why not just use >> parameterized scopes? It seemed like a good idea when I first invented it a >> decade ago: https://blue-button.github.io/blue-button-plus-pull/#scopes or >> when it got pulled into other efforts like >> https://openid.net/specs/openid-heart-fhir-oauth2-1_0-2017-05-31.html … >> and Orie even suggested the following set of parameterized scopes for this >> API: >> >> 'create:credentials': Grants permission to create credentials >> 'derive:credentials': Grants permission to derive credentials >> 'create:presentations': Grants permission to create presentations >> 'verify:presentations': Grants permission to verify presentations >> 'exchange:presentations': Grants permission to exchange presentations >> >> So what’s the problem? I can say with full confidence after years of >> experience building and deploying systems to support parameterized scopes >> like this that they are fragile, awkward, and lead to insecure corner >> cases. For example, am I supposed to parse these strings to find the bits >> on either side of that colon? Am I allowed to make up my own combinations >> of elements, so for example do I get “derive:presentations” from that set >> above, for free? What if I am protecting more than one API and they use a >> different separator? Or what if there’s just a plain old namespace >> collision and someone else has “exchange:presentations” on their unrelated >> API that that the AS is protecting at the same time? And what if someone >> has an additional dimension they need to convey, like the identifier for a >> specific account— does that mean we add a parameter to the string above, or >> do we need a separate scope to carry this, and how do we combine all of >> that? While all of these questions can be answered, the answers make >> something that seems simple on the surface spiral out of hand very quickly. >> I know this because I’ve seen it time and again, and this experience is >> exactly what led me to create what has become RAR. >> >> So let’s talk about how we’d address the above actions in RAR. First, >> please note that I’m going to be fast and loose with JSON syntax here >> because I’m typing it out by hand, so don’t try to compile this. :) Second, >> for simplicity of following this argument, let’s say that all five actions >> above are inside a single RAR type value, and we’ll just use “vha" as the >> stand-in for that value (in reality it would be a URI, and there might be >> multiple for a given API family like VC HTTP API). >> >> Picking apart the pieces above, we’ve got two elements that fit fairly >> well into the “actions” and “datatypes” fields in a RAR request type: >> >> actions: [ create, derive, verify, exchange ] >> datatypes: [ credentials, presentations ] >> >> Since RAR is about combining different dimensions into a single request, >> we can easily get to the kind of expressions above. Let’s say I want to >> create credentials and permissions, but nothing else — I can ask for the >> following value: >> >> >> { >> type: “vha”, >> actions: [ create ], >> datatypes: [ credentials, presentations ] >> } >> >> Or if I want to create and derive credentials but do nothing with >> presentations, I can do: >> >> { >> type: “vha”, >> actions: [ create, derive ], >> datatypes: [ credentials ] >> } >> >> And how about a more complex cross-product? Let’s say I want to create >> and derive credentials but only exchange presentations. All RAR requests >> are in an array, just like OAuth 2 scopes are fundamentally an array, so >> that request would look like this: >> >> [ >> >> { >> type: “vha”, >> actions: [ create, derive ], >> datatypes: [ credentials ] >> }, >> { >> type: “vha”, >> actions: [ exchange ], >> datatypes: [ presentations ] >> } >> >> ] >> >> Unlike with scopes, the extent of each aspect is clear to developers of >> both the API and the clients of the API. It’s very clear what I’m asking to >> do and what I’m doing it to, without having to define or parse or >> understand any kind of VC-HTTP-API-specific syntax to cram into an existing >> field. This gets even better with GNAP because you can ask for multiple >> different-scoped tokens at the same time. >> >> And what if someone requests a confusing or bad combination? >> >> { >> type: “vha”, >> actions: [ create, derive ], >> datatypes: [ credentials, presentations ] >> } >> >> RAR clearly defines each object as the union of all items within it, so >> anything processing this would be able to tell that “derive” and >> “presentations” doesn’t fit together and this is an invalid request. >> There’s no need to guess and no need to put in special casing. Your >> implementation would be configured with viable combinations, and anything >> that falls outside of that is easily detected. >> >> It gets even clearer if we want to talk about other dimensions not >> captured in the example scopes above. If I want to do this for a specific >> account? We can define a security identifier in this request to contain >> that information: >> >> { >> type: “vha”, >> actions: [ create, derive ], >> datatypes: [ credentials ], >> identifier: did:example:12345 >> } >> >> Already we’re doing something that would be difficult with scope strings. >> >> And what if we are protecting multiple APIs that use similar syntax? They >> sit in separate namespaces so there is no chance for confusion. >> >> [ >> >> { >> type: “vha”, >> actions: [ create, derive ], >> datatypes: [ credentials ] >> }, >> { >> type: “TOTALLY-NOT-VHA”, >> actions: [ create, derive ], >> datatypes: [ credentials ], >> not-a-vha-attribute: do-some-weird-thing >> } >> >> ] >> >> What does this mean for the VC HTTP API itself? It means that each call >> defined as part of the API would have a section like: >> >> Security: >> Type: “vha” >> Action: “create” >> Datatype: “credentials" >> >> … and that’s all the detail that would be needed. The core part of the >> spec would say something like “use the fields defined in the ’security’ >> section to make a RAR or GNAP request”, and that only applies if you’re >> doing OAuth 2 (with any flow) or GNAP (with any mode). You’re still free to >> protect the API with whatever fancy pants thing you want, but even then the >> Security section will lay out the core dimensions that each call is >> differentiated on. >> >> So yes, it’s possible to pull this off with scope strings. I’ve done >> things more complex than this and have seen some really crazy stuff like >> using a fully-qualified query language as the scope string value. However, >> what I’m trying to convince this group is that there is a much simpler way >> and that’s by embracing the object structures that RAR lets you define, to >> talk about the dimensions of access that you want to allow or disallow. >> That discussion is going to happen anyway, and is probably ALREADY >> happening. I am saying this group should embrace that challenge as part of >> the protocol definition, and do so sooner rather than later. If we wait, >> it’ll end up a mess of proprietary solutions that don’t want to change, and >> people will dig in their heels even more for either a loose spec or >> patchwork of things so implementations don’t have to change. >> >> What I’m calling for is structure for interoperability and compatibility, >> in a way that’s a very, very light lift on the spec itself and would in >> fact help define the elements of the spec. Believe me — I’ve been down this >> road before and I am hoping that this group could learn from my mistakes >> instead of repeating them. >> >> — Justin >> >
Received on Wednesday, 21 July 2021 15:34:06 UTC