Subject: [GNAP] Feedback on polymorphism

From: Mika Boström <[email-masked]>
Date: Fri, 23 Oct 2020 15:18:49 +0100

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

---

From: Justin Richer <[email-masked]>
Date: Fri, 23 Oct 2020 13:18:36 -0400

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 <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 <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=[email-masked]> 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",
> 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
> [email-masked]
> https://www.ietf.org/mailman/listinfo/txauth

---

From: Dick Hardt <[email-masked]>
Date: Fri, 23 Oct 2020 12:07:23 -0700

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 <[email-masked]> 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
> }
>
> 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=[email-masked]> wrote:
>
> Hello, everyone.
>
ᐧ

---

From: Justin Richer <[email-masked]>
Date: Fri, 23 Oct 2020 15:41:57 -0400

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 <[email-masked]> 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.
> 
> 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>
> 
> 
> 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 <https://news.ycombinator.com/item?id=24855750> 
> 
> /Dick
> 
> 
> On Fri, Oct 23, 2020 at 10:20 AM Justin Richer <[email-masked] <mailto:[email-masked]>> wrote:
> Hi Mika,
> 
>> On Oct 23, 2020, at 10:18 AM, Mika Boström <mika.bostrom=[email-masked] <mailto:mika.bostrom=[email-masked]>> wrote:
>> 
>> Hello, everyone.
>> 
>> [email-masked] <mailto:[email-masked]>
>> https://www.ietf.org/mailman/listinfo/txauth <https://www.ietf.org/mailman/listinfo/txauth>
> 
> -- 
> TXAuth mailing list
> [email-masked] <mailto:[email-masked]>
> https://www.ietf.org/mailman/listinfo/txauth <https://www.ietf.org/mailman/listinfo/txauth>
> ᐧ

---

From: Dick Hardt <[email-masked]>
Date: Fri, 23 Oct 2020 12:52:34 -0700

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.

/Dick

ᐧ

On Fri, Oct 23, 2020 at 12:42 PM Justin Richer <[email-masked]> 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
>
> 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
>> 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
>> 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
>> 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
>> 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
>> [email-masked]

---

From: Justin Richer <[email-masked]>
Date: Fri, 23 Oct 2020 16:35:38 -0400

> On Oct 23, 2020, at 3:52 PM, Dick Hardt <[email-masked]> 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. 
> 
> 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 <[email-masked] <mailto:[email-masked]>> wrote:
> Dick,
> 
>> On Oct 23, 2020, at 3:07 PM, Dick Hardt <[email-masked] <mailto:[email-masked]>> wrote:
>> 
>> Hey Justin,
>>

---

From: Fabien Imbault <[email-masked]>
Date: Sat, 24 Oct 2020 03:26:54 +0200

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 <[email-masked]> a écrit :

> 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
> 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
>
> ᐧ
>
>> 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
>>> 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
>>> 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 (
>>> 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.
>>>
>>> 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.
>>>

---

From: Dick Hardt <[email-masked]>
Date: Sat, 24 Oct 2020 14:49:28 -0700

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 <[email-masked]>
wrote:

> 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
> 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.
>> 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
>>> 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
>>> 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.
>>>
>>>
>>> On a related note, there was significant negative feedback on handles
>>> and polymorphism in the Hacker News article
>>>> 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
>>>> }
>>>>
>>>> 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
>>>> 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

---

From: Fabien Imbault <[email-masked]>
Date: Sun, 25 Oct 2020 00:25:01 +0200

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 <[email-masked]> a écrit :

>> 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?
>>
>>>>> 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

---

From: Fabien Imbault <[email-masked]>
Date: Sun, 25 Oct 2020 00:39:57 +0200

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 <[email-masked]> a
écrit :

> 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.
>
>>> 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.
>>> (short answer: the priority should be simplicity for spec users, not
>>> spec implementers and even less spec designers).
>>>
>>> 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.
>>>
>>> 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.
>>> 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
>>>
>>>
>>>
>>>
>>>
>>>>> As the draft has evolved, I question the continued use of
>>>>> polymorphism. Note that I appreciate the elegance of using a string for
>>>>> 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.
>>>>>
>>>>>> 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 (
>>>>>> The driving reason for using polymorphism at the protocol level was
>>>>>> to simplify the protocol and make it :more: deterministic to create and
>>>>>> 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
>>>>>> 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
>>>>>> 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
>>>>>> [email-masked]

---

From: Yaron Sheffer <[email-masked]>
Date: Sun, 25 Oct 2020 12:17:38 +0200

Hi Fabien,

I think your product management model has a lot of merit, but it does not capture the security issue well.

I agree that as we look at different customer personas, the “end user” (the developer that’s using the libraries) should be our highest priority. But I disagree about end-user mistakes being the top *security* issue. Libraries are often open source in our space and used very widely. So they make for tasty targets, and people are attacking them and are still finding security issues in libraries that we’ve been talking about forever [1].

(Yes, my example is actually an app flaw, but I think it could have been prevented by a better designed library.)

In other words, we do need to care about how easy it is to implement the protocol correctly by *library* developers. From Justin describing his own experience and other people on the thread that Dick referred to, I would say that JSON polymorphism is painful for Java and Go developers. With all due respect, I care about them much more than I care about Haskell, as many more implementations are likely to use these languages.

Thanks,

                Yaron

[1] https://www.zofrex.com/blog/2020/10/20/alg-none-jwt-nhs-contact-tracing-app/

From: TXAuth <[email-masked]> on behalf of Fabien Imbault <[email-masked]>
Date: Sunday, October 25, 2020 at 01:25
To: Dick Hardt <[email-masked]>
Cc: Mika Boström <mika.bostrom=[email-masked]>, GNAP Mailing List <[email-masked]>, Justin Richer <[email-masked]>
Subject: Re: [GNAP] Feedback on polymorphism

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 

If a client library developer wants to expose polymorphism, they can do that independent of what is in the protocol. 

AS developer
RS developer
client developer
user

A client library developer can expose whatever interface they want to simplify implementation.

/Dick

ᐧ

On Fri, Oct 23, 2020 at 6:27 PM Fabien Imbault <[email-masked]> 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

 

Justin

- version of client

- version of OS

 

{

  posture: {

    software_version: 1.2.3,

    os_version: 14.3.2

  },

  client: “client-541-ab"

}

 — Justin

/Dick

ᐧ

Dick,

 — Justin

Hey Justin,

 

   "client": {

   }

   object.

{ 
 "key": { 
     "proof": "bearer" 
    } 
}

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

Hi Mika,

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. 

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    },

    bearer_token: true,

    bind_to_rc_key: true

}

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    }

}

// bearer token

{

    key: false

}

{

    key: true

}

 — Justin

Hello, everyone.

# payload 1

{

  ...,

  "public_key": {

    "alg": "rsa",

    "modulus": <BIGINT>

  }

}

# payload 2

{

  ...,

  "public_key": {

    "alg": "rsa",

  }

}

Best regards,

Mika

-- 

Mika Boström

Smarkets

ᐧ

-- TXAuth mailing list [email-masked] https://www.ietf.org/mailman/listinfo/txauth

---

From: Fabien Imbault <[email-masked]>
Date: Sun, 25 Oct 2020 11:39:39 +0100

Hi Yaron,

Thanks for the feedback.

Regarding client libraries, I think we can indeed learn a great deal from
cryptographic libraries. Cryptographic design provides a great amount of
flexibility for the specialists (including many parameters that you really
need to get right). We might think this is great to provide options but it
actually increases the cognitive load of library users.

Look instead at what Google has provided with tink as an alternative and
you'll see it is a much easier way for cryptographic engineers (who aren't
cryptographers) to avoid mistakes or misuses.

That's the *security* issue I'm referring to (not the fact that being open
they're tasty targets, although that may be related in some cases). And
tink is the kind of design we should be trying to achieve.

I agree that it should be applicable to a wide range of well known
programming tools, including the likes of java and go.
But I don't really see a limitation here. Might not be the most idiomatic
feel, but it can be made to work.

Just so I understand, what alternatives would you prefer to polymorphism? I
can suggest json-ld but even Justin will Teel you it's even more complex
:-)

Cheers
Fabien

Le dim. 25 oct. 2020 à 11:17, Yaron Sheffer <[email-masked]> a
écrit :

