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

Denis <denis.ietf@free.fr> Fri, 10 July 2020 14:05 UTC

Return-Path: <denis.ietf@free.fr>
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 6EF123A0F01 for <txauth@ietfa.amsl.com>; Fri, 10 Jul 2020 07:05:59 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -0.619
X-Spam-Level:
X-Spam-Status: No, score=-0.619 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, FREEMAIL_FROM=0.001, FREEMAIL_REPLY=1, HTML_FONT_LOW_CONTRAST=0.001, HTML_MESSAGE=0.001, KHOP_HELO_FCRDNS=0.276, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, URIBL_BLOCKED=0.001] autolearn=no autolearn_force=no
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 bvlIwgsTBO_9 for <txauth@ietfa.amsl.com>; Fri, 10 Jul 2020 07:05:54 -0700 (PDT)
Received: from smtp.smtpout.orange.fr (smtp07.smtpout.orange.fr [80.12.242.129]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id A93B23A0D01 for <txauth@ietf.org>; Fri, 10 Jul 2020 07:05:04 -0700 (PDT)
Received: from [192.168.1.11] ([86.238.65.197]) by mwinf5d14 with ME id 1S522300B4FMSmm03S528o; Fri, 10 Jul 2020 16:05:02 +0200
X-ME-Helo: [192.168.1.11]
X-ME-Auth: ZGVuaXMucGlua2FzQG9yYW5nZS5mcg==
X-ME-Date: Fri, 10 Jul 2020 16:05:02 +0200
X-ME-IP: 86.238.65.197
To: Justin Richer <jricher@mit.edu>
Cc: Dick Hardt <dick.hardt@gmail.com>, txauth@ietf.org
References: <CAD9ie-vnA98pobbboS00SAHneEG52_8eMxh_sE3r3jg6gyooGg@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> <A7E1F61B-78F8-4647-847A-E1C8909EA452@mit.edu> <CAD9ie-tSjEWT-+D43yKaFZmEdFcbL=fyM0kHuFX_fNa4zHdm1w@mail.gmail.com> <6D58464F-3EFA-4367-9033-91FCB9CF40AC@mit.edu> <CAD9ie-syw5YJVsJHncZ-PcLQbYC4r=4LLSQCKtMP=-hGKqT0SA@mail.gmail.com> <0905DCA3-1B30-429A-AB02-8ED27D37F6C3@mit.edu> <CAD9ie-vV-pH6oebREkfY5rZ=8vYZpD2irjyjJ=4mvfKKeKY4-A@mail.gmail.com> <974147F1-A9CE-4093-A170-9F4F9DFB3638@mit.edu>
From: Denis <denis.ietf@free.fr>
Message-ID: <437457fa-54bc-4001-c00e-b3067cfcdb87@free.fr>
Date: Fri, 10 Jul 2020 16:04:59 +0200
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.9.0
MIME-Version: 1.0
In-Reply-To: <974147F1-A9CE-4093-A170-9F4F9DFB3638@mit.edu>
Content-Type: multipart/alternative; boundary="------------7255F332E568B62442703DFC"
Content-Language: en-GB
Archived-At: <https://mailarchive.ietf.org/arch/msg/txauth/m4Vi_Xukd7nip4zebb1fF6KMoow>
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 14:06:04 -0000

Hi Justin,

I dare to jump into this dialogue. I have two closely related questions:

    1) What kind of polymorphism do you intent to support ?
    2) What are the basic reasons for supporting "polymorphism" ?

Some help: Wikipedia states 
(https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) :

    In programming languages and type theory, polymorphism is the
    provision of a single interface to entities of different types
    or the use of a single symbol to represent multiple different types.

    The most commonly recognized major classes of polymorphism are:

      *      Ad hoc polymorphism: defines a common interface for an
        arbitrary set of individually specified types.
      *      Parametric polymorphism: when one or more types are not
        specified by name but by abstract symbols that can represent any
        type.
      *      Subtyping (also called subtype polymorphism or inclusion
        polymorphism): when a name denotes instances of many different
        classes
             related by some common superclass.

Before answering to these two questions, please consider the following 
observations that follow.

> Yes, the core idea is to not have to parse an assertion to get back 
> the core authentication information, which consists of an identifier
> (iss/sub pair in OIDC, but could be a number of things). Sometimes the 
> client is going to want the rest of the identity information,
> but If the user’s logged into the client before, the client has likely 
> cached that info and probably won’t need it, and sending it would be
> a violation of privacy principles.. The client would want the info 
> pretty much just in these cases:
>
>  1. The client has never seen the user before.
>  2. The user’s information has been updated since the last time the 
> client saw it.
>
> Now for case (1), how would the client know if it wants to request the 
> user’s profile info or not, since it doesn’t know who the user is? And 
> the AS won’t know
> if client is going to want the profile info, since the AS won’t know 
> if the client has the user’s info or not. Sure, the AS might have seen 
> that client and that
> user combo previously, but it doesn’t know if the client needs an update.

