Subject: [OAUTH-WG] Plaintext JWT bug

From: Richard Barnes <[email-masked]>
Date: Thu, 1 Aug 2013 14:08:18 +0200

It has come to my attention that JWT is using "alg":"none" to create
"Plaintext JWTs".  Some of us in JOSE believe that this "alg" value should
be removed, because of a risk of downgrade attacks.  In order to do that, a
suggested revision to JWT is below.  To summarize:
-- Plaintext JWTs are not JWSs.
-- They just have a header and payload (separated by a '.')
-- The header MUST NOT contain "alg", since there's no crypto going on

Thanks,
--Richard

-----BEGIN-----
6.  Plaintext JWTs

   To support use cases where the JWT content is secured by a means
   other than a signature and/or encryption contained within the JWT
   (such as a signature on a data structure containing the JWT), JWTs
   MAY also be created without a signature or encryption.  A plaintext
   JWT is the concatenation of a base64url-encoded JWT Header, a
   period ('.') character, and the base64url-encoded JWT Claims Set.

   The header of a plaintext JWT contains parameters drawn from the
   set as the JWS header.  However, a JWT header MUST NOT contain an
   "alg" header parameter, since no cryptographic processing is being
   performed.

6.1.  Example Plaintext JWT

   The following example JWT Header declares that the encoded object is
   a Plaintext JWT:

     {"typ":"JWT"}

   Base64url encoding the octets of the UTF-8 representation of the JWT
   Header yields this Encoded JWT Header:

     eyJ0eXAiOiJKV1QifQ

   The following is an example of a JWT Claims Set:

     {"iss":"joe",
      "exp":1300819380,
      "http://example.com/is_root":true}

   Base64url encoding the octets of the UTF-8 representation of the JWT
   Claims Set yields this Encoded JWS Payload (with line breaks for
   display purposes only):

     eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
     cGxlLmNvbS9pc19yb290Ijp0cnVlfQ

   Concatenating these parts in this order with aperiod ('.') character
   between the parts yields this complete JWT (with line breaks for
   display purposes only):

     eyJ0eXAiOiJKV1QifQ
     .
     eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt
     cGxlLmNvbS9pc19yb290Ijp0cnVlfQ

-----END-----

---

From: Mike Jones <[email-masked]>
Date: Thu, 1 Aug 2013 12:20:15 +0000

This is useful because it means that you can pass both unsigned and signed content using the same syntax, with no special parsing required.  This is used in practice, for instance, to enable both unsigned and signed request objects, signed and unsigned ID Tokens, etc.

This is already in widespread use.