> I agree that as we look at different customer personas, the “end user”
> (the developer that’s using the libraries) should be our highest priority.
> But I disagree about end-user mistakes being the top **security** issue.
> Libraries are often open source in our space and used very widely. So they
> make for tasty targets, and people are attacking them and are still finding
> security issues in libraries that we’ve been talking about forever [1].
>
>
>
> In other words, we do need to care about how easy it is to implement the
> protocol correctly by **library** developers. From Justin describing his
> own experience and other people on the thread that Dick referred to, I
> would say that JSON polymorphism is painful for Java and Go developers.
> With all due respect, I care about them much more than I care about
> Haskell, as many more implementations are likely to use these languages.
>
>
>
> Thanks,
>
>                 Yaron
>
>
>
> [1]
> https://www.zofrex.com/blog/2020/10/20/alg-none-jwt-nhs-contact-tracing-app/
>
>
>
> *From: *TXAuth <[email-masked]> on behalf of Fabien Imbault <
> [email-masked]>
> *Date: *Sunday, October 25, 2020 at 01:25
> *To: *Dick Hardt <[email-masked]>
> *Cc: *Mika Boström <mika.bostrom=[email-masked]>, GNAP
> Mailing List <[email-masked]>, Justin Richer <[email-masked]>
> *Subject: *Re: [GNAP] Feedback on polymorphism
>
>
>
> Hi Dick,
>
>
>
> -- TXAuth mailing list [email-masked]

---

From: Yaron Sheffer <[email-masked]>
Date: Sun, 25 Oct 2020 14:36:23 +0200

Personally, I would support polymorphism in the protocol if it (the RFC) came with a well-defined JSON Schema [1] document, so a recipient can automatically validate incoming messages at run-time. I would expect senders to also validate messages as part of their testing. It’s not an ideal solution, because:

Some people at the IETF don’t like JSON Schema, for various reasons.
JSON Schema is not a standard, so it’s painful to require it normatively.
Even if it’s normative, some recipients will not validate messages anyway.

This would be shifting some of the complexity from the library developer to the spec developer, which is the right thing to do IMO.

Thanks,

                Yaron

[1] https://json-schema.org/

From: Fabien Imbault <[email-masked]>
Date: Sunday, October 25, 2020 at 12:39
To: Yaron Sheffer <[email-masked]>
Cc: Dick Hardt <[email-masked]>, Mika Boström <mika.bostrom=[email-masked]>, GNAP Mailing List <[email-masked]>, Justin Richer <[email-masked]>
Subject: Re: [GNAP] Feedback on polymorphism

Hi Yaron,

Thanks for the feedback. 

Regarding client libraries, I think we can indeed learn a great deal from cryptographic libraries. Cryptographic design provides a great amount of flexibility for the specialists (including many parameters that you really need to get right). We might think this is great to provide options but it actually increases the cognitive load of library users.

Look instead at what Google has provided with tink as an alternative and you'll see it is a much easier way for cryptographic engineers (who aren't cryptographers) to avoid mistakes or misuses. 

That's the *security* issue I'm referring to (not the fact that being open they're tasty targets, although that may be related in some cases). And tink is the kind of design we should be trying to achieve. 

I agree that it should be applicable to a wide range of well known programming tools, including the likes of java and go. 

But I don't really see a limitation here. Might not be the most idiomatic feel, but it can be made to work. 

Just so I understand, what alternatives would you prefer to polymorphism? I can suggest json-ld but even Justin will Teel you it's even more complex :-) 

Cheers

Fabien 

Le dim. 25 oct. 2020 à 11:17, Yaron Sheffer <[email-masked]> a écrit :

Hi Fabien,

Thanks,

                Yaron

Hi Dick,

Fabien 

AS developer
RS developer
client developer
user

/Dick

Error! Filename not specified.ᐧ

Hi there, 

Back to the GNAP topic. 

Cheers.

Fabien

 

 

Justin

- version of client

- version of OS

 

{

  posture: {

    software_version: 1.2.3,

    os_version: 14.3.2

  },

  client: “client-541-ab"

}

 — Justin

/Dick

Error! Filename not specified.ᐧ

Dick,

 — Justin

Hey Justin,

 

   "client": {

   }

   object.

{ 
 "key": { 
     "proof": "bearer" 
    } 
}

/Dick

Hi Mika,

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    },

    bearer_token: true,

    bind_to_rc_key: true

}

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    }

}

// bearer token

{

    key: false

}

{

    key: true

}

 — Justin

Hello, everyone.

# payload 1

{

  ...,

  "public_key": {

    "alg": "rsa",

    "modulus": <BIGINT>

  }

}

# payload 2

{

  ...,

  "public_key": {

    "alg": "rsa",

  }

}

Best regards,

Mika

-- 

Mika Boström

Smarkets

Error! Filename not specified.ᐧ

---

From: Fabien Imbault <[email-masked]>
Date: Sun, 25 Oct 2020 13:47:53 +0100

Hi Yaron,

As Justin explained that's the kind of idea we tested. For instance
https://github.com/fimbault/test_gnap_schema (in rust).

Cheers
Fabien

Le dim. 25 oct. 2020 à 13:36, Yaron Sheffer <[email-masked]> a
écrit :

> Personally, I would support polymorphism in the protocol if it (the RFC)
> came with a well-defined JSON Schema [1] document, so a recipient can
> automatically validate incoming messages at run-time. I would expect
> senders to also validate messages as part of their testing. It’s not an
> ideal solution, because:
>
>
>
>    - Some people at the IETF don’t like JSON Schema, for various reasons.
>    - JSON Schema is not a standard, so it’s painful to require it
>    normatively.
>    - Even if it’s normative, some recipients will not validate messages
>    anyway.
>
>
>
> This would be shifting some of the complexity from the library developer
> to the spec developer, which is the right thing to do IMO.
>
>
>
> Thanks,
>
>                 Yaron
>
>
>
> *From: *Fabien Imbault <[email-masked]>
> *Date: *Sunday, October 25, 2020 at 12:39
> *To: *Yaron Sheffer <[email-masked]>
> *Cc: *Dick Hardt <[email-masked]>, Mika Boström <mika.bostrom=
> [email-masked]>, GNAP Mailing List <[email-masked]>,
> Justin Richer <[email-masked]>
> Just so I understand, what alternatives would you prefer to polymorphism?
> I can suggest json-ld but even Justin will Teel you it's even more complex
> :-)
>
>
>
> Cheers
>
> Fabien
>
>
>
> *Error! Filename not specified.*ᐧ
>
>
>
> *Error! Filename not specified.*ᐧ
>
>
>
> *Error! Filename not specified.*ᐧ
>
>
>
>
>
> --
> TXAuth mailing list
> [email-masked]

---

From: "Huang, Peter (HPE HQ)" <[email-masked]>
Date: Sun, 25 Oct 2020 16:06:13 +0000

I have been reading but not commented before, but I will add my comments here.

1) in related to polymorphism, been a software developer many years, then a directory (ldap, IAM) and a security engineer (PKI, kerberos).  I think this one has merit.  my experiences are from doing RS, RC and user development background.  From my view,  this (JSON)  is like ASN1 but much simpler.  I like Justin's approach to verify it 1st since before a reference implementation, it just a concept.

2) I'm somewhat puzzle of no discussion around multiple tokens and the complication it brings.  When I try to get OAUTH2/OIDC adopted within our company, that has been the most difficult conversations with other teams. I have to reach out to John B for clarification of use of azp. Am I missing some discussions there?

3) I'm a little concerned that the spec has grown to be some complex to miss the original intend.  the discussion has been really good especially from others not in the design team (e.g. Dick), I would definitely like to hear more from John, Mike J, Brian C and others on this.

 my 2 cents.

peter
________________________________
From: Fabien Imbault <[email-masked]>
Sent: Sunday, October 25, 2020 3:39 AM
To: Yaron Sheffer <[email-masked]>
Cc: Dick Hardt <[email-masked]>; Mika Boström <mika.bostrom=[email-masked]>; GNAP Mailing List <[email-masked]>; Justin Richer <[email-masked]>
Subject: Re: [GNAP] Feedback on polymorphism

Hi Yaron,

Thanks for the feedback.

Cheers
Fabien

Le dim. 25 oct. 2020 à 11:17, Yaron Sheffer <[email-masked]<mailto:[email-masked]>> a écrit :

Hi Fabien,

Thanks,

                Yaron

[1] https://www.zofrex.com/blog/2020/10/20/alg-none-jwt-nhs-contact-tracing-app/<https://www.zofrex.com/blog/2020/10/20/alg-none-jwt-nhs-contact-tracing-app/>