For cases (1) and (2), as long as the user has not yet decided to 
attempt to reach a RS, the client has nothing to do.

  * When the user selects a RS and if FIDO is supported, the client
    should check whether the user has a FIDO account with that RS.
    If he does, it should connect transparently to the RS.  If he does
    not have a FIDO account with that RS, the client should check
    whether the RS supports FIDO or some attributes from some AS are
    requested. If FIDO is supported by the RS, it should propose
    to the user to create a FIDO account. If some attributes from some
    AS are requested, it should check whether the user has
    an account with one or more of these ASs. If he has, the user should
    select the appropriate AS and after his consent the client
    should contact that AS to obtain the requested attributes in order
    to get them inside an access token. Finally the client should send
    the access token to the RS. What happens next depends upon what the
    user is willing to do.

  * When the user selects a RS and if FIDO is NOT supported, the client
    should connect to the RS and the RS should report to the client
    the means of authentication that it supports. This may be FIDO
    and/or some access tokens with specific attributes from specific ASs.
    If the user believes that the requested authentication means is
    adequate according to what he wants to do on the RS, he may then /
    locally /choose the most appropriate means.

>
> And for (2), the client won’t know if the user’s info has been updated 
> or not because it doesn’t know who the user is yet.
> If the AS can provide some time of updated stamp to the client, the 
> client can pull the new info when it needs it.
>
> If you ignore both of these cases and put all the user information 
> inline with the main request/response, you end up in a situation
> where the client always requests everything and the server always 
> provides everything, since you can’t be sure you’re not in situation
> (1) or (2) ahead of time.

The RS should inform the client about what it needs to present, at 
latest at the time of the first access attempt.
As long as the client has not yet attempted to reach a RS, the client 
has nothing to do.

> This is really what I mean about the two-stage identity protocol.
> In the first stage, you push the bare minimum of what you need to get 
> the user known to the client.
> In the second stage, the client uses its access token to call an API 
> to get whatever else it needs to know about the user.

Since the RS is not yet identified, the AS(s) that is/are trusted by the 
RS is/are still unknown.
The client should not contact any AS before it knows which RS the user 
is willing to access.

Last questions:

Since these two stages should not happen, why is "polymorphism" really 
or still needed ? If yes, for which purpose(s) ?

Denis

