Hi Hannes,
My replies to your comments follow in-line. Thanks again for writing these up.
-- Mike
-----Original Message-----
From: [email protected] [mailto:[email protected]] 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 protected]
https://www.ietf.org/mailman/listinfo/oauth
_______________________________________________
OAuth mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/oauth