Subject: Re: [OAUTH-WG] My review of draft-ietf-oauth-json-web-token-11

From: Mike Jones <[email-masked]>
Date: Mon, 3 Mar 2014 22:22:45 +0000

Hi Hannes,

My replies to your comments follow in-line.  Thanks again for writing these up.

                                                            -- Mike

-----Original Message-----
From: [email-masked] [mailto:[email-masked]] On Behalf Of Tschofenig, Hannes (NSN - FI/Espoo)
Sent: Thursday, September 12, 2013 1:07 AM
To: oauth mailing list
Subject: [OAUTH-WG] My review of draft-ietf-oauth-json-web-token-11

Hi Mike, Hi all,

As part of preparing the shepherd write-up I have read the draft and here are a few comments.

In general, the draft looks good. The comments are fairly minor.

1. Section 4: JWT Claims

In the first paragraph you write:

"

The Claim Names within a JWT Claims Set MUST be unique; recipients MUST either reject JWTs with duplicate Claim Names or use a JSON parser that returns only the lexically last duplicate member name "

I think what you want to write here is that the sender of a JWT must ensure that the claims are unique. If a JWT is, however, received with non-unique claims then some decision must be taken. You list two choices and I am wondering why not just have one. Let's just reject the JWT if that happens to ensure consistent behavior.

This was extensively discussed within JOSE and the language used is the same.  Ideally, yes, we'd reject duplicate names, but both the old and new JSON specs allow duplication, so if we're to use existing deployed parsers, that isn't really a practical option.  (We used to require rejection of duplicate names, but objections were raised to that.)

I believe it might be good to clarify that unique here means that claims may appear more than once in a JWT but you are concerned about having two claims that actually have a different semantic. Correct?

No, the issue is that either parsers will only return one (they will overwrite each other) or duplicates will cause a parsing error.  Therefore, for things to always work regardless of parser, producers can't include any duplicates.

You write: "However, in the absence of such requirements, all claims that are not understood by implementations SHOULD be ignored."

The 'SHOULD' is not good enough here. Either you ignore claims that you don't understand or you do something else. Since there does not seem to be a way to declare claims as "critical" to understand I suggest to turn this into a MUST.

Agreed.  I made this change in -18.

With every claim you add "Use of this claim is OPTIONAL.". I would suggest to move that sentence to the front and avoid repeating it with every claim. In fact you have that necessary sentence currently in Section 4.1 "None of the claims defined below are intended to be mandatory to use, but rather, provide a starting point for a set of useful, interoperable claims."

For what it's worth, Jim Schaad had requested the opposite - that the "OPTIONAL" statements be on a per-name basis - so each definition could be easily read in isolation.

Since you describe the "use" there is obviously the question about the "implementation". So, what claims in this document are mandatory to implement? All? None?

None.  It's up to the application what claims are MTI for its use case.  I added text clarifying this.

Claim Types: You distinguish between three types of claims, namely Reserved Claim Names, Public Claim Names, and Private Claim Names.

- Reserved claims are those that are registered with IANA.

 - Public Claims are (interestingly enough) also registered via IANA or use a Collision Resistant Namespace.

 - Private Claims are those that may produce collisions

Clear I would suggest to change the definition of a public claim. Let's just call the claims that are registered via IANA reserved claims.

"Reserved" was changed to "registered", both here and in JOSE, as a result of review comments from both working groups.

I also wonder why we need private claims at all when it is so easy to construct public claims?

In practice, people will use unregistered names in some contexts.  (There was a 1/2 hour presentation in AppsAWG today about this very thing!)  Given we really can't prevent this and it will happen, it's better to clearly describe the downsides and alternatives than to pretend that private names won't be used.  At least this way, people will have been warned about the consequences of their choices.

Section 4.1.1: "iss" (Issuer) Claim

You write:

"

The iss (issuer) claim identifies the principal that issued the JWT. The processing of this claim is generally application specific.

"

Would it be useful to say what people use this claim for. It might also be useful to indicate that this value cannot be relied on for any trust or access control decisions without proper cryptographic assurance. I can already see people who base their security decisions on this value without any relationship to the actual crypto of the JWT. So, one might wonder what the relationship of the crypto and the iss claim is.

I added language about making trust decisions in the Security Considerations section.  Did you have particular language in mind about what the claim is used for, beyond stating that it identifies the issuer?

Section 4.1.3: "aud" (Audience) Claim

You write:

"

The aud (audience) claim identifies the audiences that the JWT is intended for.

"

That's not a good description. You could instead write: "The aud (audience) claim identifies the recipient the JWT is intended for."

Agreed - done.

You write:

"

In the special case when the JWT has one audience, the aud value MAY be a single case sensitive string containing a StringOrURI value.

