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

From: "Tschofenig, Hannes (NSN - FI/Espoo)" <[email-masked]>
Date: Thu, 12 Sep 2013 08:07:02 +0000

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. 

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? 

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. 

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

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?

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. 

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

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. 

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

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

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? 

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? 

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

What is the relationship between cty and typ? 

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.

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? 

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!

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.

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? 

Ciao
Hannes