From: TXAuth <[email-masked]<mailto:[email-masked]>> on behalf of Fabien Imbault <[email-masked]<mailto:[email-masked]>>
Date: Sunday, October 25, 2020 at 01:25
To: Dick Hardt <[email-masked]<mailto:[email-masked]>>
Cc: Mika Boström <mika.bostrom=[email-masked]<mailto:[email-masked]>>, GNAP Mailing List <[email-masked]<mailto:[email-masked]>>, Justin Richer <[email-masked]<mailto:[email-masked]>>
Subject: Re: [GNAP] Feedback on polymorphism

Hi Dick,

Fabien

Le sam. 24 oct. 2020 à 23:50, Dick Hardt <[email-masked]<mailto:[email-masked]>> a écrit :

  *   AS developer
  *   RS developer
  *   client developer
  *   user

/Dick

[Image removed by sender.]ᐧ

On Fri, Oct 23, 2020 at 6:27 PM Fabien Imbault <[email-masked]<mailto:[email-masked]>> wrote:

Hi there,

Back to the GNAP topic.

Cheers.

Fabien

Le ven. 23 oct. 2020 à 22:35, Justin Richer <[email-masked]<mailto:[email-masked]>> a écrit :

On Oct 23, 2020, at 3:52 PM, Dick Hardt <[email-masked]<mailto:[email-masked]>> wrote:

Justin

- version of client

- version of OS

{

  posture: {

    software_version: 1.2.3,

    os_version: 14.3.2

  },

  client: “client-541-ab"

}

 — Justin

/Dick

[Image removed by sender.]ᐧ

On Fri, Oct 23, 2020 at 12:42 PM Justin Richer <[email-masked]<mailto:[email-masked]>> wrote:

Dick,

 — Justin

On Oct 23, 2020, at 3:07 PM, Dick Hardt <[email-masked]<mailto:[email-masked]>> wrote:

Hey Justin,

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>

   "client": {

   }

   object.

{
 "key": {
     "proof": "bearer"
    }
}

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<https://news.ycombinator.com/item?id=24855750>

/Dick

On Fri, Oct 23, 2020 at 10:20 AM Justin Richer <[email-masked]<mailto:[email-masked]>> wrote:

Hi Mika,

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<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.

{

    key: {

      proof: httpsig,

      jwk: { … key value … }

    },

    bearer_token: true,

    bind_to_rc_key: true

}

{

    key: {

      proof: httpsig,

      jwk: { … key value … }

    }

}

// bearer token

{

    key: false

}

{

    key: true

}

 — Justin

On Oct 23, 2020, at 10:18 AM, Mika Boström <mika.bostrom=[email-masked]<mailto:mika.bostrom=[email-masked]>> wrote:

Hello, everyone.

# payload 1

{

  ...,

  "public_key": {

    "alg": "rsa",

    "modulus": <BIGINT>

  }

}

# payload 2

{

  ...,

  "public_key": {

    "alg": "rsa",

  }

}

Best regards,

Mika

--

Mika Boström

Smarkets

--
TXAuth mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/txauth<https://www.ietf.org/mailman/listinfo/txauth>

--
TXAuth mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/txauth<https://www.ietf.org/mailman/listinfo/txauth>

[Image removed by sender.]ᐧ

--
TXAuth mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/txauth<https://www.ietf.org/mailman/listinfo/txauth>

-- TXAuth mailing list [email-masked]<mailto:[email-masked]> https://www.ietf.org/mailman/listinfo/txauth<https://www.ietf.org/mailman/listinfo/txauth>

---

From: Justin Richer <[email-masked]>
Date: Sun, 25 Oct 2020 12:33:22 -0400

I agree fully with Fabien’s statements on who we’re making things easy for. If this security protocol isn’t easy and straightforward for client developers — with or without a library — then it simply will not be adopted. It might be hard to see when looking at the whole protocol, but this goal is actually one of the drivers for the way polymorphism is used in the current draft. The driving philosophy of OpenID Connect’s development was “keep the simple things simple, make the complex things possible”, and that’s a philosophy I strongly believe we need to continue here in GNAP.

Importantly, a client developer shouldn’t need to have to support all possible permutations in order to get something right. OAuth has shown us that even when a protocol has a lot of options, client software is going to be coded to use only one set of options. If the protocol can support that reality, I think we are doing well. In the current draft, generally speaking it’s the AS that needs to handle different options, not the client. Take for example requesting resources: a very simple client might just send an array of strings, like OAuth scopes. The AS needs to be able to handle the string inputs as well as the rich object descriptors, but the client software doesn’t even need to know that the object format exists in order to create compliant JSON.  The client developer can do this without any special libraries, it can just bang out the JSON directly. Such a client won’t be able to do the more fancy stuff that the request objects allow, but for this client, that’s fine since all it needs to do is produce an array with strings that the AS will accept. The same is true across the various other options, like requesting multiple access tokens vs a single one, or providing an instance identifier vs. a set of information for the client instance itself. Client developers should be fully able to ignore parts of the protocol that they aren’t using, especially the more advanced stuff. An AS shouldn’t get to have such a choice, but as the AS is the lynchpin of the security model, I am OK with things being slightly more complex to support, especially if it shifts that complexity away from clients.

I am in favor of including JSON Schema in the draft in a non-normative way, and you can see an earlier version of that experiment that Fabien and I undertook as part of the Design Team. The schema will be available for developers who want to / can use it, but even for people who aren’t using the schema directly it can provide additional context and information. I am willing to put some cycles into creating schemas for the main request and response messages and put those into a pull request to create an appendix in the draft. I’d also be fine with a non-normative JSON-LD reference for LD processors — but (1) I’m not going to write that :) and (2) it can’t be required for the protocol to be understood.

 — Justin

> On Oct 25, 2020, at 8:47 AM, Fabien Imbault <[email-masked]> wrote:
> 
> Hi Yaron,
> 
> As Justin explained that's the kind of idea we tested. For instance https://github.com/fimbault/test_gnap_schema <https://github.com/fimbault/test_gnap_schema> (in rust).
> 
> Cheers
> Fabien 
> 
> Le dim. 25 oct. 2020 à 13:36, Yaron Sheffer <[email-masked] <mailto:[email-masked]>> a écrit :
> [1] https://json-schema.org/ <https://json-schema.org/>
>  
> 
>  
> 
> From: Fabien Imbault <[email-masked] <mailto:[email-masked]>>
> To: Yaron Sheffer <[email-masked] <mailto:[email-masked]>>
> Cc: Dick Hardt <[email-masked] <mailto:[email-masked]>>, Mika Boström <mika.bostrom=[email-masked] <mailto:[email-masked]>>, GNAP Mailing List <[email-masked] <mailto:[email-masked]>>, Justin Richer <[email-masked] <mailto:[email-masked]>>
> Le dim. 25 oct. 2020 à 11:17, Yaron Sheffer <[email-masked] <mailto:[email-masked]>> a écrit :
> 
> Hi Fabien,
> 
>  
> 
> [1] https://www.zofrex.com/blog/2020/10/20/alg-none-jwt-nhs-contact-tracing-app/ <https://www.zofrex.com/blog/2020/10/20/alg-none-jwt-nhs-contact-tracing-app/>
>  
> 
> From: TXAuth <[email-masked] <mailto:[email-masked]>> on behalf of Fabien Imbault <[email-masked] <mailto:[email-masked]>>
> To: Dick Hardt <[email-masked] <mailto:[email-masked]>>
> Cc: Mika Boström <mika.bostrom=[email-masked] <mailto:[email-masked]>>, GNAP Mailing List <[email-masked] <mailto:[email-masked]>>, Justin Richer <[email-masked] <mailto:[email-masked]>>
> Le sam. 24 oct. 2020 à 23:50, Dick Hardt <[email-masked] <mailto:[email-masked]>> a écrit :
> 
> On Fri, Oct 23, 2020 at 6:27 PM Fabien Imbault <[email-masked] <mailto:[email-masked]>> wrote:
> 
> Hi there, 
> 
>  
> 
> Le ven. 23 oct. 2020 à 22:35, Justin Richer <[email-masked] <mailto:[email-masked]>> a écrit :
> 
>  
> 
>  
> 
> On Oct 23, 2020, at 3:52 PM, Dick Hardt <[email-masked] <mailto:[email-masked]>> wrote:
> 
>  
> 
> Justin
> 
>  
> 
> -- TXAuth mailing list [email-masked] <mailto:[email-masked]> https://www.ietf.org/mailman/listinfo/txauth <https://www.ietf.org/mailman/listinfo/txauth>