"

Shouldn't this read:

"

In the special case when the JWT has one audience, the aud value is a single case sensitive string containing a StringOrURI value.

"

No - because either "aud":"foo" or "aud":["foo"] are legal and mean the same thing.

Section 4.1.8. "typ" (Type) Claim

You write:

"

The typ (type) claim MAY be used to declare a type for the contents of this JWT Claims Set in an application-specific manner in contexts where this is useful to the application. The typ value is a case sensitive string. Use of this claim is OPTIONAL.

The values used for the typ claim come from the same value space as the typ header parameter, with the same rules applying.

"

I believe the first sentence should say: "The typ (type) claim is used to declare a type for the contents of this JWT Claims Set ....". I don't understand what the "MAY" here was supposed to indicate since if it does not declare the type of the claims then what else does it do?

Why is the typ claim actually there when there is already the same claim in the header?

The "typ" claim was removed as part of the JOSE change to use MIME type names for "typ" and "cty" header parameter values.

Section 5.1. "typ" (Type) Header Parameter

You write:

"

The typ (type) header parameter MAY be used to declare the type of this JWT in an application-specific manner in contexts where this is useful to the application. This parameter has no effect upon the JWT processing. If present, it is RECOMMENDED that its value be either JWT or urn:ietf:params:oauth:token-type:jwt to indicate that this object is a JWT.

"

Here again I would write: " The typ (type) header parameter is used to declare the type of this JWT in an application-specific manner in contexts where this is useful to the application."

Why doesn't this value have any impact on the processing? It appears to be useless? Would it be good to mandate that it is set to JWT or urn:ietf:params:oauth:token-type:jwt when the content is a JWT? Why do you leave two options for what the value is set to? Why would anyone use the longer string?

The URN value was removed as part of the JOSE change to use MIME type names for "typ" and "cty" header parameter values.

Section 5.2. "cty" (Content Type) Header Parameter

What is the relationship between cty and typ?

As described in the JOSE specs that define them, "typ" is the type of the entire object, whereas "cty" is the type of the message contained in the JWS or JWE.  Both are now MIME type values.  "cty" is used by JWTs in the specific way specified whereas "typ" can be used as needed by applications using JWTs.

Section 5.3. Replicating Claims as Header Parameters

I am not sure why you would want to have encryption of the claims and then again include them in cleartext. That would defeat the purpose of encryption. Then, you could as well just provide them in cleartext (only signed, for example).

Putting the sub value into the header does not seem to be a good idea since this may be personal data.

This showed up in a use case that Dick Hardt had, in which case he wanted to route the contents of the JWT to the recipient without being able to read the contents of the JWT itself.  In his case, there was an intermediary handling the JWT that did not have the decryption key.

It's application-specific whether the audience is private information or not.

Putting these fields into the header in general does not strike me as a good idea since you loose the ability to sign these values. They will be exposed to all security threats since they cannot be protected. Why not use a nested JWT instead?

They are still integrity-protected, because JWE uses only authenticated encryption.  They are protected from tampering or alteration.

The 'SHOULD' in this sentence particularly makes me nervous: "If such replicated Claims are present, the application receiving them SHOULD verify that their values are identical." This essentially means that if you have protected claims and someone adds unprotected stuff into the header it may mean that an application would accept that. Not a good idea!

Per the above, you can't add stuff, because of the authenticated encryption used.

Section 6 Plaintext JWTs

Why do we want plaintext JWTs? I thought that the threat analysis concluded that sending this stuff of information around without any security protection is a bad idea.

The JWT can either be cryptographically protected by a signature and/or encryption in the JWT itself or by signature and/or encryption of a data structure in which the JWT is conveyed.  For instance, if it is returned from an OAuth Token Endpoint, it is integrity protected by the channel's use of TLS and so may not need to be signed and/or encrypted in some application contexts.  OpenID Connect uses this capability in several places, for instance, as does Phil Hunt's OAuth Authentication draft.

Section 7. Rules for Creating and Validating a JWT

I am curious why this section is so extensive given that we are essentially just applying JWS and JWE here. Wouldn't a pointer to the JWS/JWE spec be sufficient?

It's longer because the JWT adds two things:  First, the contents can be either a JWS or JWE, and so there's logic described for the slightly different actions taken in the two cases.  Second, the JWT can be nested, so the logic for nesting and detecting nested JWTs is defined.  It *does* just rely on JWS and JWE for the creation and verification aspects of the JWS and JWE aspects of JWTs.

That said, I did remove a step that was actually a pure duplication of a corresponding JWS/JWE step.

Ciao

Hannes

_______________________________________________

OAuth mailing list

[email-masked]

https://www.ietf.org/mailman/listinfo/oauth