42

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.

MetaGuru
  • 42,847
  • 67
  • 188
  • 294

5 Answers5

38

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.

Eran Hammer
  • 7,036
  • 3
  • 31
  • 23
  • So then I just clear the Nonce table every 6 hours, always ensure that a Nonce is only used one time and also that an incoming timestamp is greater than or equal to the last successful request timestamp ever used. Is that right? That way if they try to re-use a Nonce it will fail, but if they wait 6 hours and attempt to use the request it will STILL fail because the timestamp will be older than the last request made? Then again if the request never made it through, then it COULD be used again... so I don't see how this is going to stop a replay attack. – MetaGuru Jul 29 '11 at 20:35
  • 4
    You need to keep a rolling queue, not empty it every 6 hours. What you do is keep a list of all the nonce values for every given client identifier, and evict values from the queue when their timestamp is greater than your window (say, 15 minutes). If a request comes with a timestamp older than your window, you reject it outright, otherwise, you lookup the timestamp+nonce in the queue and if not found, serve the protected resource. – Eran Hammer Jul 31 '11 at 02:32
  • I wonder where I would store this queue or if it would be just 'built in' to the query I use to pull back from the nonce table? What do you mean for every given client identifier? I currently store Nonces with an AccountID, but how do I distinguish from a Nonce that is 'in the queue' and one that is just 'in the table'? – MetaGuru Aug 03 '11 at 21:34
  • Thanks, but I cannot compare it to MY system clock right? If the servers are not synced then there would be false failures. I should only be comparing the incoming timestamps to previous request timestamps? – MetaGuru Aug 08 '11 at 14:45
  • 1
    You compare it to your timestamp and should allow up to 15 minutes clock skew. If the client's clock is more than 15 minutes off (GMT of course), you should return an error telling the client to sync. If your developers write desktop or browser-based apps, they should use a time service for the app timestamp needs and not the local clock. Also, if you don't need replay protection, you can ignore the nonce altogether. Today, Twitter checks the nonce while Yahoo and Google do no. – Eran Hammer Aug 08 '11 at 16:11
  • 2
    @eran-hammer If we insist that each subsequent timestamp has to be greater than the previous timestamp for that user, would we still need a nonce? – tofutim Mar 20 '15 at 20:38
9

OK, after enough pondering I believe I have cracked this one.

They want me to always know the timestamp of the last successful request that was made so that if any timestamp comes in prior to that it will be ignored.

Also the Nonce must be unique, but I am only going to store them up to a certain date range, therefore if the timestamp is so many hours old the Nonce will be dropped and can then be used again, however because the last used timestamp is also stored, they cannot re-use an old request even if the Nonce is considered unique because the timestamp on that request would be outdated.

However this only works because of the signature. If they changed the timestamp or the Nonce on a request the signature would no longer match the request and would be denied (as the timestamp and Nonce are both a part of the signature creation and they do not have the signing key).

Phew!

MetaGuru
  • 42,847
  • 67
  • 188
  • 294
0

If OAuth used just the timstamp, it'd be relatively easy for an attacker to guess what the next timestamp would be, and inject their own request into the process. They'd just have to do "previous timestamp + 1".

By using the nonce, which is generated in a cryptographically secure manner (hopefully), the attacker can't simply inject TS+1, because they won't have the proper nonce to authenticate themselves.

Think of it as a secure door lock that requires both a keycard and a pin code. You can steal the keycard, but still can't get through the door because you don't know the pin.

Marc B
  • 356,200
  • 43
  • 426
  • 500
  • 1
    You've missed the question. I understand the nonce, but if the nonce can only be used once, I don't see the added value of the timestamp. – MetaGuru Jul 28 '11 at 21:49
  • Maybe a packet got lost. There may be more than one nonce "in flight" at a time. The timestamp is there to guarantee the ordering of things. – Marc B Jul 28 '11 at 21:51
  • once a nonce has been consumed it cannot be used again, and they are unique – MetaGuru Jul 29 '11 at 13:00
0

Can't comment yet, so posting as an answer. Reply to @tofutim's comment

Why use nonces?

Indeed, if we insist the the timestamp value of the new request has to be greater than the timestamps of all the previous requests, there seems to be little point in nonce:

  • Replay attack is prevented, since the provider would reject the message with timestamp equal to the previous one

  • Yes, the next timestamp is easy to guess for an attacker - just use timestamp + 1 - but the attacker still has no way to tamper the timestamp parameter, since all parameters are signed using consumer's secret (and token secret)

However, reading the OAuth 1.0a spec reveals that

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.

The Consumer SHALL then generate a Nonce value that is unique for all requests with that timestamp

So nonces are used to prevent replay attack when you send multiple requests with the same timestamp.

Why allow to send requests with the same timestamp?

Consider the case when you want to send multiple requests to independent resources in parallel, to finish the processing faster. Conceptually, the server handles each request one-by-one. You don't know in which orders the requests will arrive, since it depends on many things such as OS, network the packages will travel, the server logic and so on

If you send requests with increasing timestamp, there's still a possibility that the request with hire timestamp will be handled first, and then all requests with lower timestamp will fail. Instead, you can send request with equal timestamps and different nonces

Azerum
  • 73
  • 1
  • 2
  • 5
-1

It is reasonable to assume one could attempt to crack the nonce with brute force. A timestamp reduces the chance someone might succeed.

Denilson
  • 104
  • 5