---

From: Yaron Sheffer <[email-masked]>
Date: Sun, 25 Oct 2020 20:42:34 +0200

Hi Justin,

I agree that there are going to be more clients than AS’s, and that clients should be simpler to write.

But I’m not following your next argument. It sounds like “The AS is complex anyway, and it’s security-critical anyway, so why not have it absorb some additional complexity?”. With polymorphism in the protocol, AS developers are likely to move to weak typing (generic types, e.g. interface{} in Go). The entire implementations will pay the price (in more brittle code) for the benefit of the few polymorphic fields that indeed may be easier to validate. I don’t think this is the right call.

Thanks,

                Yaron

From: Justin Richer <[email-masked]>
Date: Sunday, October 25, 2020 at 18:33
To: Fabien Imbault <[email-masked]>
Cc: Yaron Sheffer <[email-masked]>, Dick Hardt <[email-masked]>, Mika Boström <mika.bostrom=[email-masked]>, GNAP Mailing List <[email-masked]>
Subject: Re: [GNAP] Feedback on polymorphism

 — Justin

Hi Yaron,

As Justin explained that's the kind of idea we tested. For instance https://github.com/fimbault/test_gnap_schema (in rust).

Cheers

Fabien 

Le dim. 25 oct. 2020 à 13:36, Yaron Sheffer <[email-masked]> a écrit :

Thanks,

                Yaron

 

Hi Yaron,

Thanks for the feedback. 

Cheers

Fabien 

Hi Fabien,

Thanks,

                Yaron

Hi Dick,

Fabien 

AS developer
RS developer
client developer
user

/Dick

Hi there, 

Back to the GNAP topic. 

Cheers.

Fabien

 

 

Justin

- version of client

- version of OS

 

{

  posture: {

    software_version: 1.2.3,

    os_version: 14.3.2

  },

  client: “client-541-ab"

}

 — Justin

/Dick

Dick,

 — Justin

Hey Justin,

 

   "client": {

   }

   object.

{ 
 "key": { 
     "proof": "bearer" 
    } 
}

/Dick

Hi Mika,

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    },

    bearer_token: true,

    bind_to_rc_key: true

}

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    }

}

// bearer token

{

    key: false

}

{

    key: true

}

 — Justin

Hello, everyone.

# payload 1

{

  ...,

  "public_key": {

    "alg": "rsa",

    "modulus": <BIGINT>

  }

}

# payload 2

{

  ...,

  "public_key": {

    "alg": "rsa",

  }

}

Best regards,

Mika

-- 

Mika Boström

Smarkets

---

From: Justin Richer <[email-masked]>
Date: Sun, 25 Oct 2020 16:42:01 -0400

That’s not exactly what I’m saying — I’m more making the argument that things that complexity in the AS isn’t an automatic (or even high priority) negative, if it offers a measurable benefit like simplicity to the rest of the system. Obviously things that make an AS very difficult to implement are going to be a problem.

Also, I’m not sure I was clear about characterizing my implementation in Java. I explicitly set out to build it the hard way: I wanted something that would run through a completely automated parser, without any pre-processing or special code paths, into static types and concrete object classes. There are no generic “Object”s or “List of Maps of Maps” or things like that in my implementation, and my code doesn’t even call the JSON parser directly, since it’s all wired directly through Spring. The difficult part wasn’t writing the code that says “for this specific field, if it’s a string do A, if it’s an object do B”, the actual difficult part was wiring it up such that it’s transparent to the rest of my code base. If I had been doing my own parsing by hand and then handing it to “real” classes, or had resorted to generic types upon parsing and pulling out raw values when I need them, it would have been a lot simpler. But both of these are fragile, as you point out, and the way I did it I was actually guaranteeing strict parsing and strict types, even with all the polymorphism in place. This is the approach I would expect a fully compliant AS to do, and something that conformance testing, schemas, and careful protocol design can ferret out from bad implementations.

 — Justin

> On Oct 25, 2020, at 2:42 PM, Yaron Sheffer <[email-masked]> wrote:
> 
> Hi Justin,
>  
>> On Oct 25, 2020, at 8:47 AM, Fabien Imbault <[email-masked] <mailto:[email-masked]>> wrote:
>>  
>> Hi Yaron,
>>

---

From: Dick Hardt <[email-masked]>
Date: Sun, 25 Oct 2020 16:57:33 -0700

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 <[email-masked]>
wrote:

>> 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
>>
>>
>>
>>>> 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?
>>>> 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.
>>>>
>>>> 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.
>>>>
>>>>>> 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
>>>>>>

---

From: Dick Hardt <[email-masked]>
Date: Sun, 25 Oct 2020 17:04:16 -0700

I want to point out that JSON schema can enforce mutually exclusive
properties.

For example the "client" object containing once of "instance_id",
"class_id", or "display"

ᐧ

On Sun, Oct 25, 2020 at 9:33 AM Justin Richer <[email-masked]> wrote:

