Re: [Txauth] Polymorphism (Was: JSON Schema?)

Dick Hardt <dick.hardt@gmail.com> Fri, 10 July 2020 20:54 UTC

Return-Path: <dick.hardt@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 AC71F3A097E for <txauth@ietfa.amsl.com>; Fri, 10 Jul 2020 13:54:20 -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 LaguzcgRR1Ii for <txauth@ietfa.amsl.com>; Fri, 10 Jul 2020 13:54:17 -0700 (PDT)
Received: from mail-lj1-x243.google.com (mail-lj1-x243.google.com [IPv6:2a00:1450:4864:20::243]) (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 A06193A097B for <txauth@ietf.org>; Fri, 10 Jul 2020 13:54:16 -0700 (PDT)
Received: by mail-lj1-x243.google.com with SMTP id h19so7884852ljg.13 for <txauth@ietf.org>; Fri, 10 Jul 2020 13:54:16 -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=tt6KyIMwupfCU0+vDpomwY7K5lnHLUKrXijGvRQO5/8=; b=QrU8fjj2vy5L3Reocp9+i7HJlDHlECwVDwEve3rBngyQW+T/smhQpcUzRi1VMQUOBZ NoGb3R2wGQBdaAoIirsTRfMkZALUm9gkC5ubtUI9Y1bWmpB83VgsfA+gXIe24u4WkqyM k7G+l9FwwEBOXQI7ovsAR6Vowue1glfBxvvp8gH4jON514niD9d6Tz11LtgCZQu6cBAA PKDqdJBxij8IsrnHNHHY8L3wUS3qPNPVTdUygZ7Xq0d0Ps8/q0I/UIkr4RCDf53ogPGk 3Yr8Iiwozlx8QnugQeT0xP3d42jYfFc4DOcCZUCqmK+pj6ha+u+t2VK2EU0y/gk7VTkq RfHQ==
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=tt6KyIMwupfCU0+vDpomwY7K5lnHLUKrXijGvRQO5/8=; b=DDjlu7viQCTe35Q80d8iinPvptkW2DfcfnAzvQE7WD+GWrn9XQ0C93CgFy1FDcoKi3 uA+7iDrFi6xqgVoMuR/cb07EM3v5uKHKo30DghkVADibnF24u+IkLytU4njmCtfduoM1 EW6uNmkOLjiKSy9GFieIwPEuXEdNAFtpSEfMShvEA4qFIx2kN4BODAulYNvJwFocubXu R7507++f45UqI9ncUABpU1vlVz2ZwtCqY+f1BQxeAWkPZ1P1LDD9wGgX5+etzcfKh3Sg FoYAW4UAUmGjgwHbC09TrSj7+NacxqozxE1eJ6UYhwTIelP/4a3TvjOOOwZzI7fs7E1n RPrw==
X-Gm-Message-State: AOAM530ERbyRUKsZMk5yKEOwkG5ePZE3aYutcl1/9dd12x2Zpz0X7JTU KsAUyjgwijFJaudo/ryXdzCAAWNl6N5hzZ07Cn4=
X-Google-Smtp-Source: ABdhPJyy1Oj2fox/QTWjf2cuvu1Mzo5mp/m47sovuluwvc5+thYrIou0FpJ4dMOM2eR+uzMohuXm6Z/UC7wtEEsood0=
X-Received: by 2002:a2e:b70b:: with SMTP id j11mr27602946ljo.142.1594414454165; Fri, 10 Jul 2020 13:54:14 -0700 (PDT)
MIME-Version: 1.0
References: <CAD9ie-vnA98pobbboS00SAHneEG52_8eMxh_sE3r3jg6gyooGg@mail.gmail.com> <E9EC90C9-7A9A-4909-8627-A161B33E941F@mit.edu> <CAD9ie-vyB8+5jS=K_qUHfvxsF2wPV5APRo+7WUDfJxNzJONJpg@mail.gmail.com> <8CC8B466-FD6F-4C23-8DAA-99B8A9BDF548@mit.edu> <CAD9ie-u9z7Mc-wNjztoOTy4N_Z9jFDc2Sb6quLspasMGAMKdSw@mail.gmail.com> <097FB93E-96DA-4DF6-8511-0B32FD321211@mit.edu> <CAD9ie-tpuisauOFGiUj65-RcYPtcvW_gZP1CAadqq5cE6P36HQ@mail.gmail.com> <EE4A7D91-1106-44CB-92BF-C3AA3649BDFE@mit.edu> <CAD9ie-saoc2FUm46r4h1B27iYK04j_skf5-zJR7EXLmWBzj=hA@mail.gmail.com> <F41A8F88-C1B4-4CE2-8573-7A03C086D25B@mit.edu> <CAD9ie-tHCg9Ti1xWuzUP5EGLAcU2cpFALErqq98+fPnD3enZCQ@mail.gmail.com> <820525FD-4556-4617-8D89-C600D8C90C33@mit.edu> <CAD9ie-uwz_Li7n9iuX_--YtWeE+HX5sWEe95nZ8Y0akYh8WTHg@mail.gmail.com> <CAD9ie-vFwjQWQZjeL1Qza9MQ5=35qbWW15umyqGhhawFWephLA@mail.gmail.com> <D3EB60DC-6040-480D-A477-C1346130DF96@mit.edu> <CAD9ie-v9MdskdG74Ou__nn9mMmN2gJT6F45mg3dPs7CzJeD7WQ@mail.gmail.com> <69082870-1A99-4912-95EA-D1B7A1C967E5@mit.edu> <CAD9ie-uJHm4UHzNqreVta6Rrm5iQ=8chAbZqfaUFX6OOyXTbow@mail.gmail.com> <D1CD3AF7-051B-4BBD-9E16-5640FB2A718F@mit.edu> <CAD9ie-v+vv0VWeCC8gxytgjaVaHUjF9XJqwLa=sdB=FPwxpGTA@mail.gmail.com> <4A77832C-9613-48BD-9CB2-EE3121E44DB0@mit.edu>
In-Reply-To: <4A77832C-9613-48BD-9CB2-EE3121E44DB0@mit.edu>
From: Dick Hardt <dick.hardt@gmail.com>
Date: Fri, 10 Jul 2020 13:53:37 -0700
Message-ID: <CAD9ie-tctw2v1WBUXUJo6hiQMV=5+KRjvWdBDnn-K=tE12ef2g@mail.gmail.com>
To: Justin Richer <jricher@mit.edu>
Cc: txauth@ietf.org
Content-Type: multipart/alternative; boundary="0000000000002a56d505aa1c8bbf"
Archived-At: <https://mailarchive.ietf.org/arch/msg/txauth/zVClw3-EZh7hZhZPc3bwuRvw7Hw>
Subject: Re: [Txauth] Polymorphism (Was: JSON Schema?)
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: Fri, 10 Jul 2020 20:54:21 -0000

Now that you are saying that the scope string is short hand for the object,
the polymorphism makes sense. There is only one type in the array, and a
string is shorthand for it. In this thread, you have talked about them
being separate things.

I just reread XYZ-08 section on resources, and there is no mention of
polymorphism, or an example of it. Given your comments that XAuth should
support both scopes and RAR, and that your proposed schema was based on
RAR, that scopes and RAR objects were different things.

Now it is clear that you are proposing that GNAP have a brand new schema
for authorization queries. And on closer inspection of your examples in
XYZ, there is no "type" in the property in the object.

So now I see the choice being:

A) reinvent a new, GNAP specific schema for requesting access to resources
(XYZ)
B) reuse the RAR and OAuth scope schemas (XAuth)

