What's the point of a timestamp in OAuth if a Nonce can only be used one time?

CloudMeta picture CloudMeta · Jul 28, 2011 · Viewed 23.2k times · Source

I had at first misinterpreted the timestamp implementation of OAuth into thinking that it meant a timestamp that was not within 30 seconds past the current time would be denied, it turned out this was wrong for a few reasons including the fact that we could not guarantee that each system clock was in sync enough down to the minutes and seconds regardless of time zone. Then I read it again to get more clarity:

"Unless otherwise specified by the Service Provider, the timestamp is expressed in the number of seconds since January 1, 1970 00:00:00 GMT. The timestamp value MUST be a positive integer and MUST be equal or greater than the timestamp used in previous requests."

source: http://oauth.net/core/1.0/#nonce

Meaning the timestamps are only compared in relation to previous requests from the same source, not in comparison to my server system clock.

Then I read a more detailed description here: http://hueniverse.com/2008/10/beginners-guide-to-oauth-part-iii-security-architecture/

(TL;DR? - skip to the bold parts below)

To prevent compromised requests from being used again (replayed), OAuth uses a nonce and timestamp. The term nonce means ‘number used once’ and is a unique and usually random string that is meant to uniquely identify each signed request. By having a unique identifier for each request, the Service Provider is able to prevent requests from being used more than once. This means the Consumer generates a unique string for each request sent to the Service Provider, and the Service Provider keeps track of all the nonces used to prevent them from being used a second time. Since the nonce value is included in the signature, it cannot be changed by an attacker without knowing the shared secret.

Using nonces can be very costly for Service Providers as they demand persistent storage of all nonce values received, ever. To make implementations easier, OAuth adds a timestamp value to each request which allows the Service Provider to only keep nonce values for a limited time. When a request comes in with a timestamp that is older than the retained time frame, it is rejected as the Service Provider no longer has nonces from that time period. It is safe to assume that a request sent after the allowed time limit is a replay attack. OAuth provides a general mechanism for implementing timestamps but leaves the actual implementation up to each Service Provider (an area many believe should be revisited by the specification). From a security standpoint, the real nonce is the combination of the timestamp value and nonce string. Only together they provide a perpetual unique value that can never be used again by an attacker.

The reason I am confused is if the Nonce is only used once, why would the Service Provider ever reject based on timestamp? "Service Provider no longer has nonces from that time period" is confusing to me and sounds as if a nonce can be re-used as long as it is within 30 seconds of the last time it was used.

So can anyone clear this up for me? What is the point of the timestamp if the nonce is a one time use and I am not comparing the timestamp against my own system clock (because that obviously would not be reliable). It makes sense that the timestamps will only be relative to each other, but with the unique nonce requirement it seems irrelevant.

Answer

Eran Hammer picture Eran Hammer · Jul 29, 2011

The timestamp is used for allowing the server to optimize their storage of nonces. Basically, consider the read nonce to be the combination of the timestamp and random string. But by having a separate timestamp component, the server can implement a time-based restriction using a short window (say, 15 minutes) and limit the amount of storage it needs. Without timestamps, the server will need infinite storage to keep every nonce ever used.

Let's say you decide to allow up to 15 minutes time difference between your clock and the client's and are keeping track of the nonce values in a database table. The unique key for the table is going to be a combination of 'client identifier', 'access token', 'nonce', and 'timestamp'. When a new request comes in, check that the timestamp is within 15 minutes of your clock then lookup that combination in your table. If found, reject the call, otherwise add that to your table and return the requested resource. Every time you add a new nonce to the table, delete any record for that 'client identifier' and 'access token' combination with timestamp older than 15 minutes.