> I agree fully with Fabien’s statements on who we’re making things easy
> for. If this security protocol isn’t easy and straightforward for client
> developers — with or without a library — then it simply will not be
> adopted. It might be hard to see when looking at the whole protocol, but
> this goal is actually one of the drivers for the way polymorphism is used
> in the current draft. The driving philosophy of OpenID Connect’s
> development was “keep the simple things simple, make the complex things
> possible”, and that’s a philosophy I strongly believe we need to continue
> here in GNAP.
>
> Importantly, a client developer shouldn’t need to have to support all
> possible permutations in order to get something right. OAuth has shown us
> that even when a protocol has a lot of options, client software is going to
> be coded to use only one set of options. If the protocol can support that
> reality, I think we are doing well. In the current draft, generally
> speaking it’s the AS that needs to handle different options, not the
> client. Take for example requesting resources: a very simple client might
> just send an array of strings, like OAuth scopes. The AS needs to be able
> to handle the string inputs as well as the rich object descriptors, but the
> client software doesn’t even need to know that the object format exists in
> order to create compliant JSON.  The client developer can do this without
> any special libraries, it can just bang out the JSON directly. Such a
> client won’t be able to do the more fancy stuff that the request objects
> allow, but for this client, that’s fine since all it needs to do is produce
> an array with strings that the AS will accept. The same is true across the
> various other options, like requesting multiple access tokens vs a single
> one, or providing an instance identifier vs. a set of information for the
> client instance itself. Client developers should be fully able to ignore
> parts of the protocol that they aren’t using, especially the more advanced
> stuff. An AS shouldn’t get to have such a choice, but as the AS is the
> lynchpin of the security model, I am OK with things being slightly more
> complex to support, especially if it shifts that complexity away from
> clients.
>
> I am in favor of including JSON Schema in the draft in a non-normative
> way, and you can see an earlier version of that experiment that Fabien and
> I undertook as part of the Design Team. The schema will be available for
> developers who want to / can use it, but even for people who aren’t using
> the schema directly it can provide additional context and information. I am
> willing to put some cycles into creating schemas for the main request and
> response messages and put those into a pull request to create an appendix
> in the draft. I’d also be fine with a non-normative JSON-LD reference for
> LD processors — but (1) I’m not going to write that :) and (2) it can’t be
> required for the protocol to be understood.
>
>  — Justin
>
>> That's the *security* issue I'm referring to (not the fact that being
>> open they're tasty targets, although that may be related in some cases).
>> And tink is the kind of design we should be trying to achieve.
>>
>>
>>

---

From: Fabien Imbault <[email-masked]>
Date: Mon, 26 Oct 2020 03:04:14 +0100

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 <[email-masked]> a écrit :

>> 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
>> Le dim. 25 oct. 2020 à 00:25, Fabien Imbault <[email-masked]>
>> a écrit :
>>
>>> Hi Dick,
>>>
>>>>>> 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
>>>>>> 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
>>>>>>> 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.
>>>>>>>
>>>>>>>
>>>>>>> On a related note, there was significant negative feedback on
>>>>>>> handles and polymorphism in the Hacker News article
>>>>>>>> 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.
>>>>>>>>

---

From: Mika Boström <[email-masked]>
Date: Wed, 28 Oct 2020 16:28:39 +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 <[email-masked]>
wrote:

> But beneath the polyphormism question, the HN debate seems on the surface
> a lot like the original xyz (polyphormism goes along with the reduced
>> 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
>>
>>>> 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.
>>>>
>>>>> If a client library developer wants to expose polymorphism, they can
>>>>> do that independent of what is in the protocol.
>>>>>
>>>>>> 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
>>>>>> 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 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 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"
>>>>>>>>> The driving reason for using polymorphism at the protocol level
>>>>>>>>> was to simplify the protocol and make it :more: deterministic to create and
>>>>>>>>> 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

-- 
Mika Boström
Smarkets

---

From: Fabien Imbault <[email-masked]>
Date: Wed, 28 Oct 2020 17:55:32 +0100

Thanks for the great feedback. Your concern is very valid.

My implementation is in rust, which makes life easier in that specific
case.

So I'm not a golang specialist but I guess the transcription of json
strings/arrays into go structs would work around the lines described by
https://medium.com/@alexkappa/json-polymorphism-in-go-4cade1e58ed1
When we have a more formalized json schema, I suggest we make a library of
json examples and some related code samples in mainstream languages, to
check it is feasible for everyone.

Cheers,
Fabien

On Wed, Oct 28, 2020 at 5:28 PM Mika Boström <[email-masked]>
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 :-)
>>>>
>>>>> 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.
>>>>>
>>>>>>> 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.
>>>>>>>
>>>>>>> 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?
>>>>>>> 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
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>> 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
>>>>>>>>>> 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
>>>>>>>>>> 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
>>>>>>>>>> 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.
>>>>>>>>>>

---

From: Justin Richer <[email-masked]>
Date: Wed, 28 Oct 2020 13:11:45 -0400

Mika,

First, thank you for joining the conversation, and thank you for the great feedback! The spec is really just getting started, and this kind of discussion and input is important. As you can see, the working group hasn’t fully settled on a set of answers yet, and so more perspectives are needed and desired. There are always tradeoffs with every protocol decision, and it’s important that we understand these decisions as we make them.

I think we would both agree that the goal this kind of a standard is definitely not to expect people to use a particular reference implementation, and anything that relies on a specific library, language, or implementation isn’t truly interoperable in any meaningful way. 

I’m not familiar enough with Go to comment on details of the implementation below, but in the Java implementation that I did, each field with different type-based representations is tagged with a serializer/deserializer hook. This is very common for Java-based JSON systems, and not just for polymorphic content. For example, if I have a JWT, I want it stored as a structured object that contains easy access to all the parsed data, but I need it serialized as a single string within JSON. Therefore I tag the individual field that’s of Java type JWT with serializer and deserializer classes, both of which do a simple transformation to and from the canonical string form that the JWT class provides for me. Fields with multiple possible types are handled similarly to this: as you note below, there is a domain object class for the field itself, and the deserializer checks the type of the JSON node during parsing to determine how to populate that class object. Going in the other direction, the serializer looks at the state of the object and its contents to figure out if it needs to be a complex type (like a JSON object) or a simple type (like a JSON string) and outputs the appropriate JSON node to the serializer’s stream. 

I’ve worked with a number of other languages and platforms, and there are similar capabilities to what I had used for Java, described here. I believe in Go you’d have something similar to do a custom marshall/unmarshall of the field/type in question. You don’t really want it to be a “union type” within the data model, so much as you need to be able how to get into and out of JSON. And in my experience, for dynamically typed languages like Python and JavaScript, it’s often easier (or at least more common) to just parse the JSON directly and pull out the values directly as needed, as opposed to mapping them to a concrete class object. You can actually do something similar with Java if you want to just map to generic types. These implementations will need to do some additional sanity checks during the reading of individual fields, but these end up being the same kinds of checks and mappings that happen during the parsing phase of a statically typed language. In other words, you check for “string or object” at the point of reading the “client” field and branch your code there, as opposed to having the parser do it for you. This might seem like a lot of overhead for just trying to read a value, but bear in mind that the alternative is to do something like read an object, then check across the fields of that object, and branch your code based on that — including new error branches for inconsistent states.

This is why it’s important to me that polymorphism is applied in a very specific way in the protocol. If there’s a field named “client” then I should be able to look at whatever value is in that field and get back a “client” of some kind that I can put into a dat structure, whether I’m parsing the object directly or looking up a reference. If I can get something that’s not a “client” from that field, or if I have to deal with several radically different kinds of objects from there, then I think we’ve missed the mark. The one place currently in the protocol where we have objects with some known structure but potentially arbitrary contents are within the “resources” array, and for that there is a required “type” field to keep different sides from guessing what to do with it. Even so, it’s always a requested resource description, so it semantically always maps to the same :kind: of object.

Ultimately, the question we need to ask is this: if we don’t use polymorphism within the protocol to express the constructs that we’re using it for, what are we going to use instead? In my experience, it’s much more brittle to have a system built out of nameless objects with collections of mutually-exclusive fields and constraints about contents. Sure you can support those by parsing to a single class object, but then you need wrappers around the class objects to ensure they aren’t accidentally put into an internally inconsistent state. Plus, to be secure you’ll need to ensure all inputs and outputs aren’t in an inconsistent state. My proposed approach is that we build such interlocks into the protocol directly by careful use of type-based information in the stream. To me, this looks more like the BAD kind of polymorphism that you’ve talked about, where I need to look inside the data stream to figure out what flavor of object I’m dealing with without having an explicit type-based definition. 

Again, thank you for joining the conversation. There’s definitely a lot of material to dig into — this is a big effort and it’s going to take some time before it’s finished! Your continued feedback is not only welcomed, it is encouraged, and I’d recommend you even join the mailing list if you want to keep engaging with the group.

 — Justin

> On Oct 28, 2020, at 12:28 PM, Mika Boström <[email-masked]> wrote:
> 
> Hi everyone,
> 
> Looks like I stuck my finger in a hornets' nest. First off, apologies for not chipping in earlier, but there was a lot of material to digest. Also, warning: lots to read ahead.
> 
> I'm one of those people who end up making use of AuthN/AuthZ functionality through a library. On top of that I can see myself being roped in as a server (AS) implementation help. So I'm approaching this from an outsider's perspective. Someone who expects to be exposed to the eventual RFC and all the nitty-gritty details. My relatively terse comment ended up at the top of the aforementioned HN thread, which didn't necessarily help. Sorry about that.
> 
> Now, having read Justin's initial reply - and the rest of the thread - I believe I can see where the desire for polymorphism comes from. To be clear: I am all for strict types inside an implementation, as it will add helpful guard-rails to the state management code paths. However, I see this as a case of leaky abstraction. If we take the existing oauth.xyj-java code to be the reference implementation, the choice makes logical sense: JSON is not expressive enough to serialise arbitrary objects, so in order to avoid writing complex payload parser(s) the internal implementation details now leak to the protocol itself. From a purely technical perspective, it's a cool trick. From a distance it even looks a bit like the result of protobuf decoding, but without the generated code parts.
> 
> But then the downside. I don't personally expect to be able to use the reference implementation, being mostly a Python user myself. A fair number of AS implementations will be written with languages such as Go, Python, C#, Ruby, and JavaScript (thanks to node.js), and all of them will have to deal with the polymorphism. From what I've read over the past couple of days, I understand that at least Go supports custom unmarshalers from JSON to typed structs, at the cost of an indirection. Normally when a Go code processes JSON to a typed struct, the process is helped by field annotations in the type definition itself. For example, if the payload for a person in JSON was
> 
> {
>   "name": "<string>",
>   "age": <int>,
>   "country": "<string>",
>   "city": "<string>"
> }
> 
> 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 {
> 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 <[email-masked] <mailto:[email-masked]>> 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 <[email-masked] <mailto:[email-masked]>> 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 
> 
> On Sat, Oct 24, 2020 at 3:40 PM Fabien Imbault <[email-masked] <mailto:[email-masked]>> 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. 
> Le dim. 25 oct. 2020 à 00:25, Fabien Imbault <[email-masked] <mailto:[email-masked]>> a écrit :
> Hi Dick,
>

---

From: Yaron Sheffer <[email-masked]>
Date: Wed, 28 Oct 2020 20:47:13 +0200

Hi Fabien,

At least in the case of Go, I think the “solution” is far worse than the problem. The code in the article you cite is very specific to the use case and IMHO quite ugly. So my preferred Go implementation would be a combination of untyped structures (Go interface{}) and run-time enforcement of JSON Schema.

Also, going back to our earlier discussion on this topic, I just read Sec. 7 of gnap-00 and realized that the RC also needs to deal with polymorphism (the “key” value), not only the AS.

Thanks,

                Yaron

From: TXAuth <[email-masked]> on behalf of Fabien Imbault <[email-masked]>
Date: Wednesday, October 28, 2020 at 18:56
To: Mika Boström <[email-masked]>
Cc: GNAP Mailing List <[email-masked]>, Justin Richer <[email-masked]>, Dick Hardt <[email-masked]>
Subject: Re: [GNAP] Feedback on polymorphism

My implementation is in rust, which makes life easier in that specific case. 

So I'm not a golang specialist but I guess the transcription of json strings/arrays into go structs would work around the lines described by https://medium.com/@alexkappa/json-polymorphism-in-go-4cade1e58ed1

When we have a more formalized json schema, I suggest we make a library of json examples and some related code samples in mainstream languages, to check it is feasible for everyone. 

Cheers,

Fabien

On Wed, Oct 28, 2020 at 5:28 PM Mika Boström <[email-masked]> wrote:

Hi everyone,

{

  "name": "<string>",

  "age": <int>,

  "country": "<string>",

  "city": "<string>"

}

type Person struct {

  Name string `json:"name"

  Age int `json:"age"`

}

type Entity struct {

}

Cheers,

Mika

On Mon, 26 Oct 2020 at 02:04, Fabien Imbault <[email-masked]> wrote:

Hi Dick,

Fabien 

Hi Fabien

 

ᐧ

On Sat, Oct 24, 2020 at 3:40 PM Fabien Imbault <[email-masked]> wrote:

 

Le dim. 25 oct. 2020 à 00:25, Fabien Imbault <[email-masked]> a écrit :

Hi Dick,

Fabien 

AS developer
RS developer
client developer
user

/Dick

ᐧ

Hi there, 

Back to the GNAP topic. 

Cheers.

Fabien

 

Justin

- version of client

- version of OS

 

{

  posture: {

    software_version: 1.2.3,

    os_version: 14.3.2

  },

  client: “client-541-ab"

}

 — Justin

/Dick

ᐧ

Dick,

 — Justin

Hey Justin,

 

   "client": {

   }

   object.

{ 
 "key": { 
     "proof": "bearer" 
    } 
}

/Dick

Hi Mika,

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    },

    bearer_token: true,

    bind_to_rc_key: true

}

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    }

}

// bearer token

{

    key: false

}

{

    key: true

}

 — Justin

Hello, everyone.

# payload 1

{

  ...,

  "public_key": {

    "alg": "rsa",

    "modulus": <BIGINT>

  }

}

# payload 2

{

  ...,

  "public_key": {

    "alg": "rsa",

  }

}

Best regards,

Mika

-- 

Mika Boström

Smarkets

ᐧ

-- 

Mika Boström

Smarkets

---

From: Justin Richer <[email-masked]>
Date: Wed, 28 Oct 2020 15:30:17 -0400

Yaron, it’s a good observation on the RC’s requirements. You are correct that the RC would need to deal with the “key” value having potentially different types, but In this specific case I think it would be naturally limited by a capability the RC is able to support, or not:

Either the RC is going to be able to bind the token to an arbitrary key from the AS (which is when it would see a non-boolean value), or it won’t be able to do that, in which case it can only expect/read a boolean there. A general purpose RC library will deal with that polymorphism, but it would also deal with the polymorphism of the request language. I would expect a simple client to just reject a response with an arbitrary key in that field if it doesn’t know how to handle it. I think it’s a feature that the RC wouldn’t have to always know about every part of the protocol in order to get something working in a secure and predictable fashion.

We could also decide to limit that case in the response in order to lessen the burden on the RC. As Dick pointed out earlier in the thread, it wouldn’t be difficult to come up with a syntax to declare bearer tokens — and in fact, his proposal aligns with previous versions of the XYZ Draft. I personally think the syntax is awkward and has some drawbacks, but it does work for the basic use case of switching between bearer tokens and server-provided keys. However, the missing piece is something that I think should become the default in GNAP: binding the resulting token to the key the client presented during the request. This aligns with both DPoP and OAuth MTLS methods today, both of which have been shown to work very well in production. However, server-provided and server-referenced keys are called for by the OAuth PoP Architecture documents. These are more complex use cases, to be sure, but I think it’s possible to support them with relatively low cost to the rest of the system.

It’s definitely a tradeoff, but one I think lands closer to simplicity for a wider array of software implementations and helps get us away from bearer tokens as a default for the simple case of a client instance binding to its own key.

 — Justin

> On Oct 28, 2020, at 2:47 PM, Yaron Sheffer <[email-masked]> wrote:
> 
> Hi Fabien,
>  
> To: Mika Boström <[email-masked] <mailto:[email-masked]>>
> Cc: GNAP Mailing List <[email-masked] <mailto:[email-masked]>>, Justin Richer <[email-masked] <mailto:[email-masked]>>, Dick Hardt <[email-masked] <mailto:[email-masked]>>
> So I'm not a golang specialist but I guess the transcription of json strings/arrays into go structs would work around the lines described by https://medium.com/@alexkappa/json-polymorphism-in-go-4cade1e58ed1 <https://medium.com/@alexkappa/json-polymorphism-in-go-4cade1e58ed1>
> On Wed, Oct 28, 2020 at 5:28 PM Mika Boström <[email-masked] <mailto:[email-masked]>> wrote:
>> Hi everyone,
>>

---

From: Justin Richer <[email-masked]>
Date: Wed, 28 Oct 2020 15:54:53 -0400

To Yaron’s point on JSON Schema, I just pushed a pull request that includes a JSON Schema for the main request and response messages as currently defined in the protocol. I’m sure it’s not perfect, but it seems to work against both positive and negative examples that I’ve thrown at it so far, and I’d be glad to see others play with it and improve it. 

https://github.com/ietf-wg-gnap/core-protocol/pull/4

A question for the WG, do we want to include this resource as a non-normative addition to the document? I’m in favor of having it in there and keeping it updated through protocol changes, as it will help those who want to use it and can be ignored by those who don’t care about it.

 — Justin

> On Oct 28, 2020, at 3:30 PM, Justin Richer <[email-masked]> wrote:
> 
>> On Oct 28, 2020, at 2:47 PM, Yaron Sheffer <[email-masked] <mailto:[email-masked]>> wrote:
>> 
>> Hi Fabien,
>>

---

From: Fabien Imbault <[email-masked]>
Date: Wed, 28 Oct 2020 20:57:37 +0100

Hi Yaron,

We'll indeed have to check how make it as idiomatic as possible with
experts of each language (help welcome).

Regarding the client, the variations are more limited but they do exist.
Here I believe it's much more problematic than on the server side and there
are at least a few actions we should take:

A) check in sec 7 if we really have a compelling reason for key and proof
variants. This is derived from larger discussions on key binding as per the
related note. There are quite a few open questions related to this theme.

B) there is also the choice between value/reference that may generate
complexity.

C) More generally, as many feedbacks already have noticed, we need to have
a systematic review and reduce the set of available options in the
protocol.

Unless we have a clear idea why runtime behavior requires mutability, it
might be useful to have a way to define the chosen variant before hand, so
that the expected behavior becomes deterministic on the client side. There
are various ways it could be done in practice.

For sure several independant implementations would help, especially if we
make sure they can work together.

Anyway all this open to improvement.

Cheers
Fabien

Le mer. 28 oct. 2020 à 19:47, Yaron Sheffer <[email-masked]> a
écrit :

> Hi Fabien,
>
>
>
> At least in the case of Go, I think the “solution” is far worse than the
> problem. The code in the article you cite is very specific to the use case
> and IMHO quite ugly. So my preferred Go implementation would be a
> combination of untyped structures (Go interface{}) and run-time enforcement
> of JSON Schema.
>
>
>
> Also, going back to our earlier discussion on this topic, I just read Sec.
> 7 of gnap-00 and realized that the RC also needs to deal with polymorphism
> (the “key” value), not only the AS.
>
>
>
> Thanks,
>
>                 Yaron
>
>
>
> *Date: *Wednesday, October 28, 2020 at 18:56
> *To: *Mika Boström <[email-masked]>
> *Cc: *GNAP Mailing List <[email-masked]>, Justin Richer <[email-masked]>,
> Dick Hardt <[email-masked]>

---

From: Andrii Deinega <[email-masked]>
Date: Thu, 29 Oct 2020 12:23:08 -0700

Hi Mika, Justin, and WG,

The act (actor) claim introduced in RFC 8693 (OAuth 2.0 Token Exchange) has
a JSON object as its value. This claim could be a part of AT JWT or a token
introspection response and has the same semantics in both cases. The JSON
object as its value may look like this

"act":
{
  "sub":"[email-masked]"
}

or even be nested like in

"act":
{
 "sub":"https://service16.example.com",
   "act":
   {
     "sub":"https://service77.example.com"
   }
}

Personally, I find it to be a very expressive approach. Also, as far I as
know, several (oAuth2) client libraries have good support of things like

"aud":"https://service1.example.com" and "aud":["
https://service1.example.com","https://service2.example.com"]

in AT JWTs for a quite long time.

Regards,
Andrii

On Wed, Oct 28, 2020 at 12:58 PM Fabien Imbault <[email-masked]>
wrote:

>> Also, going back to our earlier discussion on this topic, I just read
>> Sec. 7 of gnap-00 and realized that the RC also needs to deal with
>> polymorphism (the “key” value), not only the AS.
>>
>>
>>
>> Thanks,
>>
>>                 Yaron
>>
>>
>>
>> When we have a more formalized json schema, I suggest we make a library
>> of json examples and some related code samples in mainstream languages, to
>> 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.
>>
>>
>>

---

From: Fabien Imbault <[email-masked]>
Date: Fri, 30 Oct 2020 13:53:38 +0100

Hi Justin,

> Regarding your question, what else could we propose?

I've started a review of possibilities at
https://github.com/fimbault/reasonably-polymorphic/blob/main/README.md to
be followed by actual code testing.

Cheers,
Fabien

On Thu, Oct 29, 2020 at 8:23 PM Andrii Deinega <[email-masked]>
wrote:

> Hi Mika, Justin, and WG,
>
> The act (actor) claim introduced in RFC 8693 (OAuth 2.0 Token Exchange)
> has a JSON object as its value. This claim could be a part of AT JWT or a
> token introspection response and has the same semantics in both cases. The
> JSON object as its value may look like this
>
> "act":
> {
>> C) More generally, as many feedbacks already have noticed, we need to
>> have a systematic review and reduce the set of available options in the
>> protocol.
>>
>>> *Cc: *GNAP Mailing List <[email-masked]>, Justin Richer <
>>> [email-masked]>, Dick Hardt <[email-masked]>
>>> 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.
>>>
>>>
>>>
>>> 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
>>> 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.
>>>
>>>
>>>

---

From: Yaron Sheffer <[email-masked]>
Date: Fri, 30 Oct 2020 16:18:57 +0200

Hi Fabien,

One correction, JSON Schema (which I am personally advocating for, but still) does not have an IETF spec. They claim on their web site that they want it standardized, but in practice are not (yet?) moving in this direction. Their Internet Draft is unmaintained.

At a higher level, I think your discussion conflates two things: the representation of data on the wire (JSON or various mostly binary encodings) and the data modeling language, a.k.a. schema. Personally I think JSON is almost a must in our case, and if this is true, the playing field is *much* more narrow.

A major strength of JSON which you don’t mention in your comparison is the cryptographic ecosystem (JOSE): standard formats for encryption, signature etc.

I wasn’t aware of Ion. I don’t think it’s a good fit for us, still a very interesting direction.

Thanks,

                Yaron

From: Fabien Imbault <[email-masked]>
Date: Friday, October 30, 2020 at 14:53
To: Andrii Deinega <[email-masked]>
Cc: Mika Boström <[email-masked]>, Justin Richer <[email-masked]>, Yaron Sheffer <[email-masked]>, GNAP Mailing List <[email-masked]>, Dick Hardt <[email-masked]>
Subject: Re: [GNAP] Feedback on polymorphism

Hi Justin, 

> Regarding your question, what else could we propose? 

I've started a review of possibilities at https://github.com/fimbault/reasonably-polymorphic/blob/main/README.md to be followed by actual code testing. 

Cheers,

Fabien

On Thu, Oct 29, 2020 at 8:23 PM Andrii Deinega <[email-masked]> wrote:

Hi Mika, Justin, and WG,

The act (actor) claim introduced in RFC 8693 (OAuth 2.0 Token Exchange) has a JSON object as its value. This claim could be a part of AT JWT or a token introspection response and has the same semantics in both cases. The JSON object as its value may look like this

"act":
{

"act":
{

Personally, I find it to be a very expressive approach. Also, as far I as know, several (oAuth2) client libraries have good support of things like

"aud":"https://service1.example.com" and "aud":["https://service1.example.com","https://service2.example.com"]

Regards,

Andrii

On Wed, Oct 28, 2020 at 12:58 PM Fabien Imbault <[email-masked]> wrote:

Hi Yaron,

We'll indeed have to check how make it as idiomatic as possible with experts of each language (help welcome). 

Regarding the client, the variations are more limited but they do exist. Here I believe it's much more problematic than on the server side and there are at least a few actions we should take:

A) check in sec 7 if we really have a compelling reason for key and proof variants. This is derived from larger discussions on key binding as per the related note. There are quite a few open questions related to this theme. 

B) there is also the choice between value/reference that may generate complexity. 

C) More generally, as many feedbacks already have noticed, we need to have a systematic review and reduce the set of available options in the protocol. 

Unless we have a clear idea why runtime behavior requires mutability, it might be useful to have a way to define the chosen variant before hand, so that the expected behavior becomes deterministic on the client side. There are various ways it could be done in practice. 

For sure several independant implementations would help, especially if we make sure they can work together. 

Cheers 

Fabien 

Le mer. 28 oct. 2020 à 19:47, Yaron Sheffer <[email-masked]> a écrit :

Hi Fabien,

Thanks,

                Yaron

Cheers,

Fabien

Hi everyone,

{

  "name": "<string>",

  "age": <int>,

  "country": "<string>",

  "city": "<string>"

}

type Person struct {

  Name string `json:"name"

  Age int `json:"age"`

}

type Entity struct {

}

Cheers,

Mika

Hi Dick,

Fabien 

Hi Fabien

 

 

Hi Dick,

Fabien 

AS developer
RS developer
client developer
user

/Dick

Hi there, 

Back to the GNAP topic. 

Cheers.

Fabien

 

 

Justin

- version of client

- version of OS

 

{

  posture: {

    software_version: 1.2.3,

    os_version: 14.3.2

  },

  client: “client-541-ab"

}

 — Justin

/Dick

Dick,

 — Justin

Hey Justin,

 

   "client": {

   }

   object.

{ 
 "key": { 
     "proof": "bearer" 
    } 
}

/Dick

Hi Mika,

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    },

    bearer_token: true,

    bind_to_rc_key: true

}