I'm kind of surprised that this is coming up now.  This has been in JWT since March 2011 and in the JOSE specs since the working group versions, so it's not exactly a surprise.  (The biggest change was that we moved it from JWT to JWS in March 2012, at Jim Schaad's suggestion, because it is generally useful outside of just JWTs.)  Yes, an alternative syntax could have been used, but using the "alg":"none" value to express this works fine in practice.  I don't perceive a compelling reason to change it at this point.

                                                            -- Mike

From: [email-masked] [mailto:[email-masked]] On Behalf Of Richard Barnes
Sent: Thursday, August 01, 2013 5:08 AM
To: [email-masked] WG
Subject: [OAUTH-WG] Plaintext JWT bug

It has come to my attention that JWT is using "alg":"none" to create "Plaintext JWTs".  Some of us in JOSE believe that this "alg" value should be removed, because of a risk of downgrade attacks.  In order to do that, a suggested revision to JWT is below.  To summarize:
-- Plaintext JWTs are not JWSs.
-- They just have a header and payload (separated by a '.')
-- The header MUST NOT contain "alg", since there's no crypto going on

Thanks,
--Richard

-----BEGIN-----
6.  Plaintext JWTs

     {"typ":"JWT"}

     eyJ0eXAiOiJKV1QifQ

     {"iss":"joe",
      "exp":1300819380,

     eyJ0eXAiOiJKV1QifQ
     .

-----END-----

---

From: Richard Barnes <[email-masked]>
Date: Thu, 1 Aug 2013 14:23:55 +0200

You don't view downgrade attacks as a compelling reason?

I look forward to your attempt to get this through SECDIR review.

On Thu, Aug 1, 2013 at 2:20 PM, Mike Jones <[email-masked]>wrote:

>  This is useful because it means that you can pass both unsigned and
> signed content using the same syntax, with no special parsing required.
> This is used in practice, for instance, to enable both unsigned and signed
> request objects, signed and unsigned ID Tokens, etc.****
>
> ** **
>
> This is already in widespread use.****
>
> ** **
>
> I'm kind of surprised that this is coming up now.  This has been in JWT
> since March 2011 and in the JOSE specs since the working group versions, so
> it's not exactly a surprise.  (The biggest change was that we moved it from
> JWT to JWS in March 2012, at Jim Schaad's suggestion, because it is
> generally useful outside of just JWTs.)  Yes, an alternative syntax could
> have been used, but using the "alg":"none" value to express this works fine
> in practice.  I don't perceive a compelling reason to change it at this
> point.****
>
> ** **
>
>                                                             -- Mike****
>
> ** **
>
> *From:* [email-masked] [mailto:[email-masked]] *On Behalf
> Of *Richard Barnes
> *Sent:* Thursday, August 01, 2013 5:08 AM
> *To:* [email-masked] WG
> *Subject:* [OAUTH-WG] Plaintext JWT bug****
>
> ** **
>
> suggested revision to JWT is below.  To summarize:****
>
> -- Plaintext JWTs are not JWSs.  ****
>
> -- They just have a header and payload (separated by a '.')****
>
> -- The header MUST NOT contain "alg", since there's no crypto going on****
>
> ** **
>
> Thanks,****
>
> --Richard****
>
> ** **
>
> ** **
>
> -----BEGIN-----****
>
> 6.  Plaintext JWTs****
>
> ** **
>
>    To support use cases where the JWT content is secured by a means****
>
>    other than a signature and/or encryption contained within the JWT****
>
>    (such as a signature on a data structure containing the JWT), JWTs****
>
>    MAY also be created without a signature or encryption.  A plaintext****
>
>    JWT is the concatenation of a base64url-encoded JWT Header, a ****
>
>    period ('.') character, and the base64url-encoded JWT Claims Set.****
>
> ** **
>
>    The header of a plaintext JWT contains parameters drawn from the ****
>
>    set as the JWS header.  However, a JWT header MUST NOT contain an****
>
>    "alg" header parameter, since no cryptographic processing is being****
>
>    performed.****
>
> ** **
>
> 6.1.  Example Plaintext JWT****
>
> ** **
>
>    The following example JWT Header declares that the encoded object is***
> *
>
>    a Plaintext JWT:****
>
> ** **
>
>      {"typ":"JWT"}****
>
> ** **
>
>    Base64url encoding the octets of the UTF-8 representation of the JWT***
> *
>
>    Header yields this Encoded JWT Header:****
>
> ** **
>
>      eyJ0eXAiOiJKV1QifQ****
>
> ** **
>
>    The following is an example of a JWT Claims Set:****
>
> ** **
>
>      {"iss":"joe",****
>
>       "exp":1300819380,****
>
>       "http://example.com/is_root":true}****
>
> ** **
>
>    Base64url encoding the octets of the UTF-8 representation of the JWT***
> *
>
>    Claims Set yields this Encoded JWS Payload (with line breaks for****
>
>    display purposes only):****
>
> ** **
>
>      eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt****
>
>      cGxlLmNvbS9pc19yb290Ijp0cnVlfQ****
>
> ** **
>
>    Concatenating these parts in this order with aperiod ('.') character***
> *
>
>    between the parts yields this complete JWT (with line breaks for****
>
>    display purposes only):****
>
> ** **
>
>      eyJ0eXAiOiJKV1QifQ****
>
>      .****
>
>      eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFt****
>
>      cGxlLmNvbS9pc19yb290Ijp0cnVlfQ****
>
>      ****
>
> ** **
>
> -----END-----****
>
> ** **
>

---

From: Mike Jones <[email-masked]>
Date: Thu, 1 Aug 2013 12:26:11 +0000

You prevent downgrade attacks by having your application reject algorithms that don't meet their security requirements.  Unless your application explicitly chooses to accept "alg":"none", the same code that would reject "alg":"rot13" would reject "alg":"none".

If your application isn't rejecting unacceptable algorithms, that's an application bug - not a spec bug.

                                                            -- Mike

From: Richard Barnes [mailto:[email-masked]]
Sent: Thursday, August 01, 2013 5:24 AM
To: Mike Jones
Cc: [email-masked] WG
Subject: Re: [OAUTH-WG] Plaintext JWT bug

On Thu, Aug 1, 2013 at 2:20 PM, Mike Jones <[email-masked]<mailto:[email-masked]>> wrote:

                                                            -- Mike

From: [email-masked]<mailto:[email-masked]> [mailto:[email-masked]<mailto:[email-masked]>] On Behalf Of Richard Barnes
Sent: Thursday, August 01, 2013 5:08 AM
To: [email-masked]<mailto:[email-masked]> WG
Subject: [OAUTH-WG] Plaintext JWT bug

Thanks,
--Richard

-----BEGIN-----
6.  Plaintext JWTs

     {"typ":"JWT"}

     eyJ0eXAiOiJKV1QifQ

     {"iss":"joe",
      "exp":1300819380,

     eyJ0eXAiOiJKV1QifQ
     .

-----END-----

---

From: Richard Barnes <[email-masked]>
Date: Thu, 1 Aug 2013 14:35:58 +0200

This thread is about the proposed change to JWT.  Further discussion of the
risks of "alg":"none" will be on the JOSE list.

--Richard

On Thu, Aug 1, 2013 at 2:26 PM, Mike Jones <[email-masked]>wrote:

>  You prevent downgrade attacks by having your application reject
> algorithms that don’t meet their security requirements.  Unless your
> application explicitly chooses to accept “alg”:”none”, the same code that
> would reject “alg”:”rot13” would reject “alg”:”none”.****
>
> ** **
>
> If your application isn’t rejecting unacceptable algorithms, that’s an
> application bug – not a spec bug.****
>
> ** **
>
>                                                             -- Mike****
>
> ** **
>
> *From:* Richard Barnes [mailto:[email-masked]]
> *Sent:* Thursday, August 01, 2013 5:24 AM
> *To:* Mike Jones
> *Cc:* [email-masked] WG
> *Subject:* Re: [OAUTH-WG] Plaintext JWT bug****
>
> ** **
>
> You don't view downgrade attacks as a compelling reason?****
>
> ** **
>
> I look forward to your attempt to get this through SECDIR review.****
>
> ** **
>
> On Thu, Aug 1, 2013 at 2:20 PM, Mike Jones <[email-masked]>
> wrote:****
>
> This is useful because it means that you can pass both unsigned and signed
> content using the same syntax, with no special parsing required.  This is
> used in practice, for instance, to enable both unsigned and signed request
> objects, signed and unsigned ID Tokens, etc.****
>
>  ****
>