Subject: [OAUTH-WG] Why not use a server-supplied nonce (was: HTTP MAC Authentication Scheme)

From: Adam Barth <[email-masked]>
Date: Wed, 8 Jun 2011 23:30:28 -0700

[Trimming the CC to just the OAuth WG.]

On Wed, Jun 8, 2011 at 8:53 PM, Robert Sayre <[email-masked]> wrote:
> On Wed, Jun 8, 2011 at 10:32 AM, Eran Hammer-Lahav <[email-masked]> wrote:
>>> -----Original Message-----
>>> From: Tim [mailto:[email-masked]]
>>> Sent: Wednesday, June 08, 2011 8:32 AM
>>
>>> At risk of repeating myself: Why not just adapt HTTP Digest for OAuth?
>>> That is not just rhetorical, it is a genuine question.  What is HTTP Digest
>>> missing that you need?
>
> Digest has a bunch of problems. See this document
>
> http://tools.ietf.org/html/draft-ietf-httpbis-security-properties-05#section-2.2.2
>
> for a short tour of them.
>
>> The latest version of this draft:
>>
>> http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-00
>>
>> Includes a Design Constraints section which tries to explain this:
>>
>>   Unlike the HTTP Digest authentication scheme, this mechanism does not
>>   require interacting with the server to prevent replay attacks.
>>   Instead, the client provides both a nonce and a timestamp, which the
>>   server can use to prevent replay attacks using a bounded amount of
>>   storage.
>
> It's not obvious to me why the mechanism in the draft is better than a
> server-generated nonce and/or opaque string, as found in Digest.

Maybe I'm not completely clear how a mechanism with a server-supplied
nonce would work.  How do you avoid having to make a round-trip to the
server for every request?

> The mechanism in the draft can be bitten by clock skew problems, and
> having the server send a nonce doesn't necessarily require an
> unbounded amount of storage. I'm sorry if I've missed previous
> discussion on this issue, but could someone explain?

I think we've handled most of the clock skew problems by using
relative time rather than absolute time.  I'd certainly consider a
mechanism with a server-supplied nonce if you have one in mind.

>>   Also unlike Digest, this mechanism is not intended to
>>   protect the user's password itself because the client and server both
>>   have access to the key material in the clear.  Instead, servers
>>   should issue a short-lived derivative credential for this mechanism
>>   during the initial TLS setup phase.
>
> That makes sense. I'm having trouble reconciling the Design
> Constraints section (1.1) with the section on Entropy of MAC Keys
> (7.5). How long are these keys supposed to be around in practice?

I'd recommend using a MAC key of roughly the same length as the block
size of the MAC.  For example, for hmac-sha-1, I'd use 20 bytes.

> Also, Adam wrote "this mechanism is for folks who cannot or will not
> deploy TLS". How does that statement fit here?

Often the issues surrounding deploying TLS revolve around third-party
integrations, such as advertisements.  This mechanism side-steps those
issues, albeit providing less security than TLS.

Adam

---

From: Robert Sayre <[email-masked]>
Date: Thu, 9 Jun 2011 19:03:37 -0700

> server for every request?

Maybe I'm confused about the expected flow here. It's not clear to me
where the initial credentials are coming from, or how much the server
knows about the MAC credentials. The specification has multiple
servers (resource servers and authorization servers) in play
sometimes, but other times it refers to "the server". Also, section 4
makes it seem like quite a lot coordination is expected between the
authorization server and the resource server. This might all be
obvious to someone who lives and breathes OAuth, but I think it is
worth clarifying.

Here's what I was thinking: The example in section 1.1 includes an
initial 401 response. If that initial 401 response is expected, then
the server can include some domain-wide data in the WWW-Authenticate
header, and refresh it at will, even in successful responses.

GET /resource/1 HTTP/1.1
Host: example.com

...

HTTP/1.1 401 Unauthorized
WWW-Authenticate: MAC opaque="abc123abc123"

...

GET /resource/1 HTTP/1.1
Host: example.com
Authorization: MAC ... opaque="abc123abc123"