{ 

    key: {

      proof: httpsig,

      jwk: { … key value … }

    }

}

// bearer token

{

    key: false

}

{

    key: true

}

 — Justin

Hello, everyone.

# payload 1

{

  ...,

  "public_key": {

    "alg": "rsa",

    "modulus": <BIGINT>

  }

}

# payload 2

{

  ...,

  "public_key": {

    "alg": "rsa",

  }

}

Best regards,

Mika

-- 

Mika Boström

Smarkets

 

-- 

Mika Boström

Smarkets

---

From: Fabien Imbault <[email-masked]>
Date: Fri, 30 Oct 2020 16:13:21 +0100

Hi Yaron,

Thanks a lot for the feedback, I fixed the issue related to the
standardisation status (I guess there's some historic background that I
don't know ;-)).

Is JSON the only real possible format? Probably, at least for compatibility
with pretty much everything that exists. Only TJSON could maybe be used as
an alternative (and kind of removes the need for a schema), with the
downsides that you don't have so many existing libraries and that the
community seems much smaller: 2k stars for JSON schema spec vs 65 for TJSON
spec (and the expired website SSL certificate doesn't help).

The main problem I see is that for constrained cases, CBOR won't have a
schema in a foreseeable future (at least I'm not aware of any work on
that). I know it's not our main focus right now and might not even be
covered by the current WG, but still it might become an issue at some
point.

Best,
Fabien

On Fri, Oct 30, 2020 at 3:19 PM Yaron Sheffer <[email-masked]> wrote:

> Hi Fabien,
>
>
>
> One correction, JSON Schema (which I am personally advocating for, but
> still) does not have an IETF spec. They claim on their web site that they
> want it standardized, but in practice are not (yet?) moving in this
> direction. Their Internet Draft is unmaintained.
>
>
>
> At a higher level, I think your discussion conflates two things: the
> representation of data on the wire (JSON or various mostly binary
> encodings) and the data modeling language, a.k.a. schema. Personally I
> think JSON is almost a must in our case, and if this is true, the playing
> field is **much** more narrow.
>
>
>
> A major strength of JSON which you don’t mention in your comparison is the
> cryptographic ecosystem (JOSE): standard formats for encryption, signature
> etc.
>
>
>
> *Date: *Friday, October 30, 2020 at 14:53
> *To: *Andrii Deinega <[email-masked]>
> *Cc: *Mika Boström <[email-masked]>, Justin Richer <
> [email-masked]>, Yaron Sheffer <[email-masked]>, GNAP Mailing
> List <[email-masked]>, Dick Hardt <[email-masked]>

---

From: Dick Hardt <[email-masked]>
Date: Fri, 30 Oct 2020 08:20:37 -0700

I exchanged some emails with the JSON Schema team last summer. They are
actively working on a revision to better server OpenAPI.

They felt stonewalled at the IETF and now question the value of spending
time in a standards body.

Another schema option is JSON Type Definition [1], which is built on CDDL
(RFC 8610) [2], the CBOR type language.

[1] https://tools.ietf.org/html/draft-ucarion-json-type-definition
[2] https://tools.ietf.org/html/rfc8610

ᐧ

On Fri, Oct 30, 2020 at 8:13 AM Fabien Imbault <[email-masked]>
wrote:

> Is JSON the only real possible format? Probably, at least for
> compatibility with pretty much everything that exists. Only TJSON could
> maybe be used as an alternative (and kind of removes the need for a
> schema), with the downsides that you don't have so many existing libraries
> and that the community seems much smaller: 2k stars for JSON schema spec vs
> 65 for TJSON spec (and the expired website SSL certificate doesn't help).
>
>> A major strength of JSON which you don’t mention in your comparison is
>> the cryptographic ecosystem (JOSE): standard formats for encryption,
>> signature etc.
>>
>>
>>
>> https://github.com/fimbault/reasonably-polymorphic/blob/main/README.md
>> to be followed by actual code testing.
>>
>>
>>
>> Cheers,
>>
>> Fabien
>>
>>
>>

---

From: Fabien Imbault <[email-masked]>
Date: Fri, 30 Oct 2020 16:41:41 +0100

Thanks Dick, interesting ! I'll add that to my list.
Maybe we could liaise with the JSON schema team if it helps.

In the meantime, I'll focus on how to implement my json polymorphism ;-)

On Fri, Oct 30, 2020 at 4:21 PM Dick Hardt <[email-masked]> wrote:

>>> Personally, I find it to be a very expressive approach. Also, as far I
>>> as know, several (oAuth2) client libraries have good support of things like
>>>
>>> A) check in sec 7 if we really have a compelling reason for key and
>>> proof variants. This is derived from larger discussions on key binding as
>>> per the related note. There are quite a few open questions related to this
>>> theme.
>>>
>>>
>>>

---

From: Justin Richer <[email-masked]>
Date: Fri, 30 Oct 2020 12:42:19 -0400

Thanks for putting this list together, Fabien! And thanks Dick, I was also going to point out CDDL as a potential option for a schema description language.

 — Justin

> On Oct 30, 2020, at 11:41 AM, Fabien Imbault <[email-masked]> wrote:
> 
> On Fri, Oct 30, 2020 at 4:21 PM Dick Hardt <[email-masked] <mailto:[email-masked]>> wrote:
> I exchanged some emails with the JSON Schema team last summer. They are actively working on a revision to better server OpenAPI.
> 
> They felt stonewalled at the IETF and now question the value of spending time in a standards body. 
> 
> Another schema option is JSON Type Definition [1], which is built on CDDL (RFC 8610) [2], the CBOR type language.
> 
> 
> [1] https://tools.ietf.org/html/draft-ucarion-json-type-definition <https://tools.ietf.org/html/draft-ucarion-json-type-definition>
> [2] https://tools.ietf.org/html/rfc8610 <https://tools.ietf.org/html/rfc8610>
> 
> 
> ᐧ
> 
> On Fri, Oct 30, 2020 at 8:13 AM Fabien Imbault <[email-masked] <mailto:[email-masked]>> wrote:
> Hi Yaron, 
> 
> Thanks a lot for the feedback, I fixed the issue related to the standardisation status (I guess there's some historic background that I don't know ;-)).
> 
> Is JSON the only real possible format? Probably, at least for compatibility with pretty much everything that exists. Only TJSON could maybe be used as an alternative (and kind of removes the need for a schema), with the downsides that you don't have so many existing libraries and that the community seems much smaller: 2k stars for JSON schema spec vs 65 for TJSON spec (and the expired website SSL certificate doesn't help).   
> 
> The main problem I see is that for constrained cases, CBOR won't have a schema in a foreseeable future (at least I'm not aware of any work on that). I know it's not our main focus right now and might not even be covered by the current WG, but still it might become an issue at some point. 
> 
> Best,
> Fabien   
> 
> On Fri, Oct 30, 2020 at 3:19 PM Yaron Sheffer <[email-masked] <mailto:[email-masked]>> wrote:
> Hi Fabien,
> 
>  
> 
> To: Andrii Deinega <[email-masked] <mailto:[email-masked]>>
> Cc: Mika Boström <[email-masked] <mailto:[email-masked]>>, Justin Richer <[email-masked] <mailto:[email-masked]>>, Yaron Sheffer <[email-masked] <mailto:[email-masked]>>, GNAP Mailing List <[email-masked] <mailto:[email-masked]>>, Dick Hardt <[email-masked] <mailto:[email-masked]>>
> I've started a review of possibilities at https://github.com/fimbault/reasonably-polymorphic/blob/main/README.md <https://github.com/fimbault/reasonably-polymorphic/blob/main/README.md> to be followed by actual code testing. 
> 
>  
> 
> Cheers,
> 
> Fabien
> 
>  
> 
> On Thu, Oct 29, 2020 at 8:23 PM Andrii Deinega <[email-masked] <mailto:[email-masked]>> wrote:
> 
> Hi Mika, Justin, and WG,
> 
>  
> 
>   "sub":"[email-masked] <mailto:[email-masked]>"
> }
> 
>  "sub":"https://service16.example.com <https://service16.example.com/>",
>    "act":
>    {
>      "sub":"https://service77.example.com <https://service77.example.com/>"
>    }
> }
> 
> "aud":"https://service1.example.com <https://service1.example.com/>" and "aud":["https://service1.example.com <https://service1.example.com/>","https://service2.example.com <https://service2.example.com/>"]
> 
> On Wed, Oct 28, 2020 at 12:58 PM Fabien Imbault <[email-masked] <mailto:[email-masked]>> wrote:
> 
> Hi Yaron,
> 
>  
> 
> Le mer. 28 oct. 2020 à 19:47, Yaron Sheffer <[email-masked] <mailto:[email-masked]>> a écrit :
> 
> Hi Fabien,
> 
>  
>

