Re: [GNAP] Feedback on polymorphism

Mika Boström <mika.bostrom@smarkets.com> Wed, 28 October 2020 16:28 UTC

Return-Path: <mika.bostrom@smarkets.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 6A04F3A005F for <txauth@ietfa.amsl.com>; Wed, 28 Oct 2020 09:28:57 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.097
X-Spam-Level:
X-Spam-Status: No, score=-2.097 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, 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=smarkets.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 gzTy_RHdmHlN for <txauth@ietfa.amsl.com>; Wed, 28 Oct 2020 09:28:52 -0700 (PDT)
Received: from mail-oi1-x22c.google.com (mail-oi1-x22c.google.com [IPv6:2607:f8b0:4864:20::22c]) (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 899BF3A0062 for <txauth@ietf.org>; Wed, 28 Oct 2020 09:28:52 -0700 (PDT)
Received: by mail-oi1-x22c.google.com with SMTP id w191so175866oif.2 for <txauth@ietf.org>; Wed, 28 Oct 2020 09:28:52 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=smarkets.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=G6VlBqucXva9KjrokR87UNiPr1+U/lbIoSmGYWZa1sE=; b=QyTYu2oAXfz2f/kb8gcSOrM5wikWJzoo9zuUmzebkn/yqu0Yyhx4kf4EIfUYvcNOB1 2AacgCzCdPY/kq1E/L2rDnOC9Cmuj/04A66+VyJf4RfOUW/JM4J1hnYjMhW9pacdnmbF 6ypc/WyMkKWX4jiXMcblbR1d9+DQUYx1CWbvmzQQ2h3/Iny0TBfd85+8xoCtadjO3RUI 9KBvb8eQy3GnpymWxR/BNGpFpLQ7XmVr8UBRL66cLQLTl3N0zRBrCAa46682HlyB3MIS ay+b9C0M/ekQ/figBbAkVRnceWx6fVWbdcmpBuRXP1A5M8OMpvaAWTlfVuhuxN807/rQ gJEg==
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=G6VlBqucXva9KjrokR87UNiPr1+U/lbIoSmGYWZa1sE=; b=o8I49VEeifM9X9UVCKXZbYzDKzRAX8b2IV72x0fw4ZyvR9PxwIfX07zqECwS091poA dX9XzO1j0HBO4AXROXMBVWVJ6Jk258bcUJjrDWEmUQMom3OgXgY9otJRI1mpyrz9NpcC 4O6pqt+jpAl1c/qAOEG+uiWbhlPMwx2mlvuJnVOHIrpoKkc/mbS6nwfU2xbwJLlqcIIR KvYnLWvjeqPGyb1vYXzXcD47C2/BnsathlWac9QkNGGw8IEMzNvsy/k5iMw0wMPAitkn 8rirc3bOG4Iz4PjWLBCjYIbVki2jCxW/6Uzn6rcWiG6pZFu0Stwy8ua8fDdn4D6+zHqu 8rmg==
X-Gm-Message-State: AOAM530dO3zGqqw3tQFBRHJ+clH1a54SPWAv/y+aAjXcXyYNyQ21xYRz kdolpqmkKw1Uj5HG5gA6Mt6Zsn+7dEQ+wZ0nxKVxZnIdgLWthgej
X-Google-Smtp-Source: ABdhPJxaHwjtyJ0HgRIqW9xAnjSke98WzuBGFsvigqqql6q4/wwORn9lfIRtr9Q7Hj3e8TWbUmmo7dwU9NipKavm2GI=
X-Received: by 2002:aca:3687:: with SMTP id d129mr172424oia.100.1603902531400; Wed, 28 Oct 2020 09:28:51 -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>
In-Reply-To: <CAM8feuRWN7y7Cyqrr=eTQB3HXOchVezi57rmpoiquowvo=HhEg@mail.gmail.com>
From: Mika Boström <mika.bostrom@smarkets.com>
Date: Wed, 28 Oct 2020 16:28:39 +0000
Message-ID: <CADxMOMcKiKYUfNQR7T17yBLxnK1TNh74fi+xPkOCZwi9dP+ByQ@mail.gmail.com>
To: Fabien Imbault <fabien.imbault@gmail.com>
Cc: Dick Hardt <dick.hardt@gmail.com>, Justin Richer <jricher@mit.edu>, GNAP Mailing List <txauth@ietf.org>
Content-Type: multipart/alternative; boundary="000000000000a38b3305b2bda89f"
Archived-At: <https://mailarchive.ietf.org/arch/msg/txauth/yBJHM1DbsM7C4odaHCM254J3sR4>
X-Mailman-Approved-At: Wed, 28 Oct 2020 09:34:53 -0700
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:28:58 -0000

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