...

HTTP/1.1 200 OK
WWW-Authenticate: MAC opaque="def456def456"

...

GET /resource/2 HTTP/1.1
Host: example.com
Authorization: MAC ... opaque="def456def456"

That opaque string can be anything the server wants, and it can change
with every request, or less often. Adding this field could help
servers even if it doesn't , in cases where a misbehaving client is
getting the client nonce wrong.

If the goal of the scheme is to avoid encountering a 401 even for the
initial request, then I suggest updating the example in section 1.1.

> size of the MAC.  For example, for hmac-sha-1, I'd use 20 bytes.

I was asking about how often keys might expire. Section 7.5 says
something like 2 weeks. What can we reasonably expect from the use
cases we have in mind?

- Rob

---

From: Adam Barth <[email-masked]>
Date: Thu, 9 Jun 2011 22:25:48 -0700

> initial request, then I suggest updating the example in section 1.1.

What happens when the client wants to send more than one request at a
time to the server?  For example, when loading a web page, browsers
often open multiple sockets to send multiple request in parallel to
improve performance.

The normal flow in the browser setting does not use 401 and is as follows:

Client ----> Server (HTTPS)
GET /login

Server ----> Client (HTTPS)
200 OK
Set-Cookie: SID=3048jhseofhoesdfdf; MAC-Key=OIneoiunf;
MAC-Algorithm=hmac-sha-1; Path=/

Client ----> Server (HTTPS)
POST /login
Authorization: MAC id="SID", nonce="2:ion308r32"; mac="ow8fnwnougview4t0="
username=sayrer&password=tacotacotaco

The session is now established.  Commonly, we'd expect the session to
contain a mix of HTTP and HTTPS requests.  Each request comes with a
new nonce and a mac, etc.

> something like 2 weeks. What can we reasonably expect from the use

Yes.  Their lifetime should be commensurate with session cookies.
(This mechanism really just adds a little more security to session
cookies.)

Adam

---

From: Robert Sayre <[email-masked]>
Date: Fri, 10 Jun 2011 10:42:04 -0700

> often open multiple sockets to send multiple request in parallel to

In my example, I changed it with each request just to show how it
might work if the server changed it with every request. FWIW, section
3.2.3 of RFC2617 covers exactly this tradeoff.

> The normal flow in the browser setting does not use 401 and is as follows:

OK, but there's still an initial challenge that fulfills the same
role. I wasn't clear on the coordination present between the first and
second requests below. Now I am.

> new nonce and a mac, etc.

Perhaps some confusion has been caused by my use of the word "nonce".
I have been using it as Digest does, where the server nonce is only
sent with an authentication challenge, and then reused by the client
until the server decides it is stale. So, the client can use the same
server nonce many times. In the flow above, a server nonce would be
sent in the first response, and then reused by the client.

A client nonce is still worth including (just a random string), but I
still think giving the server a way to determine the age of the
credentials without relying on the client would be more reliable.
Let's call my proposed addition the "opaque" parameter. The client
sends it back unchanged, just like the id. In the example below, the

Server ----> Client (HTTPS)
200 OK
Set-Cookie: SID=3048jhseofhoesdfdf; MAC-Key=OIneoiunf;
MAC-Algorithm=hmac-sha-1; Path=/;
Opaque='MTMwNzcyNjExMjofeosXZh7sTFT1mBGkKAw6AoOOQQ=='

Client ----> Server (HTTPS)
POST /login
Authorization: MAC id="SID", nonce="2:ion308r32"; mac="ow8fnwnougview4t0=";
Opaque='MTMwNzcyNjExMjofeosXZh7sTFT1mBGkKAw6AoOOQQ=='
username=sayrer&password=tacotacotaco

Below, I included a little python session showing a simple example of
how this might work. It allows the server to check the age of the
credentials, check that it generated the age that was given, and
/then/ hit the authentication database.

This is just one use of an opaque field that servers might want to
try. I suppose this data could get stuffed into the SID too. Is that
the idea?

