Re: [GNAP] Feedback on polymorphism
Fabien Imbault <fabien.imbault@gmail.com> Wed, 28 October 2020 16:55 UTC
Return-Path: <fabien.imbault@gmail.com>
X-Original-To: txauth@ietfa.amsl.com
Delivered-To: txauth@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 94E9A3A08EB for <txauth@ietfa.amsl.com>; Wed, 28 Oct 2020 09:55:50 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.096
X-Spam-Level:
X-Spam-Status: No, score=-2.096 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_FONT_LOW_CONTRAST=0.001, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ew5U9zbihQ0w for <txauth@ietfa.amsl.com>; Wed, 28 Oct 2020 09:55:44 -0700 (PDT)
Received: from mail-io1-xd36.google.com (mail-io1-xd36.google.com [IPv6:2607:f8b0:4864:20::d36]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 778C83A067A for <txauth@ietf.org>; Wed, 28 Oct 2020 09:55:44 -0700 (PDT)
Received: by mail-io1-xd36.google.com with SMTP id r9so34916ioo.7 for <txauth@ietf.org>; Wed, 28 Oct 2020 09:55:44 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=i1h+OVYy8YQqi63eQHI6937kADdOn8uDNPEwqRhCGn4=; b=bbebKu60G8KK7NAVJDOKvnjZ6g5MnTTpsJkfXRCTLS74Xu53XAxwZroKGEicP2kMeH JO91NGn4AbwrrWEeI9ubH5H2gFPpTnpwXAbAd6ERL1Ze7TzDxA4pl3XqihRs3dDaF9YP 6XwPirxg3WZlF/NkQAV0f6azWhaQefzOm4aLARXLeT/AM+FB6XfjggkMZ1T02SsXGUI4 V+TKkOilI+Cc4rwbIyyqDQw1oUDrM1SPVWiGgPXqEi+cV0wxL4qUhwFdco6WOsINfGup /WiHGFA1MBDWudqoLjJ2TM/Nbdu88ANPujrpycjlxlsILadlmDf3LTRlN/WBV9QkFegx OBnw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=i1h+OVYy8YQqi63eQHI6937kADdOn8uDNPEwqRhCGn4=; b=BHMpLQex8t0q15+Nxr7L+hDLNxhVgAB+70iWs+NjXf3f4NtinwL68p1hO/wSx59x+E BQDiuaXF30QHxVDachedpZCnS2FE9mW/lNdUuwADo1w35reqXTUm2RnciPiQK/pgolIC Zaurg5CqxN0PIsCoHCoQr+AiiGHyvrqkAlUmhdk5mjTs44l2J5YNn23eoVl4XkxsE2HH xwuFmoEkEKsnpNEwJyo3xKv0OCxEtyzktYtWR3GhWJxUbxAIqFqOXJnqZN405UbNkQQY CL9GKtVuLvlOx4tWd0au4PkQY9MGe+TMUf6LivfmymrpG2F/wYOlHzCqV1bNqEKhNMh5 TmMQ==
X-Gm-Message-State: AOAM533sRKuFnzQI78EgF1AY/R0fYTjnAjAGA0Yustmcel5iqi0GXh3G LmeFJOiPabXS/jWv4xtmNBjrBICggIFXniBCJrQ=
X-Google-Smtp-Source: ABdhPJxy8BLBKFLNn3IWgq7sMOkIa9z/mxLF/MsOw/h7h+oH4Bsk69pZma9UILSj2ZbaC0O+lHN5aSOgtIH1WPtig+8=
X-Received: by 2002:a02:48:: with SMTP id 69mr75854jaa.108.1603904143422; Wed, 28 Oct 2020 09:55:43 -0700 (PDT)
MIME-Version: 1.0
References: <CADxMOMf016Rq2GhRF5utT6KsiQiS3ir4QXjrnW_1+buiqtG7uA@mail.gmail.com> <AAF5364C-F337-483F-B011-A2B11779290E@mit.edu> <CAD9ie-v-RygTSh4VBnAzMDFy6O21sH-Jhh+_7QMVTT0mn_ur2g@mail.gmail.com> <30AE73A0-6A18-454A-AA20-0ECE5AEBD49A@mit.edu> <CAD9ie-s1ENJv610qGYLB=OJaX7q2g3G1zWA+YeNWoRPdktVi2A@mail.gmail.com> <14F2A48D-F6CC-4DF4-9F5F-D3A01776907A@mit.edu> <CAM8feuRWn8Hyd-kcODBTtfmNquhkKHgtONfsD-W3VrmPXGDf+A@mail.gmail.com> <CAD9ie-sckXpX_2JYPRMnk34naZ4Yi4LSsU6o4ep-OtzaWqadyw@mail.gmail.com> <CAM8feuSXN3jfUvVbV0pB-WyKFJtQ_LCPrTR+mko9N25hC7sQLA@mail.gmail.com> <CAM8feuSj2f+z4XOo7SmfU_JZm_t5-i_2scOs2WOnUDwEYOKx+g@mail.gmail.com> <CAD9ie-ujooRXmUAzL6=crcVAfZ3U4ey-fJu1meZgnDi+2JcL2A@mail.gmail.com> <CAM8feuRWN7y7Cyqrr=eTQB3HXOchVezi57rmpoiquowvo=HhEg@mail.gmail.com> <CADxMOMcKiKYUfNQR7T17yBLxnK1TNh74fi+xPkOCZwi9dP+ByQ@mail.gmail.com>
In-Reply-To: <CADxMOMcKiKYUfNQR7T17yBLxnK1TNh74fi+xPkOCZwi9dP+ByQ@mail.gmail.com>
From: Fabien Imbault <fabien.imbault@gmail.com>
Date: Wed, 28 Oct 2020 17:55:32 +0100
Message-ID: <CAM8feuQbzd8e_xUEEAUd42YrPgj_6k0c+djz_KSkiOJ2VK_+Sw@mail.gmail.com>
To: Mika Boström <mika.bostrom@smarkets.com>
Cc: Dick Hardt <dick.hardt@gmail.com>, Justin Richer <jricher@mit.edu>, GNAP Mailing List <txauth@ietf.org>
Content-Type: multipart/alternative; boundary="000000000000b8fa5b05b2be081d"
Archived-At: <https://mailarchive.ietf.org/arch/msg/txauth/EyscpKrjOA0neI7H9mF2WBuZMqg>
Subject: Re: [GNAP] Feedback on polymorphism
X-BeenThere: txauth@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: <txauth.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/txauth>, <mailto:txauth-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/txauth/>
List-Post: <mailto:txauth@ietf.org>
List-Help: <mailto:txauth-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/txauth>, <mailto:txauth-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 28 Oct 2020 16:55:53 -0000
Thanks for the great feedback. Your concern is very valid. My implementation is in rust, which makes life easier in that specific case. So I'm not a golang specialist but I guess the transcription of json strings/arrays into go structs would work around the lines described by https://medium.com/@alexkappa/json-polymorphism-in-go-4cade1e58ed1 When we have a more formalized json schema, I suggest we make a library of json examples and some related code samples in mainstream languages, to check it is feasible for everyone. Cheers, Fabien On Wed, Oct 28, 2020 at 5:28 PM Mika Boström <mika.bostrom@smarkets.com> wrote: > Hi everyone, > > Looks like I stuck my finger in a hornets' nest. First off, apologies for > not chipping in earlier, but there was a lot of material to digest. Also, > warning: lots to read ahead. > > I'm one of those people who end up making use of AuthN/AuthZ functionality > through a library. On top of that I can see myself being roped in as a > server (AS) implementation help. So I'm approaching this from an outsider's > perspective. Someone who expects to be exposed to the eventual RFC and all > the nitty-gritty details. My relatively terse comment ended up at the top > of the aforementioned HN thread, which didn't necessarily help. Sorry about > that. > > Now, having read Justin's initial reply - and the rest of the thread - I > believe I can see where the desire for polymorphism comes from. To be > clear: I am all for strict types inside an implementation, as it will add > helpful guard-rails to the state management code paths. However, I see this > as a case of leaky abstraction. If we take the existing oauth.xyj-java code > to be the reference implementation, the choice makes logical sense: JSON is > not expressive enough to serialise arbitrary objects, so in order to avoid > writing complex payload parser(s) the internal implementation details now > leak to the protocol itself. From a purely technical perspective, it's a > cool trick. From a distance it even looks a bit like the result of protobuf > decoding, but without the generated code parts. > > But then the downside. I don't personally expect to be able to use the > reference implementation, being mostly a Python user myself. A fair number > of AS implementations will be written with languages such as Go, Python, > C#, Ruby, and JavaScript (thanks to node.js), and all of them will have to > deal with the polymorphism. From what I've read over the past couple of > days, I understand that at least Go supports custom unmarshalers from JSON > to typed structs, at the cost of an indirection. Normally when a Go code > processes JSON to a typed struct, the process is helped by field > annotations in the type definition itself. For example, if the payload for > a person in JSON was > > { > "name": "<string>", > "age": <int>, > "country": "<string>", > "city": "<string>" > } > > .. then the type definition would look like: > > type Person struct { > Name string `json:"name" > Age int `json:"age"` > Country string `json:"country"` > City string `json:"city"` > } > > When the (possibly complex) type of a given field is fixed, unmarshaling > should still be straightforward. I haven't verified, but since the > annotation only gives which field to look at for a given typed value, there > should be nothing special about that. But when the field can instead be a > union of more than one distinct types, things start to get messy. There is > no union type in the language at all, so the following construct is not > even possible: > > type Entity struct { > Resources []string `json:"resources"` > Client union(Client, string) `json:"client"` > } > > As I understand, the implicit expectation is that in the above case, the > unmarshaler detects that "client" is a string, and so expands it from an > opaque handle to the expected, populated type. Even after thinking about > the ramifications over the past few days I remain confused, because I don't > see how the commonly used annotations could work. If the expectation is > that protocol implementations should use strong types, then the use of > polymorphic JSON is very likely to make things _more_ complicated for > non-reference implementations. > > Hence my concern. I'm afraid that the leaky abstraction, while making the > reference implementation more robust and straightforward, contributes to > making other implementations less robust. And this being a security > protocol, the potential for brittle and/or confused implementations is > terrifying. > > I am a fan of reducing complexity, and from what I can see, for the > reference implementation the polymorphic approach actually does that. But > I'm afraid it does so at others' expense. Languages have their individual > constraints, idioms and best practices. If parsing a protocol payload > introduces low-level complexities and encourages to go against common > practices, that is an invitation for problems. I am aware that my choice of > words in the HN thread was likely to put people on defense, and for that I > apologise. But I do believe that the choice of polymorphic JSON is going to > make the life and use of other implementations notably less boring than > people in general would prefer. > > Cheers, > Mika > > On Mon, 26 Oct 2020 at 02:04, Fabien Imbault <fabien.imbault@gmail.com> > wrote: > >> Hi Dick, >> >> Well technically yes. Obviously the client can present any interface it >> seems fit. >> >> Still there's the question of the common model we want to present to the >> outside world and supported by the protocol itself (which client libraries >> all build upon). >> >> But beneath the polyphormism question, the HN debate seems on the surface >> a lot like the original xyz (polyphormism goes along with the reduced >> endpoint model) vs xauth (a bit closer to OAuth2 in spirit, and where the >> client design has more latitude). Just explained differently, by outside >> people with different agendas. >> >> Which is a bit weird because many of the critics on HN (who criticize >> polyphormism) also seem to really dislike OAuth in the first place (the >> inconsistencies are partially due to a bunch of different people >> commenting). >> >> Really to me there's no fundamental truth behind that question. It's a >> matter of preference and priorities in the design. Whatever choices we >> make, we'll have to be prepared to explain and justify them in the open, >> even to some people that will dislike pretty much whatever we do (because >> it's fun to look smart and critize without proposing alternatives). And we >> owe these answers to people like Mika, who genuinely try to make the best >> of it. >> >> Fabien >> >> Le lun. 26 oct. 2020 à 00:58, Dick Hardt <dick.hardt@gmail.com> a écrit : >> >>> Hi Fabien >>> >>> A library developer can provide whatever abstraction layer makes sense >>> for the library's target audience and language. >>> >>> If the client library developer wants to use polymorphism in the >>> interface presented to the user's of the library, the library developer can >>> do that independent of polymorphism in the protocol, and vice versa >>> >>> => polymorphism in the protocol has no impact on client library >>> developers >>> >>> >>> ᐧ >>> >>> On Sat, Oct 24, 2020 at 3:40 PM Fabien Imbault <fabien.imbault@gmail.com> >>> wrote: >>> >>>> I'm just realizing your "least to most important" might actually say >>>> the same as what I was trying to say. So I'm not even sure what we're >>>> arguing against :-) >>>> >>>> In brief my point if it wasn't clear is that we should be crystal clear >>>> on where we put the cursor of simplicity, because this can mean different >>>> things for different people and different roles. >>>> And as we see on HN we need to better explain our design choices. >>>> >>>> >>>> Le dim. 25 oct. 2020 à 00:25, Fabien Imbault <fabien.imbault@gmail.com> >>>> a écrit : >>>> >>>>> Hi Dick, >>>>> >>>>> Independantly from the debate on polyphormism, I beg to differ on your >>>>> order preference. >>>>> >>>>> Your assumption is that AS devs matter the most, because they're >>>>> doing the important security implementation. But eating our own dogfood >>>>> might help a lot to change that view. Most security issues occur because >>>>> users of the spec are unable to deal with the complexity that is passed >>>>> onto them. >>>>> >>>>> 99% of the people that will actually use the output of the work are >>>>> application developers (client or RS) and their own users. >>>>> >>>>> Our intent as well as the protocol drive the usage. Client libraries >>>>> may help, but they're not a silver bullet, especially because GNAP >>>>> ultimately has no control about what people do there (for better or worse). >>>>> And everything we do here will help get to the better part. >>>>> >>>>> I'm not saying we don't intend to also care about AS developers >>>>> (beginning with ourselves) but it's a second order optimisation. And since >>>>> it's a tendancy we're leaning towards by default, I'm pretty sure we won't >>>>> forget that anyway. >>>>> >>>>> Fabien >>>>> >>>>> >>>>> >>>>> Le sam. 24 oct. 2020 à 23:50, Dick Hardt <dick.hardt@gmail.com> a >>>>> écrit : >>>>> >>>>>> I'm confused by your logic Fabien. >>>>>> >>>>>> If a client library developer wants to expose polymorphism, they can >>>>>> do that independent of what is in the protocol. >>>>>> >>>>>> I differ on who our stakeholders are. >>>>>> >>>>>> I think our stakeholders are in least to most important: >>>>>> >>>>>> >>>>>> - AS developer >>>>>> - RS developer >>>>>> - client developer >>>>>> - user >>>>>> >>>>>> >>>>>> A client library developer can expose whatever interface they want to >>>>>> simplify implementation. >>>>>> >>>>>> I list the user so that we don't lose site of a critical role. >>>>>> >>>>>> /Dick >>>>>> >>>>>> >>>>>> ᐧ >>>>>> >>>>>> On Fri, Oct 23, 2020 at 6:27 PM Fabien Imbault < >>>>>> fabien.imbault@gmail.com> wrote: >>>>>> >>>>>>> Hi there, >>>>>>> >>>>>>> Let me try to approach the issue under a different light. More like >>>>>>> a product manager would deal with feature selection to make it intuitive >>>>>>> for its users. >>>>>>> >>>>>>> For most people, riding a bike is far easier than using a unicycle. >>>>>>> Feels more stable. And yet it's way easier to design for a single wheel >>>>>>> than to build with 2. Because then you'll need a lot more accessories >>>>>>> (chain, chain ring, etc.). Even so producing a bike doesn't have to be a >>>>>>> brittle process, it can be industrialized. >>>>>>> >>>>>>> Back to the GNAP topic. >>>>>>> Ultimately we should strive to make the spec as simple as can be. >>>>>>> But we need to ask: simple for whom? For the bike owner or for the bike >>>>>>> vendor? >>>>>>> (short answer: the priority should be simplicity for spec users, not >>>>>>> spec implementers and even less spec designers). >>>>>>> >>>>>>> The initial question that is asked is very interesting: isn't the >>>>>>> design flawed if GNAP is using json polyphormism? Or if the AS needs to >>>>>>> handle the state of the request? Or if we must handle token revocation? Or >>>>>>> if we are looking for a global unique identifier? The argument stems of the >>>>>>> fact that is still arguably harder and more error prone to implement. Fair >>>>>>> enough. >>>>>>> >>>>>>> From a spec implementer's perspective, it may well be more complex. >>>>>>> It mostly impacts the json library you'll end up using, plus a bit of >>>>>>> input/output decoration around it. Even golang provides utilities for this, >>>>>>> despite not exactly being made for this kind of purpose. >>>>>>> My practical experience implementing it is that it's not that big a >>>>>>> deal. I mean, I wished it could be simpler, but it's manageable and there >>>>>>> are other ways to reach levels of insurance that it does work as intended >>>>>>> (json schema, test cases to validate the implementation, etc.). Arguably it >>>>>>> is still easier from an implementation perspective than say, json-ld, which >>>>>>> is massively used in the SSI community. >>>>>>> >>>>>>> But ultimately who are we designing for? Are we striving to go easy >>>>>>> on the spec implementer? Or are we trying to make sure end-developers using >>>>>>> the client libraries won't shoot themselves in the foot? >>>>>>> >>>>>>> The job to be done (JTBD), from the end-developer's perspective, is >>>>>>> to efficiently ship an application. And provide authN/authZ capabilities >>>>>>> for end-users by relying on some well known implementation. >>>>>>> In turn, this spec implementer will rely on cryptographic utility >>>>>>> libraries that deals internally with the complexity of their own domain, so >>>>>>> that we don't have to. And here we could launch another HN flame war that >>>>>>> starts with the title "JWT sucks because". Which does have its set of very >>>>>>> real issues but that's beyond the point. >>>>>>> Note that any decent flamewar will be efficiently fueled by people >>>>>>> hating medium. Is it outrageous for blog posts to be behind a paywall? >>>>>>> Maybe but it's even more outrageous to lack consistency, either by not >>>>>>> knowing how to get around a paywall if you're into a hacker punk movement, >>>>>>> or on the contrary by to not paying a subscription if you believe that >>>>>>> surveillance capitalism, to reuse Zuboff's terms, should be eradicated. >>>>>>> What likely seems an unnecessary sidenote tries to illustrate the >>>>>>> point: for Justin it was easier to publish on medium, because as a blog >>>>>>> publisher, you might not want to deal with hosting your own blog. But maybe >>>>>>> as a reader you'll find that annoying. Different audiences, different JTBD, >>>>>>> different tradeoffs. >>>>>>> >>>>>>> Polyphormism is a tool that enables the end-developer to have >>>>>>> minimal knowledge of what it means to deal with a GNAP client library. You >>>>>>> prepare the request, send to the endpoint and you're good to go. Massively >>>>>>> simpler than OAuth2 or any similar protocol by the way (as anyone with >>>>>>> teaching experience on the subject might acknowledge). And there's a lot >>>>>>> more to be done to make sure we indeed reduce the complexity for the >>>>>>> end-developer and the end-user. >>>>>>> >>>>>>> If we find a better way to deal with that simplicity balance, I'm >>>>>>> all in. But the arguments need to be way more convincing than just saying >>>>>>> that it may be difficult to implement or validate. >>>>>>> >>>>>>> Cheers. >>>>>>> Fabien >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> Le ven. 23 oct. 2020 à 22:35, Justin Richer <jricher@mit.edu> a >>>>>>> écrit : >>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Oct 23, 2020, at 3:52 PM, Dick Hardt <dick.hardt@gmail.com> >>>>>>>> wrote: >>>>>>>> >>>>>>>> Justin >>>>>>>> >>>>>>>> I did note that I was the one that argued for instance_id being in >>>>>>>> the object. Since it is in the object in the current draft, not including a >>>>>>>> pass by reference option would be preferable. >>>>>>>> >>>>>>>> As for concrete examples: >>>>>>>> - version of client >>>>>>>> - version of OS >>>>>>>> - security attestation of OS / device >>>>>>>> - location of client device >>>>>>>> - network client is operating on >>>>>>>> >>>>>>>> These are all attributes of the client that an AS may require on >>>>>>>> the initial grant request, and in future grant requests (which is when an >>>>>>>> instance_id) would be used. >>>>>>>> >>>>>>>> >>>>>>>> This is where our interpretations differ: I don’t see these as >>>>>>>> “attributes of the client” in the same way that the key, display >>>>>>>> information, class identifiers, and other items currently represented by an >>>>>>>> instance_id are attributes of the client instance. The attestation >>>>>>>> components don’t modify the instance so much as present additional >>>>>>>> information on top of the client instance itself. This is why I argue that >>>>>>>> they ought to be handled in a separate object, so you’d have something like >>>>>>>> this strawman: >>>>>>>> >>>>>>>> { >>>>>>>> >>>>>>>> posture: { >>>>>>>> software_version: 1.2.3, >>>>>>>> os_version: 14.3.2 >>>>>>>> device_attestation: { … some structure or signed blob? … } >>>>>>>> location: { lat: …, lon: …, alt: … } >>>>>>>> }, >>>>>>>> >>>>>>>> client: “client-541-ab" >>>>>>>> >>>>>>>> } >>>>>>>> >>>>>>>> This is a more fundamental question about GNAP than whether the >>>>>>>> syntax uses polymorphism: this is about GNAP being very explicit about the >>>>>>>> data model of its elements. OAuth 2’s incredibly loose and broad model of >>>>>>>> what the term “client” is referring to, exactly, is deeply problematic in >>>>>>>> practice. We’re even seeing that in the OAuth 2.1 work with having to >>>>>>>> define a “credentialed client”, and even then that doesn’t fully capture >>>>>>>> the different aspects that are out there. I think we’re getting closer here >>>>>>>> in GNAP with explicit definition of “client instance”, but we still need to >>>>>>>> be more precise about what exactly a client instance includes, and what it >>>>>>>> does not. >>>>>>>> >>>>>>>> — Justin >>>>>>>> >>>>>>>> >>>>>>>> /Dick >>>>>>>> >>>>>>>> ᐧ >>>>>>>> >>>>>>>> On Fri, Oct 23, 2020 at 12:42 PM Justin Richer <jricher@mit.edu> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> Dick, >>>>>>>>> >>>>>>>>> As you’ll recall, I argued against including the client instance >>>>>>>>> identifier inside of the object as a mutually-exclusive field precisely >>>>>>>>> because of the principle violation that you are pointing out here, and so >>>>>>>>> it’s important to point out that the current text is a compromise that >>>>>>>>> needs to be examined in the wider experience of the working group. I am on >>>>>>>>> the side of removing the mutually-exclusive “instance_id” option within an >>>>>>>>> object, but this needs to be explored. >>>>>>>>> >>>>>>>>> The crux of my argument is that is exactly a case of >>>>>>>>> pass-by-reference vs pass-by-value, and that runtime attestations are not >>>>>>>>> part of the “client instance” value itself but rather belong outside of >>>>>>>>> that object in a another part of the request. As stated in the editorial >>>>>>>>> notes in this section, we need to look carefully at how these concepts fit >>>>>>>>> within the model and where we would want to put them. Without concrete >>>>>>>>> examples of what these extensions look like and how they’re generated, that >>>>>>>>> is nearly impossible to do at this stage. I look forward to seeing examples >>>>>>>>> of this kind of data and how it can fit into the protocol. >>>>>>>>> >>>>>>>>> — Justin >>>>>>>>> >>>>>>>>> On Oct 23, 2020, at 3:07 PM, Dick Hardt <dick.hardt@gmail.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>> Hey Justin, >>>>>>>>> >>>>>>>>> As the draft has evolved, I question the continued use of >>>>>>>>> polymorphism. Note that I appreciate the elegance of using a string for >>>>>>>>> pass-by-reference, and an object for pass-by-value. >>>>>>>>> >>>>>>>>> In the current draft, the >>>>>>>>> >>>>>>>>> Every time you create or process a field it will mean only one >>>>>>>>> thing, and there’s only one field to look at to answer a question. >>>>>>>>> >>>>>>>>> >>>>>>>>> is violated in 2.3.1. Identifying the RC Instance >>>>>>>>> <https://tools.ietf.org/html/draft-ietf-gnap-core-protocol-00#section-2.3.1> >>>>>>>>> >>>>>>>>> >>>>>>>>> instance_id An identifier string that the AS can use to >>>>>>>>> identify the >>>>>>>>> particular instance of this RC. The content and structure >>>>>>>>> of this >>>>>>>>> identifier is opaque to the RC. >>>>>>>>> >>>>>>>>> "client": { >>>>>>>>> "instance_id": "client-541-ab" >>>>>>>>> } >>>>>>>>> >>>>>>>>> If there are no additional fields to send, the RC MAY send the >>>>>>>>> instance identifier as a direct reference value in lieu of the >>>>>>>>> object. >>>>>>>>> >>>>>>>>> "client": "client-541-ab" >>>>>>>>> >>>>>>>>> >>>>>>>>> The instance identifier can be sent two ways. Polymorphism is a >>>>>>>>> convenience for the client, but requires the server to have two code paths >>>>>>>>> for "instance_id". We discussed this in the design team, and I argued for >>>>>>>>> having "instance_id" in the "client" object so that any updates, such as >>>>>>>>> new devices assertions, could be in the "client" object. As noted above, >>>>>>>>> while I appreciate the elegance of using a string (handle) to reference a >>>>>>>>> previously provided object, it complicates how to update an existing object >>>>>>>>> while providing the reference. >>>>>>>>> >>>>>>>>> In your example of the "key" object below, setting "proof" to >>>>>>>>> bearer would avoid the issue you describe: >>>>>>>>> >>>>>>>>> { >>>>>>>>> "key": { >>>>>>>>> "proof": "bearer" >>>>>>>>> } >>>>>>>>> } >>>>>>>>> >>>>>>>>> In your example, when processing the "key" object, code is having >>>>>>>>> to check both the JSON type of the property, as well as check the value of >>>>>>>>> the "proof" property. In the example I provided, only the value of "proof" >>>>>>>>> needs to be checked. The "proof" property is acting as a type for the "key" >>>>>>>>> object. >>>>>>>>> >>>>>>>>> Not being a Java programmer, I don't know how this would work in a >>>>>>>>> Java implementation, but node.js, the processing would need to be done as >>>>>>>>> above. >>>>>>>>> >>>>>>>>> On a related note, there was significant negative feedback on >>>>>>>>> handles and polymorphism in the Hacker News article >>>>>>>>> https://news.ycombinator.com/item?id=24855750 >>>>>>>>> >>>>>>>>> /Dick >>>>>>>>> >>>>>>>>> >>>>>>>>> On Fri, Oct 23, 2020 at 10:20 AM Justin Richer <jricher@mit.edu> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> Hi Mika, >>>>>>>>>> >>>>>>>>>> Thanks for bringing this topic here — I was able to see the forum >>>>>>>>>> discussion that brought you here, and hopefully I can help clear up what I >>>>>>>>>> mean with how polymorphism is used in the proposal. The short version is >>>>>>>>>> that the goal is to *avoid* the kinds of ambiguity that make >>>>>>>>>> insecure protocols, and so in that goal we’re fully aligned. I think that >>>>>>>>>> using polymorphism in very specific ways can help that goal — just as I >>>>>>>>>> agree that misusing it or applying it sloppily can lead to ambiguous and >>>>>>>>>> insecure systems. >>>>>>>>>> >>>>>>>>>> Some background: I built out the XYZ protocol (one of the >>>>>>>>>> predecessors to the initial GNAP Draft) in Java using strongly typed >>>>>>>>>> parsers and Java objects specifically to prove to myself that it could be >>>>>>>>>> done in a way that made any sense in the code. (My own open source >>>>>>>>>> implementation is at https://github.com/bspk/oauth.xyz-java, but >>>>>>>>>> note that it’s not yet up to date with the GNAP spec). It was important to >>>>>>>>>> me that I be able to use the system-wide configured parsers to implement >>>>>>>>>> this and not have to resort to stepping through elements completely by >>>>>>>>>> hand. Java doesn’t make it simple to get the hooks into the right places >>>>>>>>>> (especially with the Jackson parser that I used), but it is definitely >>>>>>>>>> possible to create a deterministic and strongly-typed parser and serializer >>>>>>>>>> for this kind of data structure. Some of the rationale for using >>>>>>>>>> polymorphism is covered in the trailing appendix of the draft document ( >>>>>>>>>> https://www.ietf.org/archive/id/draft-ietf-gnap-core-protocol-00.html#name-json-structures-and-polymor), >>>>>>>>>> but it’s still good to discuss this here as the working group decides which >>>>>>>>>> approaches to take. >>>>>>>>>> >>>>>>>>>> The driving reason for using polymorphism at the protocol level >>>>>>>>>> was to simplify the protocol and make it :more: deterministic to create and >>>>>>>>>> process, not less. Every time you create or process a field it will mean >>>>>>>>>> only one thing, and there’s only one field to look at to answer a question. >>>>>>>>>> Without polymorphic field values, you usually need to rely on mutual >>>>>>>>>> exclusivity of fields, which is prone to failure and requires additional >>>>>>>>>> error checking. Take for example the key binding of access tokens. An >>>>>>>>>> access token could be bound to the RC’s key used during the request, to a >>>>>>>>>> different key chosen by the AS, or it could be a bearer token with no key >>>>>>>>>> at all. By making the “key” field polymorphic, we can define it in terms of >>>>>>>>>> boolean values and objects and express this set of mutually-exclusive >>>>>>>>>> options in a non-ambiguous way. Without that, you’d need to have different >>>>>>>>>> fields for the options and include additional checks in your parser to make >>>>>>>>>> sure they weren’t sent simultaneously, otherwise you could get hit with >>>>>>>>>> this potential security vulnerability in an object: >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> key: { >>>>>>>>>> proof: httpsig, >>>>>>>>>> jwk: { … key value … } >>>>>>>>>> }, >>>>>>>>>> bearer_token: true, >>>>>>>>>> bind_to_rc_key: true >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> This would be an illegal object as per this alternate proposal, >>>>>>>>>> but then you’d have to check each field and make sure it wasn’t put next to >>>>>>>>>> others in the same object. I’ve done this exercise with many other >>>>>>>>>> protocols and it’s both error prone and easy to ignore since all the “good” >>>>>>>>>> examples would pass code that doesn’t check this. With the polymorphic >>>>>>>>>> approach to this same field, each of these three mutually-exclusive states >>>>>>>>>> is written in a way that they cannot be sent together. It’s not just >>>>>>>>>> illegal, it’s impossible and enforced by the syntax of JSON itself. >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> key: { >>>>>>>>>> proof: httpsig, >>>>>>>>>> jwk: { … key value … } >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> // bearer token >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> key: false >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> // bound to the RC’s presented key >>>>>>>>>> >>>>>>>>>> { >>>>>>>>>> key: true >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> If someone sends a different type for this field, like an array >>>>>>>>>> or number or a null, this doesn’t have a defined interpretation in the >>>>>>>>>> protocol and would be a protocol level error. >>>>>>>>>> >>>>>>>>>> While it might sound like polymorphism means that any field could >>>>>>>>>> have any type or value, the opposite is true: each possible value is >>>>>>>>>> explicitly typed, it’s just that there are potentially different types that >>>>>>>>>> express meaning for the field. This applies to all members of all objects >>>>>>>>>> (dictionaries) as well as all members of an array (list). Every time you >>>>>>>>>> process a field value or other element, you look at the type and then the >>>>>>>>>> value to determine what to do with that typed value. >>>>>>>>>> >>>>>>>>>> In your example below, each field within the dictionary would >>>>>>>>>> also need to be typed, and each type would need to have a clear indication >>>>>>>>>> of its meaning. To take your strawman key format below, the “modulus” field >>>>>>>>>> could be defined polymorphically as either a “bigint” (a JSON number) or an >>>>>>>>>> “encoded string” (a JSON string). The definition would further say what >>>>>>>>>> exactly the encoding of the string would be. That means that when you read >>>>>>>>>> the “modulus” field there wouldn’t be any confusion on what the value was >>>>>>>>>> or how it was represented, regardless of the input format. Seeing a number >>>>>>>>>> there means exactly one interpretation and seeing a string means exactly >>>>>>>>>> one (different) interpretation — but importantly, both of them are a >>>>>>>>>> “modulus”, since that’s the field that determines the type. An >>>>>>>>>> implementation would likely use an internal BigInteger type of object to >>>>>>>>>> represent the field value after parsing, so the question is how to go from >>>>>>>>>> the JSON value (which is typed) into the BigInteger value.You don’t just >>>>>>>>>> apply the type rules on the “public_key” field, you apply it to all >>>>>>>>>> sub-fields of that object. >>>>>>>>>> >>>>>>>>>> So let’s dig into the specific bug you bring up in the strawman, >>>>>>>>>> because it’s interesting: A JSON encoder that encodes numbers as strings, >>>>>>>>>> and not numbers, is not compliant with the JSON definitions of the field in >>>>>>>>>> question. For another example, the quoted string value of “true” is not >>>>>>>>>> equivalent to the boolean value true in JSON, and they shouldn’t be treated >>>>>>>>>> the same by a parser implementation when mapping to a concrete object. It’s >>>>>>>>>> in this kind of automated guessing that this class of bugs occur, and >>>>>>>>>> that’s going to be the case whether or not you take advantage of JSON’s >>>>>>>>>> polymorphic nature. I’ve run into cases where a parser library was trying >>>>>>>>>> to be overly “helpful” in doing this kind of mapping, but ended up >>>>>>>>>> introducing errors in more strict components downstream. This is something >>>>>>>>>> that protocol designers need to be aware of and guard against in the design >>>>>>>>>> of the protocol to reduce possible ambiguities. Within GNAP today, we >>>>>>>>>> generally have things that branch whether they’re an object (for a rich >>>>>>>>>> description of something) or some non-structured special value (for a >>>>>>>>>> reference or other item). >>>>>>>>>> >>>>>>>>>> The design team created some simple JSON Schemas for parts of the >>>>>>>>>> protocol during our discussion, but we didn’t include them in the design >>>>>>>>>> document due to both lack of time to keep it updated with the rapid changes >>>>>>>>>> to the protocol during the design team discussion, and not knowing if there >>>>>>>>>> would be interest in such material. I personally think it would be helpful >>>>>>>>>> to include as an informative reference in the final document, but that’s >>>>>>>>>> something for the working group to take up eventually. >>>>>>>>>> >>>>>>>>>> — Justin >>>>>>>>>> >>>>>>>>>> On Oct 23, 2020, at 10:18 AM, Mika Boström < >>>>>>>>>> mika.bostrom=40smarkets.com@dmarc.ietf.org> wrote: >>>>>>>>>> >>>>>>>>>> Hello, everyone. >>>>>>>>>> >>>>>>>>>> For background: GNAP/TxAuth/XYZ/Oauth3 came up on a discussion >>>>>>>>>> forum and when I made note about certain concerns, I was requested to send >>>>>>>>>> my comments to this working group. >>>>>>>>>> >>>>>>>>>> In short, I believe that the use of polymorphic JSON in the >>>>>>>>>> protocol invites subtle and confusing implementation problems. I also >>>>>>>>>> searched through the WG archives, and noticed that similar concerns were >>>>>>>>>> noted, briefly, in a thread in July. >>>>>>>>>> >>>>>>>>>> The problem with polymorphic values, as I see it, is that >>>>>>>>>> implementations will need to branch on the (inferred) type of a given >>>>>>>>>> field. This isn't quite as bad if the types are strictly different, but >>>>>>>>>> allows for subtle bugs when the value in question is a dictionary. What >>>>>>>>>> makes this unappealing is that "subtle bugs" in security protocols have a >>>>>>>>>> habit of turning into vulnerabilities. >>>>>>>>>> >>>>>>>>>> Let's say we have these imaginary payloads, both possible and >>>>>>>>>> valid in the same protocol step: >>>>>>>>>> >>>>>>>>>> # payload 1 >>>>>>>>>> { >>>>>>>>>> ..., >>>>>>>>>> "public_key": { >>>>>>>>>> "alg": "rsa", >>>>>>>>>> "modulus": <BIGINT> >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> # payload 2 >>>>>>>>>> { >>>>>>>>>> ..., >>>>>>>>>> "public_key": { >>>>>>>>>> "alg": "rsa", >>>>>>>>>> "modulus": "<encoded string>" >>>>>>>>>> } >>>>>>>>>> } >>>>>>>>>> >>>>>>>>>> In both cases, the type of "public_key" field is a dictionary. In >>>>>>>>>> both cases, they even have the same keys. However, the values in the >>>>>>>>>> dictionaries are entirely different, and an implementation will have to >>>>>>>>>> branch to at least two possible decoding mechanisms. To make things worse, >>>>>>>>>> some JSON implementations may choose to encode non-dictionary values as >>>>>>>>>> strings, so it is possible for an originator to transmit what they expect >>>>>>>>>> and believe to be payload 1 format, but which the receiver will interpret >>>>>>>>>> to be in payload 2 format. And if the encoded string contains only digits, >>>>>>>>>> it will even parse correctly as a bignum. >>>>>>>>>> >>>>>>>>>> While the above is clearly a manufactured scenario, it >>>>>>>>>> nonetheless demonstrates the potential for logic bugs with polymorphic >>>>>>>>>> JSON. With richer types and more complex dictionaries, there will surely be >>>>>>>>>> more room for errors. >>>>>>>>>> >>>>>>>>>> Ambiguity in protocols is always a source of implementation >>>>>>>>>> complexity and interoperability snags, but in an AuthN/AuthZ protocol it is >>>>>>>>>> worse: it's terrifying. If GNAP/Oauth3 is intended to supersede Oauth1/2, >>>>>>>>>> wouldn't it be in everyone's interest to keep implementation complexity and >>>>>>>>>> mistake potential to a minimum? >>>>>>>>>> >>>>>>>>>> Best regards, >>>>>>>>>> Mika >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> Mika Boström >>>>>>>>>> Smarkets >>>>>>>>>> -- >>>>>>>>>> TXAuth mailing list >>>>>>>>>> TXAuth@ietf.org >>>>>>>>>> https://www.ietf.org/mailman/listinfo/txauth >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> TXAuth mailing list >>>>>>>>>> TXAuth@ietf.org >>>>>>>>>> https://www.ietf.org/mailman/listinfo/txauth >>>>>>>>>> >>>>>>>>> ᐧ >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>> -- >>>>>>>> TXAuth mailing list >>>>>>>> TXAuth@ietf.org >>>>>>>> https://www.ietf.org/mailman/listinfo/txauth >>>>>>>> >>>>>>> > > -- > Mika Boström > Smarkets >
- [GNAP] Feedback on polymorphism Mika Boström
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Dick Hardt
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Dick Hardt
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Dick Hardt
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Yaron Sheffer
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Yaron Sheffer
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Huang, Peter (HPE HQ)
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Yaron Sheffer
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Dick Hardt
- Re: [GNAP] Feedback on polymorphism Dick Hardt
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Mika Boström
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Yaron Sheffer
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Andrii Deinega
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Yaron Sheffer
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Dick Hardt
- Re: [GNAP] Feedback on polymorphism Fabien Imbault
- Re: [GNAP] Feedback on polymorphism Justin Richer
- Re: [GNAP] Feedback on polymorphism Fabien Imbault