Subject: Re: [http-auth] a review of draft-ietf-httpauth-scram-auth

From: Julian Reschke <[email-masked]>
Date: Tue, 15 Apr 2014 16:41:32 +0200

On 2014-03-08 17:40, Tony Hansen wrote:
> ...
> 1. What is different in HTTP SCRAM from the original SASL SCRAM
> documented in RFC 5802?
> ...
> Now note: actual differences do exist. In particular, I noted several
> specific differences, although I may have missed some:
>
> a) The specification of the gs2 header is different. It has been
> "adjusted" to match the name=value format of www-authenticate's
> 1#challenge. In addition, the use of authzid has been lost. For example,
> ...
> b) The handling of white space and double quotes.
>
> The consequence of these substantive differences is that existing
> implementations of SASL SCRAM can NOT be used to implement HTTP SCRAM.
> Personally I think that this is a bad consequence.
>
> There are two fixes for going forward:
>
> A) Accept that there are differences. If we do this, I feel that there
> MUST MUST MUST be a serious WARNING section added for implementers to
> let them know that current SASL SCRAM libraries can NOT be used.
> B) Get rid of these differences. See below.
> ...

As far as I can tell, this change was essential. Historically, auth 
schemes have defined their own parsing, of challenges, but the problem 
is that the overall syntax of challenges in HTTP authentication is 
defined by the framework, not the authentication scheme. Thus, you need 
a *generic* parser before you even get to the point where you can 
dispatch to auth-scheme specific code.

> Regarding the handling of white space, one of the hardest parts to get
> right with SCRAM is getting the inputs into the hash algorithms exactly
> right, on BOTH sides. For example, if one side includes a space and the
> other side does not, then the hashes will not match.
>
> If you look at the ABNF for "challenge" (HTTP-P7, HTTP-P1) and the ABNF
> for the elements for the name=value pairs in HTTP SCRAM, you will find
> that they are not compatible. The HTTP definition is a superset in that
> it allows for the use of quoted strings and allows for white space to be

It allows quoted-string and token as this reflects reality in parsing 
header fields like these.

> included in various locations, neither of which are allowed by the ABNF
> for the SCRAM-specific elements. I don't think that the ABNF for
> auth-param is compatible at all with gs2-header p= option because
> token68 does not allow an "=".

HTTP uses BWS around "=", which is described as:

"The BWS rule is used where the grammar allows optional whitespace only 
for historical reasons. A sender MUST NOT generate BWS in messages. A 
recipient MUST parse for such bad whitespace and remove it before 
interpreting the protocol element.".

It also allows OWS (optional whitespace) *between* parameters. That's 
just common in HTTP, and, again, is true for all HTTP auth schemes that 
use parameters.

> ...
> 3) method agility
>
> Unless I'm totally mistaken, the issues with method agility are
> associated with the protocol exchange example shown in section 5 is
> incorrect with respect to the realm and the description of the original
> 401 Unauthorized challenge along with subsequent descriptions of the realm.
>
> I think it's worth showing a *complete* example 401 challenge exchange,
> filling in the "server might have returned 401 Unauthorized first"
> comment. THIS is where the server might provide one or more realm names
> as part of its challenge. For example, you might see:
>
>      WWW-Authenticate: Basic  Digest realm="realm1"
>          Digest realm="realm2" Digest realm="realm3"
>          SCRAM-SHA-1 realm="realm3" SCRAM-SHA-1 realm="realm4"

Commas are missing here.

> ...
> It might be worth introducing SOMEWHERE the terms "challenge #0" as the
> server challenge that lists the acceptable authentication schemes and
> their optional realms, and then the client response is "response #1"
> followed by "challenge #1", and counting up from there. In general
> terms, challenge #0 always lists the available authentication schemes
> and their optional realms (along with any other initial parameters that
> need to be passed along with that authentication scheme). Response #1
> specifies the next round of parameters for the given authentication
> scheme chosen by the client. Challenge #1 either returns the 200 with an
> optional Authorization-Info or another 401 Unauthorized with a
> WWW-Authenticate header. If this is an authentication scheme that allows
> another round to be used for additional information, Challenge #1 would
> also include a sid= parameter (or WWW-Authentication-Sid header as has
> been suggested elsewhere). Subsequent Responses (#2 and beyond) then use
> the same sid=/WWW-Authentication-Sid value to tie the challenges and
> response together.
>
> I'm not sure where SOMEWHERE should be. Is it too late to get this into
> HTTP BIS P7?

Yes, it's too late.

 > ...
> Getting Rid of the Differences with SASL SCRAM
>
> Now I'm going to present an alternative way of fixing some of the
> problems above. The basic idea is to say that the SCRAM-SHA-1 payloads
> are exactly as specified in RFC 5802, but are base64-encoded for use
> within HTTP. This is exactly the SASL authentication split that is used
> by all other application protocols that use SASL: the SASL mechanism
> specifies what information needs to be included in any given round of
> exchange and the application protocol specifies how that information is
> wrapped for transmission within the application protocol. For example,
> an application protocol could use base64 encoding of that data (as
> suggested here), or could use run-length-encoding if it's binary, or
> could use quoted-printable or hex or whatever. The important thing is
> that is a strict separation of responsibility. The application protocol
> doesn't care what the data is and what is included within it; it just
> has some mechanism for getting that data across the protocol boundary
> safely. The application protocol restores that data back to its octet
> form and passes that data into the authentication mechanism. The
> response from the authentication mechanism is then encoded for the
> application-layer response.
>
> How does this look for HTTP SCRAM? I'm going to use the word "payload"
> to represent the parameter that holds the SCRAM-SHA-1 payload. Each
> challenge and response becomes 1) the scram name, 2) either the realm or
> sid value, and then 3) the payload value. (I don't care what the
> parameter name is called.) In ABNF, this would be something like this:
>
>      challenge-scram   = scram-name WS realm-or-sid BWS "," OWS
> "payload=" payload-value
>      credentials-scram   = scram-name WS realm-or-sid BWS "," OWS
> "payload=" payload-value
>      realm-or-sid = ( "realm=" realm-value / "sid=" sid-value )
>      payload-value = 1*base64 / DQUOTE 1*base64 DQUOTE

Note that any parameter value that is in DQUOTEs must use quoted-string 
syntax.

> ...

Best regards, Julian