- Rob

>>> import hashlib
>>> import base64
>>> import time
>>> private_key = "foobar"
>>> timestamp = str(int(time.time()))
>>> timestamp
'1307726112'
>>> m = hashlib.sha1()
>>> m.update(timestamp + private_key)
>>> base64.b64encode(timestamp + ":" + m.digest())
'MTMwNzcyNjExMjofeosXZh7sTFT1mBGkKAw6AoOOQQ=='
>>> # our outgoing opaque value	^^
...

>>> # incoming request
...
>>> incoming_opaque = base64.b64decode('MTMwNzcyNjExMjofeosXZh7sTFT1mBGkKAw6AoOOQQ==')
>>> incoming_opaque
'1307726112:\x1fz\x8b\x17f\x1e\xecLT\xf5\x98\x11\xa4(\x0c:\x02\x83\x8eA'
>>> timestamp = int(incoming_opaque[:incoming_opaque.find(':')])
>>> timestamp
1307726112
>>> # now check the hash
...
>>> incoming_hash = incoming_opaque[incoming_opaque.find(':') + 1:]
>>> m = hashlib.sha1()
>>> m.update(str(timestamp) + private_key)
>>> m.digest() == incoming_hash
True
>>> # now look at the MAC
...

---

From: Adam Barth <[email-masked]>
Date: Fri, 10 Jun 2011 10:51:12 -0700

On Fri, Jun 10, 2011 at 10:42 AM, Robert Sayre <[email-masked]> wrote:
> sends it back unchanged, just like the id.

That already exists in the scheme.  It's just the value of the cookie.

> try. I suppose this data could get stuffed into the SID too. Is that

Yep.

In talking with folks who run large web sites, they already have a
session identifier cookie that contains most of the information you'd
want to encode in this opaque value.  For example, most sites include
an "issue date" in their session identifiers so they can discard old
values.

One possibility is to include the value of the Cookie header in the
MAC.  Then sites could use Set-Cookie to change a server-side nonce,
if they wanted.  So far there's hasn't been much demand for that
feature from server operators I've talked with.

Adam

---

From: Robert Sayre <[email-masked]>
Date: Fri, 10 Jun 2011 11:36:39 -0700

>> try. I suppose this data could get stuffed into the SID too. Is that

OK, this is all much clearer. Could the draft include these
explanations and examples? It seems like the draft is obfuscated right
now. Why not just plainly state something similar to

"This mechanism really just adds a little more security to session cookies."

in the introduction? I hope it isn't because of HTTP religion or
something like that.

- Rob

---

From: Adam Barth <[email-masked]>
Date: Fri, 10 Jun 2011 12:04:36 -0700

> in the introduction? I hope it isn't because of HTTP religion or

Sounds like a good idea.

Adam

---

From: Eran Hammer-Lahav <[email-masked]>
Date: Fri, 10 Jun 2011 15:19:25 -0700

> From: Robert Sayre [mailto:[email-masked]]
> Sent: Friday, June 10, 2011 11:37 AM
> To: Adam Barth
> Cc: Eran Hammer-Lahav; OAuth WG
> Subject: Re: Why not use a server-supplied nonce (was: HTTP MAC
> Authentication Scheme)
> 
> OK, this is all much clearer. Could the draft include these explanations and
> examples? It seems like the draft is obfuscated right now. Why not just
> plainly state something similar to
> 
> in the introduction? I hope it isn't because of HTTP religion or something like
> that.

We can make it clearer with regard to session cookies, but overall, the mechanism is just a cleanup of the OAuth 1.0 MAC functionality.

EHL

---

From: Adam Barth <[email-masked]>
Date: Fri, 10 Jun 2011 15:49:30 -0700

> We can make it clearer with regard to session cookies, but overall, the mechanism is just a cleanup of the OAuth 1.0 MAC functionality.

I might be helpful to have a clear example flow of how to use this
mechanism in a normal session-cookie set up.  I think that would
address some of the questions we've been getting.

Adam