---

From: Fabien Imbault <[email-masked]>
Date: Fri, 30 Oct 2020 17:50:09 +0100

Yes, I didn't know about CDDL before Dick mentioned it and just made
a first test with existing libraries, that's awesome. Appendix E in the
spec highlights a few caveats between json/cbor support but no big deal.
Fabien

On Fri, Oct 30, 2020 at 5:42 PM Justin Richer <[email-masked]> wrote:

> Thanks for putting this list together, Fabien! And thanks Dick, I was also
> going to point out CDDL as a potential option for a schema description
> language.
>
>  — Justin
>
>>>> Regarding the client, the variations are more limited but they do
>>>> exist. Here I believe it's much more problematic than on the server side
>>>> and there are at least a few actions we should take:
>>>>
>>>>
>>>>
>>>> Unless we have a clear idea why runtime behavior requires mutability,
>>>> it might be useful to have a way to define the chosen variant before hand,
>>>> so that the expected behavior becomes deterministic on the client side.
>>>> There are various ways it could be done in practice.
>>>>
>>>>
>>>>
>>>> At least in the case of Go, I think the “solution” is far worse than
>>>> the problem. The code in the article you cite is very specific to the use
>>>> case and IMHO quite ugly. So my preferred Go implementation would be a
>>>> 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
>>>> 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 {
>>>>
>>>> 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
>>>> 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).
>>>>
>>>>
>>>>