If and when another resource requesting schemas is developed, you propose
that it be a new, top level object. I'm proposing it be a new type in the
authorizations container.

Have I captured this accurately?

/Dick





On Fri, Jul 10, 2020 at 1:09 PM Justin Richer <jricher@mit.edu> wrote:

>
>
> On Jul 10, 2020, at 1:39 PM, Dick Hardt <dick.hardt@gmail.com> wrote:
>
>
>
> On Thu, Jul 9, 2020 at 5:46 PM Justin Richer <jricher@mit.edu> wrote:
>
>>
>>
>> On Jul 9, 2020, at 6:50 PM, Dick Hardt <dick.hardt@gmail.com> wrote:
>>
>>
>>
>> On Thu, Jul 9, 2020 at 12:17 PM Justin Richer <jricher@mit.edu> wrote:
>>
>>> On Jul 9, 2020, at 2:32 PM, Dick Hardt <dick.hardt@gmail.com> wrote:
>>>
>>>
>>> Looks like you missed the point of my code example, as your response is
>>> focussed on the aspects I had in comments, so let me clarify.
>>>
>>>
>>> The point seemed to be about the overall complexity and readability, and
>>> that’s what I responded to.
>>>
>>
>> It was about the complexity and readability -- of those specific lines of
>> code.
>>
>>
>> But it’s not just about those lines, it’s about the context that those
>> lines are in and the follow-on code paths that they cause. A lot of what
>> you had “in comments” for the XAuth example would have repeated what was
>> already included in the XYZ example, as I pointed out.
>>
>
> The context between those lines is pretty much the same. Yes, the XAuth
> example would have had to loop over each scope and RAR object, which is not
> that different than XYZ looping over each item, and the deciding how to
> process each item. My point is that checking the object type to decide what
> to do is an opaque decision vs checking an explicit type.
>
>
> The context is really not the same though, as you actually  point out
> here, and calling one style of type checking “opaque” vs. “explicit” is
> stylistic and not a helpful comparison. I’m not surprised to find that you
> think the way you did it is easier, especially given the disconnect we have
> of what the components of the array represent. I started with some of the
> type-field-based structures in early versions of XYZ and moved away from
> them after having bad experiences with building it. There are still a few
> parts of the XYZ protocol that have that style (the “user” section, for
> example) that I think need to be changed. I think that the data-type based
> style of polymorphism, coupled with using the left-hand-side value of
> object members to indicate type or identifier, is significantly simpler in
> design and implementation.
>
> Instead, I realized that we could get a cleaner protocol and better
> underlying code by dispatching based on the type within the protocol
> itself. I’ve gotten comments from a number of implementers that they like
> this design aspect, and I really like it myself.
>
>
>
>>
>>
>> I've used JS type polymorphism to provide a cleaner API. For example,
>> making an HTTP request. If I'm good with all the defaults, I can just
>> provide the URI as a string, if I want to change a default, I provide an
>> object and the URI is now a property of the object. Polymorphism allows the
>> caller to have a simpler interface when it is a simple operation.
>>
>> Do you have any examples of JSON polymorphism used in other protocols
>> besides in a JWT?
>>
>>
>> Sounds to me like you’re describing exactly the kind of polymorphism that
>> I’m talking about here. Use a string where it makes sense and an object
>> where it makes sense, and there’s no ambiguity in calling the function. As
>> you say, it's all about providing a cleaner API for the caller, and making
>> things consistent in the model that the caller and provider are using. It
>> takes a little bit of extra effort on the part of the API provider, but
>> that’s where the complexity cost should be paid.
>>
>
> My examples are not the same at all. The caller has a simpler version of
> passing the same object. XYZ is passing two different types, where a string
> means one thing, and an object means something else. The string is not a
> shorthand for the object.
>
>
> The string is, semantically, a shorthand for the object. That’s what I’ve
> been saying from the beginning, and I’ve put into several examples so far.
> There are two ways to add rights to an access token resulting from the
> request. So:
>
> {
>   “resources”: [ “photo” ]
> }
>
> Can really be thought of as a shorthand, for example it could expand to
> this:
>
> {
>   “resources”: [
>    {
>      “datatypes”: [ “pohoto” ],
>      “actions”: [ “read” ],
>      “locations”: [ “https://server/photoapi/“ ]
>    }
> }
>
> In this straw man, if the client wants write access to the API, it needs
> to use the object-style request to do so.
>
> It’s up to the AS, or really the API that it’s protecting, to figure out
> what that expansion really looks like, and how much of the more complex
> policy to expose. My example of processing only string-based resource
> requests was for the case where the AS only gives the shorthand version,
> and doesn’t allow detailed access into its protection policies. It’s not a
> different kind of request, it’s a shorthand, much like passing an
> identifier in lieu of a key to identify the client software instance making
> the call.
>
> But really, the point is that in both cases the string and the object *both
> represent the same kind of thing*: *a piece of access rights that the
> client is requesting at the AS which gets put into the access token.*
> Thus, having them together in a single array and processing them together
> makes sense to me. If you are thinking of strings and objects as completely
> different from each other,  you’d expect them to be handled separately, but
> I don’t think they are actually different because they both represent a
> view of the same underlying thing.
>
>
>
> In polymorphic APIs, it makes the code cleaner to pass a singular item
> when the API takes an array, or the API takes a string for the common
> property of the object which is the parameter.
>
>
> Yes, those are two examples of why it can be good. There are other reasons
> to apply it, like having an array with differently typed items that
> represent the same kind of thing underneath.
>
> Here are some code examples for both:
>
>
> // passing a singular item, a simpler version of foo(['string'])
> foo('string')
> // passing a plurality of the same item
> foo(['string1','string2','string3'])
>
> // implementation
>
> foo = ( param ) => {
>     var a = []
>     if (typeof param === 'string') {
>         a[0] = param;
>     } else if (typeof param === 'array') {
>         a = param;
>     }
>     // process array a
> }
>
>
> // pass a uri as string and accept all defaults, a simpler version of
> bar({uri:'uri'})
> bar('uri')
> // pass an object with uri and method
> bar({uri: 'uri', method: 'POST'})
>
> // implementation
> bar = ( param ) => {
>     var p = DEFAULT_OBJ;
>     if (typeof param === 'string') {
>         p.uri = param;
>     } else if (typeof param === 'object') {
>         Object.keys(param).forEach( item => {
>             p[item] = param[item];
>         });
>     }
>     // process p object
> }
>
>
> In GNAP, we could take a string rather than an array for a scope
> parameter, for example:
>
> "scope": "read"
>
>
> instead of
>
> "scope": ["read"]
>
>
> OIDC uses the latter polymorphism for
>
> {
>   "name": {"essential": true},
>   "photo": null
> }
>
> as being shorthand for
>
> {
>   "name": {"essential": true},
>   "photo": {"essential": false}
> }
>
>
> All of these are great examples of why object-type-based polymorphism is a
> good and powerful thing, and that’s the approach I’m saying we should use
> within the GNAP protocol. I would argue that the last one isn’t
> polymorphism so much as a default based on a null value (often taken as a
> special class of an “object” value anyway), but that’s splitting hairs.
>
>
>
>>
>>
>>
>>>
>>>
>>> This line (which is determining the type of the item in the array):
>>>
>>> if (typeof item === string')
>>>
>>>
>>> is implicitly stating that the item is an oauth scope.
>>>
>>>
>>> No, it is not. It is saying that it is a resource request represented as
>>> a string. One way to represent a resource request as a string is an OAuth 2
>>> style scope. And if you’re building up from an existing OAuth 2 system,
>>> then you could use a scope there. But that’s not the same as stating “the
>>> item is a scope”. In my examples, I had been trying to use the terminology
>>> that you were using, but I’m afraid that made things more unclear.
>>>
>>
>> We are comparing how to do it in XYZ vs XAuth -- so to make it apples and
>> apples, the string is a scope, since that is the use case we are looking at.
>>
>>
>> You can use a scope as the string, and if you want to think of all string
>> values in this request as all being “scopes", that’s fine, but only if you
>> can concede that the scope can mean whatever the AS wants. I think that
>> perhaps you’re putting a certain amount of semantic weight to “scope” that
>> I’m missing, though.
>>
>
> The string could be a scope, or it could be a claim such as in my "oidc"
> type example. The AS could support both scope and claims, and they could
> have overlapping string values.
>
>
> Both would represent “things that the client wants back in the access
> token”, and therefore the AS would need to differentiate. In that case I
> think it actually makes a lot more sense for the AS to define a more rich
> mechanism to request user information. In XYZ it could look like this:
>
> {
>    “resources”: [
>      {
>         “type”: “oidc_userinfo”,
>         “datatypes”: [ “email”, “phone”, “address”, “profile.photo" ]
>      }
>    ]
> }
>
> But defining the details of that kind of query is clearly outside the
> scope of GNAP (see below), and I think better suited to an identity
> protocol built on top of GNAP.
>
>
>
>
>>
>>
>>
>>>
>>> Whereas it is explicit in this statement
>>>
>>> if (authorizations.type === 'oauth_scope')
>>>
>>>
>>> which I think it easier to understand what is happening (in my opinion
>>> of course).
>>>
>>> XYZ has types, they are just implicit. RAR has explicit types, and that
>>> does not look to be holding back RAR. I don't understand why you think
>>> having explicit types will hold us back.
>>>
>>>
>>> The “type” in RAR is a name spacing device to allow extensibility in
>>> different aspects of the request. This is at a lower layer than how they’re
>>> being applied here, and it therefore makes more sense at that layer. It’s a
>>> way for a particular API to define the dimensions that it cares about in
>>> its request. It’s not really an even comparison.
>>>
>>
>> And the type in XAuth authorizations is different schemas for making a
>> request. "oauth_scope", "oauth_rar", and now "oidc". I would expect that
>> there may be more in the future, and we have a clear way of adding schemas,
>> and for the client and AS to know they are talking the same "language".
>>
>>
>> And I’m saying that additional “schemas” for requesting information
>> should be defined separately from the GNAP schema. We disagree on this
>> topic and we’re repeating ourselves.
>>
>
> The charter is pretty clear that GNAP should not define schemas, so I
> don't know what you mean by the "the GNAP schema"
>
>
>
> That’s not true. The charter is clear that "nor is the group chartered to
> develop schemas for user information, profiles, or other identity
> attributes”, but not that it’s not defining schemas for the other parts of
> the protocol. I’ve been clear on the other thread that we shouldn’t be
> defining a user schema, for attachment either to the access token or
> non-identifier items returned directly as plaintext or in assertions.
>
> By my read, we are fully within our charter to define schemas for
> authorization requests and responses, including both coarse and
> fine-grained access. I understand that it’s your stance that we should
> simply re-use OAuth 2’s “scope” parameter for this, and I disagree with
> that. My proposed approach is to have a place within the GNAP protocol to
> plug in a “scope” value if you have one, and for the AS to interpret it,
> but not to have that value always be a “scope”.
>
>
>>
>>
>>>
>>> Do you want to let the string and object be anything the AS and RS
>>> decide they could mean?
>>>
>>>
>>> Yes. Just like the AS can decide that an OAuth scope could mean any
>>> number of things.
>>>
>>
>> That was what I was afraid of. While an OAuth scope could mean whatever
>> the AS decides it wants to be, the Client and AS know it is an OAuth scope.
>>
>>
>> How is that any different? I’m confused as to why you think it’s
>> important to call this item a “scope” so that you “know what it is”, but
>> then you’re OK with “scope” meaning literally anything.
>>
>
> A scope string is one of a set of strings defined by the AS.
>
> The AS may use strings to define a different schema, such as which claims
> to return from a userinfo endpoint.
>
>
> Exactly. A scope is a string that represents access to something
> controlled by the AS. The object also represents that same thing, but in
> multiple, more specific dimensions.
>
>  I'm going to separate the my other responses into separate threads as
> they are different topics.
>
> /Dick
>
>>
>> ᐧ
>
>
>
>  - Justin
>