News for hackers. Stuff that matters.
Re:OAuth 3 by parhamn on Thursday October 22, 2020 @07:09AM (#24856777)
> Polymorphic JSON. The protocol elements have different data types that convey additional contextual meaning, allowing us to avoid mutually exclusive protocol elements and design a more succinct and readable protocol.

Yeah... let's not please.

Re:OAuth 3 by samprotas on Thursday October 22, 2020 @01:18PM (#24860464)
The number of comments here specifically upset with this part of the current design is a bit discouraging, but not necessarily surprising.

Yes, many mainstream languages have near-zero support for Tagged/Discriminated Unions or Enums with Associated Data or Algebraic Data Types (pick your favorite name for the same concept). This is a limitation of those languages, which should not force a language-agnostic protocol to adopt the lowest common denominator of expressiveness.

Consider the problem they're avoiding of mutually exclusive keys in a struct/object. What do you do if you receive more than one? Is that behavior undefined? If it is defined, how sure are you that the implementation your package manager installed for you doesn't just pick one key arbitrarily in the name of "developer friendliness" leading to security bugs? This seems like a much more bug-ridden problem to solve than having to write verbose type/switching golang/java.

Implementing more verbose deserialization code in languages with no support for Tagged Unions seems like a small price to pay for making a protocol that leaves no room for undefined behavior.

To be clear, _many_ statically typed languages have perfect support for this concept (Rust/Swift/Scala/Haskell, to name a few).

Re:OAuth 3 by parhamn on Thursday October 22, 2020 @02:36PM (#24861603)
> To be clear, _many_ statically typed languages have perfect support for this concept (Rust/Swift/Scala/Haskell, to name a few).

No they don't, at least in the way you're selling it. The "limitation" here is JSON which doesn't attach type information. You're going to have to implement some typing protocol on top of the JSON anyway which will face similar problems to the ones you raised (unless you do some trait based inference which could be ambiguous and dangerous).

If they were Enums/Unions over a serialization protocol like protobuf, maybe your case makes sense. Even then, Im guessing a large % of the OAuth 3 requests will go through Java/Golang libraries, so on a practical level this is a bad idea too.

Re:OAuth 3 by samprotas on Thursday October 22, 2020 @03:28PM (#24862339)
I agree that having multiple different types of "object values" share one JSON key with no explicit "type" tag is asking for trouble with extensibility and conflicts.

That said, I think the constructive suggestion would be: "add a type tag to all objects in a union" (something suggested elsewhere in this thread).

Their "handles" can still claim "just a string" to save bandwidth in the common case, arrays can still represent "many things" and objects require "type" to be dis-ambiguous.

Most of the comments below don't mention the (real and important, but easily solvable) issue you've brought up however. They primarily fall into one of two buckets:

- It's hard to work with data shaped like this in my language (ex: java/go)

- It's hard to deserialize data shaped like this into my language that has no tagged unions (ex: java/go)

My biggest counterpoint to all of these complaints is: The fact that your language of choice cannot represent the concept of "one of these things" doesn't change the fact that this accurately describes reality sometimes.

A protocol with mutually exclusive keys (or really anything) by convention is strictly more bug-prone than a protocol with an object that is correct by construction.

Re:OAuth 3 by oaiey on Thursday October 22, 2020 @04:55PM (#24863202)
A protocol which is cumbersome to implement in many languages. Hmmm what can't go wrong. Partial support, late support of extensions, bugs,...

IMHO: a very bad choice. Complicated basic and higher level elements of protocols are the death of them (remember SOAP). I follow the train of thoughts to not restrict yourself too much but if (eg) java or C++ cannot implement it easy, not a good idea.

Re:OAuth 3 by samprotas on Thursday October 22, 2020 @05:44PM (#24863625)
Protobuf supports "oneof" which is also cumbersome to implement in these same languages but all of them support it (with some extra LOC and no exhaustiveness checking watching your back).

Java/Go/C++ are perfectly capable of parsing a "type" key and conditionally parsing different shaped data. If you make a programming mistake here, you'll get a parse error (bad, but not a security problem). The pushback seems to be that a Java/Go/C++ implementation adds LOCS and won't gain much by doing this extra step so lets make the protocol itself match match their (less precise) data representation.

FWIW there is work towards improving Java in this regard: https://cr.openjdk.java.net/~briangoetz/amber/pattern-match....

Re:OAuth 3 by oaiey on Friday October 23, 2020 @01:11AM (#24866210)
But is not that elementary OOP polymorphism? It all depends on the fact whether the type is annotated or whether it needs to be analyzed from the data by probing. And types annotation are present in protobuf parts I remember :).
Re:OAuth 3 by Touche on Friday October 23, 2020 @08:26AM (#24868715)
> This is a limitation of those languages, which should not force a language-agnostic protocol to adopt the lowest common denominator of expressiveness.

It's an intentional decision made by those languages in order to focus on other things. If your intent is to be language-agnostic, then yeah, going with lowest common denominator concepts is exactly what you need to do. If you just want to write a Haskell auth implementation using your favorite pet language features, then write a Haskell auth implementation.

Re:OAuth 3 by GordonS on Thursday October 22, 2020 @02:36PM (#24861599)
It's not the same as union types, but you can also often achieve polymorphic serialisation with any OO language, through the use of interfaces.
Re:OAuth 3 by dgritsko on Thursday October 22, 2020 @02:42PM (#24861695)
My fingers are firmly crossed that DUs make their way into C# 10... https://github.com/dotnet/csharplang/blob/master/proposals/d...
Re:OAuth 3 by sk5t on Thursday October 22, 2020 @09:29AM (#24857753)
I'm in vigorous agreement here--polymorphic JSON is far more difficult to deserialize safely, and every instance I've seen of this in the wild has been the output of careless or deeply ignorant makers.
Re:OAuth 3 by kevincox on Thursday October 22, 2020 @10:48AM (#24858575)
Yeah, put a `type` tag in there and call it a day.
Re:OAuth 3 by oblio on Thursday October 22, 2020 @08:26AM (#24857242)
I'm not sure I get this, does the data type change depending on context? Is that what they mean?
Re:OAuth 3 by q3k on Thursday October 22, 2020 @09:51AM (#24857979)
It means sometimes you'll get:

    { foo: { bar: "baz" }}
and other times you'll get

    { foo: "something else" }
Good luck!
Re:OAuth 3 by maerF0x0 on Thursday October 22, 2020 @11:21AM (#24858968)
Polymorphic JSON is such a PITA for strongly typed languages.

    var data map[string]interface{}
    //.. 
    switch t := data["foo"].(type) {
         case string:
         case interface{}
    }

imagine that for every key...
Re:OAuth 3 by speedgoose on Thursday October 22, 2020 @11:30AM (#24859070)
In my humble opinion, Golang is pretty verbose in a bad way when it comes to JSON. Rust and the crate serde_json are also strongly typed and it's a lot better.
Re:OAuth 3 by curryst on Thursday October 22, 2020 @01:38PM (#24860722)
Yeah, having done this, it's extremely verbose if you have all your error handling in there due to the verbosity of dealing with JSON and explicit return values instead of exceptions. By far my greatest annoyance is that []interface{} cannot be directly cast to []concreteType. Having to make a sized slice and type assert each value is annoying. Require validation of the values for even more "if err != nil" fun.

Many Go advocates seem to consider the verbosity a feature, because it's explicit and forbids any clever-but-confusing tricks.

Re:OAuth 3 by q3k on Thursday October 22, 2020 @11:40AM (#24859196)
How would you express deserializing these 'polymorphic JSON' objects using serde/Rust?
Re:OAuth 3 by speedgoose on Thursday October 22, 2020 @11:44AM (#24859255)
Using a rust enum I guess.
Re:OAuth 3 by q3k on Thursday October 22, 2020 @11:54AM (#24859359)
You're right, this does seem to work [1]. I wasn't aware that serde would attempt to deserialize multiple enum variants until something matches.

[1] - https://serde.rs/enum-representations.html#untagged

Re:OAuth 3 by masklinn on Thursday October 22, 2020 @12:05PM (#24859509)
Yeah that's a rather common scheme out there so Serde does provide built-in support for this deserialisation. Probably better for deserialisation performances to use properly tagged enums, but if you don't have a choice Serde's got your back.
Re:OAuth 3 by rmrfrmrf on Thursday October 22, 2020 @03:41PM (#24862484)

    { foo: { length: 1.7976931348623157e+308 } }
Re:OAuth 3 by sroussey on Thursday October 22, 2020 @03:08PM (#24862063)
So, like Apple and in app payments then...
Re:OAuth 3 by golergka on Thursday October 22, 2020 @08:40AM (#24857357)
> XYZ’s protocol is not just based on JSON, but it’s based on a particular technique known as polymorphic JSON. In this, a single field could have a different data type in different circumstances. For example, the resources field can be an array when requesting a single access token, or it can be an object when requesting multiple named access tokens. The difference in type indicates a difference in processing from the server. Within the resources array, each element can be either an object, representing a rich resource request description, or a string, representing a resource handle (scope).

This is horrible.

Re:OAuth 3 by pwinnski on Thursday October 22, 2020 @09:24AM (#24857727)
This is definitely not a protocol dreamed up by, say, Java developers.

Obviously it's doable in Java, but I'm hard-pressed to imagine a Java developer would think of such a thing.

Re:OAuth 3 by mumblemumble on Thursday October 22, 2020 @10:11AM (#24858210)
The only time I've ever encountered an API that used it extensively, it was done by a company that does all their implementation in Java.

My best guess at what happened, based on the shape of the API, is that they implemented it by taking their pre-existing domain model, which had a fairly deep subclassing hierarchy, liberally sprinkled some annotations from com.fasterxml.jackson.annotation, and dumped the result straight onto the wire.

You could absolutely do an object-oriented codebase where two different subclasses have fields with the same name and different types, and, depending on how you structure your code, it might not be too painful. And it's fairly easy to imagine someone serializing a structure like that to JSON without ever meditating on the fact that JSON won't retain the all the type information.

Ironically, the end result was an API that is nigh-impossible to consume from Java. I ended up writing a façade in Python.

I've also seen little bits of this happen in the internal APIs at my current company. Also a Java shop, also a result of trying to directly connect an internal object model to the API. I've never seen it done in an API implemented in a dynamic or functional language.

Re:OAuth 3 by pwinnski on Thursday October 22, 2020 @11:34AM (#24859117)
I hadn't considered the one-way nature of dumping Java classes to JSON.

Mainly because I work with classes that are serialized both to and from JSON, rather than having Jackson annotations added much later.

I can see it now. Horrifying! I'm sorry for your troubles.

Re:OAuth 3 by mumblemumble on Thursday October 22, 2020 @11:49AM (#24859312)
My take-away is this: Protocols should always be defined independently of any existing code.

The code-first approach only works well when you're doing something self-contained. Which, an API, almost by definition, is not.

Re:OAuth 3 by pwinnski on Thursday October 22, 2020 @02:09PM (#24861189)
I generally try to design APIs from a consumer perspective, and then usually I end up with something RESTful. Let the server do whatever it has to do, you know?
Re:OAuth 3 by tasogare on Thursday October 22, 2020 @09:35AM (#24857803)
This is a few magnitude even more infuriating than a spec I have to work with at work, where some keys are required to be URI...
Re:OAuth 3 by golergka on Thursday October 22, 2020 @11:20AM (#24858947)
I work in Typescript, which is arguably the best mainstream language suited to type such things, and still. This is insane.
Re:OAuth 3 by alyandon on Thursday October 22, 2020 @10:02AM (#24858118)
Lovely - I can't wait to see how horrible something like that is to implement in a language like Go.
Re:OAuth 3 by dullgiulio on Thursday October 22, 2020 @01:01PM (#24860266)
You have to implement UnmarshalJSON. Between each attempt to deserialize into a possible struct, be careful to return on errors that are not JSON serialisation errors (for example caused by reading from the underlying Reader, etc.)

It's ugly and verbose but there is no need to use empty interface.

Re:OAuth 3 by CameronNemo on Thursday October 22, 2020 @11:57AM (#24859394)
Sounds like a golang problem. Rust can easily handle it with union types from what I have seen.
Re:OAuth 3 by meddlepal on Thursday October 22, 2020 @11:00AM (#24858719)
I hope you enjoy working with interface{}

_sigh_

Re:OAuth 3 by nullandvoid on Thursday October 22, 2020 @10:17AM (#24858268)
interface{} to the rescue
Re:OAuth 3 by mumblemumble on Thursday October 22, 2020 @10:00AM (#24858087)
Yeah, pretty much exactly that.

The only time I've had to deal with it in the wild was a terrible experience. As a consumer, you couldn't make any decisions with confidence without first making a careful study of the documentation. For every. single. decision.

Re:OAuth 3 by nyanpasu64 on Thursday October 22, 2020 @06:24PM (#24863927)
YAML has !Tag syntax for expressing polymorphism. Shame that nobody uses YAML because the standard is so complex, and shame that AppVeyor uses a single-element key-value mapping instead of a tag for this purpose...
Re:OAuth 3 by thosakwe on Thursday October 22, 2020 @12:28PM (#24859824)
Yeah... This is the same sort of thing you see with, say, ActivityPub, that makes it a massive pain, if not totally impossible to implement it in a statically-typed language.