> This API could be an OIDC UserInfoEndpoint, a SCIM resource, a FHIR 
> resource, or any number of other user APIs, and standardizing that 
> information is not what GNAP should be focused on. OIDC does a really 
> good job of letting developers log people in using this kind of 
> protocol. While it’s possible to cram everything into an ID token on 
> every request, there’s no need for it, and it’s likely a bad pattern 
> to follow.
>
> I’m sorry that you are surprised by my stance, but it hasn’t changed 
> since I helped write the section of the charter that you quoted below. 
> A big reason that I chose that wording was to support this use case 
> but not to go in depth with an identity protocol, which I never really 
> wanted us to do. However, it seems as soon as “identity” was brought 
> up previously, people immediately jumped into talking about a full 
> stack of user attributes and profile information. That wasn’t my 
> intent in talking about identity, and I don’t think it’s something 
> GNAP ought to do, at least not on its own.
>
> I do think there’s room for us to provide identifiers alongside the 
> access token, so that’s there. There was stated interest in providing 
> signed assertions as well, so I made sure that was enumerated for 
> those who want to do such work. And I think it makes sense for us to 
> provide a way to describe what kinds of things I want to get from an 
> access token by defining a general purpose syntax for describing those 
> things (notably, as a combination of reference strings and 
> multi-dimensional objects). With these two, we can get most of what we 
> need for a basic login system. Anything beyond that is going to need 
> user profiles, authentication contexts, session control, and a lot of 
> other identity-protocol stuff that GNAP shouldn’t be focusing on. We 
> should keep it in mind as we build GNAP, but I think that like OIDC 
> all that important extra stuff should be built separately. To me, 
> that’s what not defining schemas and formats means.
>
> I don’t see any conflict with the charter here, and I’m surprised that 
> you do.
>
>  — Justin
>
>> On Jul 9, 2020, at 5:55 PM, Dick Hardt <dick.hardt@gmail.com 
>> <mailto:dick.hardt@gmail.com>> wrote:
>>
>> Thanks for the clarifications. I had chatted to Aaron about his post, 
>> and my understanding is not what is in the post on a closer read. My 
>> takeaway was why make the developer parse the ID_Token, why not give 
>> them the information directly.
>>
>> I have interpreted the userinfo and id_token top level elements to be 
>> how the client wanted the query results, not part of the query. I had 
>> thought my example and definition of a Grant Response in XAuth [1] 
>> would have clearly communicated what I meant, but I see that I should 
>> call out that userinfo in XAuth returns the claims, rather than 
>> userinfo in OIDC returns an access token for the claims. Given GNAP 
>> is more expressive, and learning from the past, I'm proposing we 
>> offer the developer (and AS) a choice in how to acquire the claims.
>>
>> While acquiring user information through an API at any time is 
>> appropriate in some use cases, in others why not give the client the 
>> info it needs right away rather than having to make another API call 
>> to get it? This would be appropriate when the user is making a 
>> purchase and wanting to provide shipping information. The user does 
>> not want to authorize the client to fetch their shipping address in 
>> the future.
>>
>> I'm surprised by your stance:
>>
>>     My stance is that we allow the client to ask for a small set of
>>     identifiers about the user, or even just ask to “identify the
>>     user”, and leave everything else to a higher level identity
>>     protocol. I do not think that having an identity and profile
>>     query/response language at the core of GNAP is a good idea, and
>>     it’s certainly not in our charter.
>>
>>
>> Since the charter states:
>>
>>     The group is chartered to develop mechanisms for conveying
>>     identity information
>>     within the protocol including existing identifiers (such as email
>>     addresses,
>>     phone numbers, usernames, and subject identifiers) and assertions
>>     (such as
>>     OpenID Connect ID Tokens, SAML Assertions, and Verifiable
>>     Credentials). The
>>     group is not chartered to develop new formats for identifiers or
>>     assertions,
>>     nor is the group chartered to develop schemas for user
>>     information, profiles,
>>     or other identity attributes.
>>
>>
>> More than identifiers about the user are clearly in scope of the WG 
>> charter, as are mechanisms for conveying identity information. Your 
>> stance and the charter look in conflict to me. What am I missing?
>>
>> /Dick
>>
>> [1] https://tools.ietf.org/html/draft-hardt-xauth-protocol-11#section-4.1
>>
>>
>>
>> On Thu, Jul 9, 2020 at 1:04 PM Justin Richer <jricher@mit.edu 
>> <mailto:jricher@mit.edu>> wrote:
>>
>>     In Aaron’s post he doesn’t talk about how the request would be
>>     made, just what the response could look like, and we are talking
>>     about how to request that. Aaron’s post specifically calls out
>>     that this is just an identifier for the user and states:
>>
>>         If the application needs to know profile information about
>>         the user, it can get that from the userinfo endpoint using
>>         the access token it just obtained.
>>
>>
>>     And I think that’s a good design pattern to follow. This isn’t
>>     “userinfo” being returned alongside the access token.
>>
>>     The top level functionality of the OIDC claims query language is
>>     this:
>>
>>
>>         The top-level members of the Claims request JSON object are:
>>
>>         userinfo
>>         OPTIONAL. Requests that the listed individual Claims *be
>>         returned from the UserInfo Endpoint*. If present, the listed
>>         Claims are being requested to be added to any Claims that are
>>         being requested using scope values. If not present, the
>>         Claims being requested from the UserInfo Endpoint are
>>         only those requested using scope values.
>>         When the userinfo member is used, the request MUST also use
>>         a response_type value that results in an *Access Token being
>>         issued to the Client for use at the UserInfo Endpoint*.
>>
>>         id_token
>>         OPTIONAL. Requests that the listed individual Claims be
>>         returned in the ID Token. If present, the listed Claims are
>>         being requested to be added to the default Claims in the ID
>>         Token. If not present, the default ID Token Claims are
>>         requested, as per the ID Token definition in Section 2 and
>>         per the additional per-flow ID Token requirements in
>>         Sections 3.1.3.6, 3.2.2.10, 3.3.2.11, and 3.3.3.6..
>>
>>
>>     Since you had re-used the “userinfo” and “id_token” top-level
>>     claims, I had assumed that they meant the same thing as in the
>>     OIDC spec. It’s clear to me, now, that this isn’t what you meant,
>>     but this is why I’m saying you’re not using the whole query
>>     language.
>>
>>     There are proposed extensions to the OIDC claims query that would
>>     put returned data into a different place[1], and so it would be
>>     possible to use the claims structures to handle this. But at that
>>     point if the goal is just to use the internal query format, then
>>     I think that we can do better using … polymorphic JSON. :)
>>
>>     My stance is that we allow the client to ask for a small set of
>>     identifiers about the user, or even just ask to “identify the
>>     user”, and leave everything else to a higher level identity
>>     protocol. I do not think that having an identity and profile
>>     query/response language at the core of GNAP is a good idea, and
>>     it’s certainly not in our charter.
>>
>>      — Justin
>>
>>     [1]
>>     https://mattrglobal.github.io/oidc-client-bound-assertions-spec/ defines
>>     a “credential’ target.
>>
>>>     On Jul 9, 2020, at 3:29 PM, Dick Hardt <dick.hardt@gmail.com
>>>     <mailto:dick.hardt@gmail.com>> wrote:
>>>
>>>     Yes. Which is why I referred to Aaron's post originally which
>>>     calls out for returning plain text claims.
>>>
>>>     I don't really understand what you mean by "OIDC claims query
>>>     language". The claims mean the same thing. And I was also
>>>     reusing the modifiers such as {"essential": true}. What top
>>>     level functionality are you referring to?
>>>
>>>     On Thu, Jul 9, 2020 at 12:21 PM Justin Richer <jricher@mit.edu
>>>     <mailto:jricher@mit.edu>> wrote:
>>>
>>>         Ah, so you’re saying that the “userinfo” claims would be
>>>         returned directly? I didn’t realize that you had intended to
>>>         change how the OIDC claims query language functioned in your
>>>         examples, and had assumed it would work the same was as the
>>>         spec you were referencing. Your example of splitting it up
>>>         makes that more clear. Though I would argue at that point,
>>>         you’re creating a new query language since you’re not using
>>>         the top-level functionality from ODIC’s definition.
>>>
>>>          — Justin
>>>
>>>>         On Jul 9, 2020, at 3:15 PM, Dick Hardt
>>>>         <dick.hardt@gmail.com <mailto:dick.hardt@gmail.com>> wrote:
>>>>
>>>>         You are jumping to many conclusions below. Let me break
>>>>         down the proposal into some bite size chunks.
>>>>
>>>>         The developer would like to get some plain text OIDC claims
>>>>         about the user:
>>>>
>>>>           "claims":{
>>>>         "oidc": {
>>>>         "userinfo" : {
>>>>           "name" : { "essential" : true },
>>>>           "photo" : { "essential" : false }
>>>>                     },
>>>>
>>>>         The developer would like to get an OIDC ID Token:
>>>>
>>>>           "claims":{
>>>>         "oidc": {
>>>>         "id_token" : {
>>>>           "email"      : { "essential" : true },
>>>>         "email_verified" : { "essential" : true }
>>>>                     }
>>>>           }
>>>>
>>>>         The developer would like to get an access token to acquire
>>>>         OIDC claims:
>>>>
>>>>         "authorizations": {
>>>>         "type":"oidc",
>>>>         "claims": ["name", "picture"]
>>>>             }
>>>>
>>>>         The developer would like to get an access token to access
>>>>         photos:
>>>>
>>>>         "authorizations": {
>>>>         "type":"oauth_scope",
>>>>         "scope": "read_photos"*
>>>>             }
>>>>
>>>>         The developer would like to get some VC claims:
>>>>
>>>>         "claims" {
>>>>               "vc": {
>>>>         "some_vc": "query_mechanism"
>>>>                 }
>>>>         }
>>>>
>>>>         The developer would like to do all of the above at once:
>>>>
>>>>         {
>>>>         "authorizations": {
>>>>         "userinfo": {
>>>>         "type":"oidc",
>>>>         "claims": ["name", "picture"]
>>>>                 },
>>>>         "photos": {
>>>>         "type":"oauth_scope",
>>>>         "scope": "read_photos"
>>>>                 }
>>>>             },
>>>>             "claims":{
>>>>         "oidc": {
>>>>         "id_token" : {
>>>>           "email"      : { "essential" : true },
>>>>         "email_verified" : { "essential" : true }
>>>>                     },
>>>>         "userinfo" : {
>>>>           "name" : { "essential" : true },
>>>>           "photo" : { "essential" : false }
>>>>                     }
>>>>                 },
>>>>             "vc": {
>>>>         "some_vc": "query_mechanism"
>>>>                 }
>>>>             }
>>>>         }
>>>>
>>>>         In the results, the developer gets claims back in the
>>>>         response claims object, and access tokens etc. back in the
>>>>         authorizations object. Just because an access token returns
>>>>         claims, it is still an access token.
>>>>
>>>>         Yes, the developer can't get a single access token that can
>>>>         both acquire OIDC claims, and access photos (there are
>>>>         separate tokens for each), but I would argue that
>>>>         separating the access is a positive security property, as a
>>>>         client component accessing the user profile has a token
>>>>         independent of the client component accessing photos. And
>>>>         at the AS, there is no requirement for the userinfo
>>>>         endpoint to take the same token as the photo endpoint.
>>>>
>>>>         Somewhat of a tangent, I'm thinking that
>>>>
>>>>           "claims":{
>>>>         "oidc": {
>>>>         "id_token" : {},
>>>>         "userinfo" : {}
>>>>                 },
>>>>
>>>>         is a little verbose, and:
>>>>
>>>>             "claims":{
>>>>         "oidc_token": {},
>>>>         "oidc_info": {}
>>>>             },
>>>>
>>>>         works better and makes it easier to distinguish support for
>>>>         ID tokens vs plain claims.
>>>>
>>>>         wrt. my position on reusing OIDC -- it has not changed. I
>>>>         have viewed the OIDC claims as the "query language". No
>>>>         need to reinvent that. We are creating a new protocol, so
>>>>         no need to use the OAuth or OIDC protocols.
>>>>
>>>>         * OAuth scopes could be a space separates string to be
>>>>         consistent with OAuth 2, or an array of strings so that it
>>>>         is more JSON like. I have no strong opinion.
>>>>
>>>>         scope.split(' ').forEach()
>>>>
>>>>         is not that much more complex than
>>>>
>>>>         scope.forEach()
>>>>
>>>>
>>>>
>>>>         On Thu, Jul 9, 2020 at 8:39 AM Justin Richer
>>>>         <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
>>>>
>>>>             But this approach doesn’t keep things in their
>>>>             respective containers — you’ve explicitly got “claims”
>>>>             underneath the “authorizations” header, and you’ve got
>>>>             items that come back as rights associated with the
>>>>             access token (which should be “authorizations”) in the
>>>>             “userinfo” section under the “claims” header. And as
>>>>             far as I can tell, these two sections are redundant to
>>>>             each other. Everything is everywhere.
>>>>
>>>>             Additionally, this approach and syntax makes it
>>>>             difficult to combine different kinds of requests into
>>>>             one. One of OpenID Connect’s biggest draws, as I’m sure
>>>>             you recall, is that it could be combined with a request
>>>>             for non-OIDC resources. This was the real innovation
>>>>             that Twitter and Facebook’s identity APIs brought,
>>>>             access to more than just authentication, and what
>>>>             Google had tried to replicate with the awkward OpenID 2
>>>>             + OAuth 1 hybrid system. Taking a step back from the
>>>>             existing solutions of OpenID 2 and OAuth 1 let us, as
>>>>             the community, see the value in the pattern that became
>>>>             OIDC on top of OAuth 2.
>>>>
>>>>             Sure, you could say that the “oidc” type also can allow
>>>>             a “scopes” parameter, but what about a RAR style
>>>>             object, then? And what about when someone comes up with
>>>>             some new way to request access rights, or a VC-based
>>>>             query language? Does every “type” need to now know
>>>>             about every other “type” in order for an AS to be able
>>>>             to figure out how they go together? This seems like the
>>>>             protocol definition limiting what combinations the AS
>>>>             can handle, or what an RS might want to use.
>>>>
>>>>             My stance is that GNAP should have a way to query for
>>>>             rights in the access token (“authorizations” in xauth
>>>>             parlance) and identifiers for the user (“claims” in
>>>>             xauth parlance), and anything else should be an
>>>>             extension with potentially different models. The AS
>>>>             would process the “authorizations” equivalent (for the
>>>>             access token) alongside any other incoming query and
>>>>             then make a policy decision based on that.
>>>>
>>>>             I find it interesting that you are now saying we don’t
>>>>             need to use the OIDC request format when previously
>>>>             you’ve made it clear that you were in favor of pointing
>>>>             at external query languages, including their syntax.
>>>>             I’m glad to see that you’re now looking at things in a
>>>>             more flexible way, but I think it’s important that we
>>>>             be careful and conscientious about how we reference any
>>>>             external query languages in GNAP.
>>>>
>>>>              — Justin
>>>>
>>>>>             On Jul 8, 2020, at 6:55 PM, Dick Hardt
>>>>>             <dick.hardt@gmail.com <mailto:dick.hardt@gmail.com>>
>>>>>             wrote:
>>>>>
>>>>>             Hey Justin,
>>>>>
>>>>>             Just because we are using OIDC claims, does not mean
>>>>>             we need to mimic the OIDC request and response.
>>>>>             I was envisioning a grant request could look as the
>>>>>             following (using XAuth syntax):
>>>>>
>>>>>             {
>>>>>             "authorizations": {
>>>>>             "type":"oidc",
>>>>>             "claims": ["name", "picture"]
>>>>>                 },
>>>>>                 "claims":{
>>>>>             "oidc": {
>>>>>             "id_token" : {
>>>>>               "email"      : { "essential" : true },
>>>>>             "email_verified" : { "essential" : true }
>>>>>                         },
>>>>>             "userinfo" : {
>>>>>               "name"     : { "essential" : true },
>>>>>               "picture"      : null
>>>>>                         }
>>>>>                     }
>>>>>                 }
>>>>>             }
>>>>>
>>>>>             Of course a developer could choose to only ask for a
>>>>>             subset of this.
>>>>>
>>>>>             Note the new authorization type of "oidc", that takes
>>>>>             "claims" rather than "scope".
>>>>>
>>>>>             This keeps all the authorizations and claims in their
>>>>>             respective request and response containers.
>>>>>
>>>>>             We had a thread months ago on the OIDC two stage
>>>>>             model, and I still fail to see why forcing that has
>>>>>             any advantage.
>>>>>
>>>>>             /Dick
>>>>>
>>>>>
>>>>>             On Wed, Jul 8, 2020 at 3:25 PM Justin Richer
>>>>>             <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
>>>>>
>>>>>                 I’m glad that we can agree that there are a number
>>>>>                 of things in legacy protocols that are unfortunate
>>>>>                 side effects of the circumstances in which they
>>>>>                 were built. Space-separated scope strings, for
>>>>>                 instance, would fall in that category, as I’ve
>>>>>                 previously explained.
>>>>>
>>>>>                 A key point in the below: the OIDC “claims”
>>>>>                 request already mixes user claims (returned in an
>>>>>                 API) and authorization (to fetch user claims from
>>>>>                 an API), so that ship has sailed if you’re using
>>>>>                 it. It doesn’t make sense to have it under a
>>>>>                 “claims” or “authorizations” request, since it’s a
>>>>>                 query language that affects both. Maybe you’d call
>>>>>                 this another “unfortunate design”, but the context
>>>>>                 was about re-using an externally-defined query
>>>>>                 language that was not made for GNAP.
>>>>>
>>>>>                 My scenario was for someone who is already using
>>>>>                 “claims” and wants to keep using it. (The vast
>>>>>                 majority of OIDC implementations, in my
>>>>>                 experience, don’t use that feature, and it’s not
>>>>>                 even required to be implemented by the AS, but
>>>>>                 again we’re talking about using this feature as an
>>>>>                 example of an external query language — and there
>>>>>                 are others out there.) In GNAP, you should return
>>>>>                 claims directly in the response, and request
>>>>>                 specific elements from the APIs protected by the
>>>>>                 access token. These are separate things, and by
>>>>>                 design both XAuth and XYZ have put them into
>>>>>                 separate containers in the request. This is a good
>>>>>                 design, and so putting something that conflates
>>>>>                 these two aspects into one or the other of the
>>>>>                 containers is not a particularly good option, in
>>>>>                 my opinion.
>>>>>
>>>>>                 Additionally, though this is a bit of an aside and
>>>>>                 getting into the specifics of identity, the
>>>>>                 “claims” parameter of ODIC is a query language
>>>>>                 bound to the full user profile. It is my stated
>>>>>                 position that the items coming back from the AS
>>>>>                 should only be identifiers, and not full profile
>>>>>                 information. The reasoning is pretty simple: the
>>>>>                 client doesn’t know what profile information it
>>>>>                 needs until it knows who the user is, so putting
>>>>>                 that into a protected API like the UserInfo
>>>>>                 Endpoint makes much more sense than putting it
>>>>>                 into the immediate response, where it is not
>>>>>                 needed, because the client already knows it. The
>>>>>                 AS doesn’t know what the client needs to know,
>>>>>                 either, so it can’t determine what to fulfill.
>>>>>                 OIDC’s two-stage model makes sense, and GNAP
>>>>>                 should really only focus on enabling this.
>>>>>
>>>>>                  — Justin
>>>>>
>>>>>>                 On Jul 8, 2020, at 6:10 PM, Dick Hardt
>>>>>>                 <dick.hardt@gmail.com
>>>>>>                 <mailto:dick.hardt@gmail.com>> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>                 On Wed, Jul 8, 2020 at 1:02 PM Justin Richer
>>>>>>                 <jricher@mit.edu <mailto:jricher@mit.edu>> wrote:
>>>>>>
>>>>>>                     On Jul 8, 2020, at 3:16 PM, Dick Hardt
>>>>>>                     <dick.hardt@gmail.com
>>>>>>                     <mailto:dick.hardt@gmail.com>> wrote:
>>>>>>>
>>>>>>>                     I think representing the request as an array
>>>>>>>                     is simplistic, and complicated at the same
>>>>>>>                     time.
>>>>>>>
>>>>>>>                     On the simplistic front, as there is no
>>>>>>>                     clear mechanism for extending the request
>>>>>>>                     with properties that apply to all of the
>>>>>>>                     request.
>>>>>>
>>>>>>                     The elements of the array are taken as a set,
>>>>>>                     to be tied to the same resulting access
>>>>>>                     token. If one of those elements is defined,
>>>>>>                     by the AS and/or the RS’s it’s protecting, to
>>>>>>                     apply across some or all of the other
>>>>>>                     elements, then that’s up to the AS’s policy.
>>>>>>                     Much like the “openid” scope in OIDC, which
>>>>>>                     switches on all sorts of contextual stuff in
>>>>>>                     the request. So to handle something like
>>>>>>                     this, an AS can easily declare that a given
>>>>>>                     scope-style string or a given object property
>>>>>>                     applies to different parts of the request.
>>>>>>                     You don’t need to externalize it here.
>>>>>>
>>>>>>
>>>>>>                 I view the "openid" scope as an unfortunate
>>>>>>                 design as OIDC was constrained by building on top
>>>>>>                 of OAuth. (a problem I hoped to avert by having
>>>>>>                 "identity" in scope for GNAP) The "openid" scope
>>>>>>                 does not function as scope per se, and I think it
>>>>>>                 makes OIDC harder to understand as the "openid"
>>>>>>                 scope causes non-scope behavior.
>>>>>>
>>>>>>
>>>>>>                     Do you have a concrete use case that requires
>>>>>>                     that feature to be done in the way that you
>>>>>>                     describe? I am trying to separate the driving
>>>>>>                     use case from the proposed solutions to see
>>>>>>                     what the differences are.
>>>>>>
>>>>>>
>>>>>>                 Perhaps the client wants access to be HIPPA
>>>>>>                 compliant? The HIPPA compliance signal applies to
>>>>>>                 the scopes.
>>>>>>
>>>>>>                 Adding other properties to an object is a well
>>>>>>                 understood extension mechanism. Adding an
>>>>>>                 additional element to an array that does not act
>>>>>>                 like the other elements seems like a hack.
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>                     Using JSON type polymorphism requires the AS
>>>>>>>                     to test each member of the array to
>>>>>>>                     determine if it is a string or an object.
>>>>>>>                     Only after detecting a RAR object does the
>>>>>>>                     AS know the client is making a RAR request.
>>>>>>
>>>>>>                     That’s correct — but the AS needs to parse
>>>>>>                     the whole resources request in order to
>>>>>>                     figure out what the client is asking for,
>>>>>>                     anyway, whether it’s by strings or objects or
>>>>>>                     whatever else might be defined by an
>>>>>>                     extension. Is there an argument for having an
>>>>>>                     AS do an early dispatch on a request before
>>>>>>                     it’s fully parsed everything?
>>>>>>
>>>>>>
>>>>>>                 Let me clarify, the code is looking at the type
>>>>>>                 of object that has been parsed.
>>>>>>
>>>>>>                 Determining if an item in an array is a scope or
>>>>>>                 a RAR object by looking at the type being either
>>>>>>                 a string or an object seems less clear than a
>>>>>>                 property of an object explicitly declaring the type.
>>>>>>
>>>>>>
>>>>>>
>>>>>>>                     This also limits the request to be composed
>>>>>>>                     only of scope strings or RAR objects. I
>>>>>>>                     don't see how other strings or objects could
>>>>>>>                     be used in the array, so there is no clear
>>>>>>>                     extension point in the "resources" array for
>>>>>>>                     other query mechanisms.
>>>>>>
>>>>>>                     That’s not the case in XYZ since we aren’t
>>>>>>                     declaring that a string has to be an
>>>>>>                     OAuth2-style scope. It can be, but ultimately
>>>>>>                     it’s just a string that the AS can
>>>>>>                     understand. And the objects are just that —
>>>>>>                     objects. If the AS understands what the
>>>>>>                     object is, it can be a RAR object or it can
>>>>>>                     be something completely API-specific with
>>>>>>                     another query language entirely.
>>>>>>
>>>>>>
>>>>>>                 But the other query language would need a type
>>>>>>                 that has been reserved in the RAR name space for
>>>>>>                 there to be interop, so it effectively is a RAR
>>>>>>                 extension.
>>>>>>
>>>>>>                 There are query languages in other domains that
>>>>>>                 may not fit nicely into RAR such as a query for
>>>>>>                 medical records.
>>>>>>
>>>>>>                 Yes, the medical records could be yet another top
>>>>>>                 level property, but per below, I think that is
>>>>>>                 confusing.
>>>>>>
>>>>>>                     (Point, though: RAR already pretty much
>>>>>>                     allows this by letting them be extended
>>>>>>                     infinitely, a feature it inherits from XYZ)
>>>>>>
>>>>>>                     I’m proposing that we do the same thing with
>>>>>>                     GNAP: it’s an array of strings or objects and
>>>>>>                     each of those means the same thing,
>>>>>>                     “something the client is asking for”.
>>>>>>
>>>>>>>
>>>>>>>                     Just as RAR has a "type" property, I propose
>>>>>>>                     the "resources" ("authorizations" in XAuth)
>>>>>>>                     be an object, where the other properties are
>>>>>>>                     determined by the "type" property. This
>>>>>>>                     allows extensions to define new ways to
>>>>>>>                     query for an authorization rather than
>>>>>>>                     having to fit into scopes or RAR.
>>>>>>>
>>>>>>
>>>>>>                     It’s my stance that this is an unnecessary
>>>>>>                     limitation at this level. The objects within
>>>>>>                     the array should be typed, like RAR, but it
>>>>>>                     doesn’t make sense for the overall request to
>>>>>>                     be typed. Instead, there should be one “type"
>>>>>>                     of query in the core, what XYZ calls the
>>>>>>                     “resources” request. Other query languages
>>>>>>                     should be added as extensions either to the
>>>>>>                     RAR-style objects (by defining a type at that
>>>>>>                     level) or as a separate top-level member.
>>>>>>
>>>>>>                     For example, let’s take the OIDC “claims”
>>>>>>                     query language. My current thought is that
>>>>>>                     this really shouldn’t be a part of the
>>>>>>                     “resources” or “claims” part of the request,
>>>>>>                     but instead as its own top-level member, like
>>>>>>                     it is in the OIDC protocol today. The main
>>>>>>                     reason for this is the nature of the OIDC
>>>>>>                     claims language: it specifies targets for the
>>>>>>                     resulting data, and those targets cross
>>>>>>                     different ways to return things. So it
>>>>>>                     doesn’t actually affect just resources like
>>>>>>                     the UserInfo Endpoint, or the ID Token, but
>>>>>>                     both and potentially others out there. If
>>>>>>                     your system supported such an extension, it
>>>>>>                     could theoretically forego both the built-in
>>>>>>                     “claims” and “resources” parts of the
>>>>>>                     request, and use the “oidc_claims_query”
>>>>>>                     member (or whatever it would be called). This
>>>>>>                     would let such an extension use the OIDC
>>>>>>                     claims processing mechanism as it is today.
>>>>>>
>>>>>>                     To me, this remains much more understandable,
>>>>>>                     extensible, and clean.
>>>>>>
>>>>>>
>>>>>>                 While this may be more understandable to a
>>>>>>                 developer just porting an app OIDC that only
>>>>>>                 wants OIDC results, but I think it is more
>>>>>>                 complicated as soon as the developer wants other
>>>>>>                 results, which is likely what prompted the
>>>>>>                 developer to use GNAP instead of ODIC.
>>>>>>
>>>>>>                 I think it is easier to understand if all the
>>>>>>                 claims are in one container, and all the
>>>>>>                 authorizations are in another container.
>>>>>>
>>>>>>                 If a developer wants access to some resources,
>>>>>>                 some claims, and an OpenID Token, they are having
>>>>>>                 to use "claims", "resources", and
>>>>>>                 "oidc_claims_query". Now the claims and access
>>>>>>                 tokens are spread across multiple containers.
>>>>>>                 There are some claims in the "claims" container,
>>>>>>                 and some "claims" in the "oidc_claims_query"
>>>>>>                 container. And is the access token response
>>>>>>                 in "oidc_claims_query" the same as an access
>>>>>>                 token response in "resources"? It would seem
>>>>>>                 simpler if they were, and if all the access
>>>>>>                 tokens came back in the same container.
>>>>>>
>>>>>>                 Per Aaron's post that you have referred to, the
>>>>>>                 developer can get sme bare claims directly in the
>>>>>>                 response in the "claims" object, an ID Token that
>>>>>>                 has the same or different claims, and if they
>>>>>>                 want, an access token that they can call a
>>>>>>                 user_info endpoint to get the same, or different
>>>>>>                 claims.
>>>>>>
>>>>>>                 For example, an enterprise app client may want an
>>>>>>                 ID Token with the email address, bare claims for
>>>>>>                 the user's name and a URI to a profile photo, and
>>>>>>                 an access token to query which groups a user
>>>>>>                 belongs to.
>>>>>>
>>>>>>                 We are still re-using the OIDC claims, but we are
>>>>>>                 not mixing claims and authorizations.
>>>>>>
>>>>>>                 /Dick
>>>>>>
>>>>>>
>>>>>>                 [1]
>>>>>>                 https://aaronparecki.com/2019/07/18/17/adding-identity-to-xyz
>>>>>>                 ᐧ
>>>>>
>>>>>             ᐧ
>>>>
>>>>         ᐧ
>>>
>>>     ᐧ
>>
>
>