Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I have developed a backend REST API for a mobile app and I am now looking to implement token-based authentication for it to avoid having to prompt the user to login on every run of the app.

What I had in mind was on the initial request the user sends their credentials using Basic authentication over SSL. Once the server authenticates the credentials it creates a secure token and sends it back to the user so they can use it in subsequent requests until the token either expires or is revoked.

I am looking for some advice as to how I can generate a token which won't be susceptible to things like MoM/Replay attacks as well as ensuring the data stored within the token cannot be extracted out.

I am going to use the following approach to generate the token which I think would prevent any data from being extracted from it. However, I still need to make sure it's not vurnerable from other attacks.

The API will only be accessible over SSL but I am not sure if it's just enough to rely solely on this.

share|improve this question
    
What about OAuth? –  Mike Weller Sep 3 '12 at 15:21
    
@MikeWeller OAuth is probably the universal solution to this problem, however, time constraints & complexity of development is where it falls down. Also, OAuth is probably a little bit overkill as there are no plans to open the API up to 3rd parties at the moment. The sort of token-based system I want to implement isn't far off what OAuth does, it's more like Twitters version of XAuth whereby you skip the whole login request part. –  James Sep 3 '12 at 15:33
    
Be very careful with writing your own session management mechanism (which is essentially what you are proposing). There are dozens of common errors that inevitably occur in every new session management mechanism, which will affect yours, too. You should seriously consider how you can use an existing mechanism instead of rolling your own –  atk Sep 8 at 4:39

3 Answers 3

up vote 31 down vote accepted

The "authentication token" works by how the server remembers it.

A generic token is a random string; the server keeps in its database a mapping from emitted tokens to authenticated user names. Old tokens can be removed automatically in order to prevent the server's database from growing indefinitely. Such a token is good enough for security as long as an attacker cannot create a valid token with non-negligible probability, a "valid token" being "a token which is in the database of emitted tokens". It is sufficient that token values have length at least 16 bytes and are produced with a cryptographically strong PRNG (e.g. /dev/urandom, CryptGenRandom(), java.security.SecureRandom... depending on your platform).

It is possible to offload the storage requirement on the clients themselves. In the paragraph above, what "memory" should the server have of a token ? Namely the user name, and the date of production of the token. So, create your tokens like this:

  • Server has a secret key K (a sequence of, say, 128 bits, produced by a cryptographically secure PRNG).
  • A token contains the user name (U), the time of issuance (T), and a keyed integrity check computed over U and T (together), keyed with K (by default, use HMAC with SHA-256 or SHA-1).

Thanks to his knowledge of K, the server can verify that a given token, sent back by the user, is one of its owns or not; but the attacker cannot forge such tokens.

The answer you link to looks somewhat like that, except that it talks about encryption instead of MAC, and that's:

  1. confused;
  2. confusing;
  3. potentially insecure;

because encryption is not MAC.

share|improve this answer
1  
+1 This is more along the lines of the type of answer I am looking for, thanks. You mention that the proposed solution for generating tokens is potentially insecure and I understand why (if it's encrypted there is the possibility for it to be decrypted). However, it's encrypted using the machine key of the server (see here) so am I right in saying it's secure as long as my server is physically secure and no-one get's a hold of the decryption key? –  James Sep 3 '12 at 14:59
    
@James: what I mean is that the authentication token is secure as long as the attacker cannot build a fake one. Encryption does not protect against that. For instance, if using a stream cipher like RC4 (data is encryted by XORing with a key-generated pseudorandom stream), it would be trivial for a user to authenticate under his name, then fiddle with the bits to make a new valid token with another name of his choosing (as long as it has the same size as his name) (and I have seen that in a deployed banking system !). Really, if you need integrity, use a MAC. –  Thomas Pornin Sep 3 '12 at 15:06
    
Ah ok I see what you mean. So in terms of storage would you say it would be safe to store the token as it is generated or should that also be salted using a MAC? –  James Sep 3 '12 at 18:45
1  
Based on your comments here is what I am doing (server-side). Generating a secret key of 256 bits using a .NET RNG. Then generating a HMAC using SHA12 of the username + creation date of token (using the secret key). Then finally, generating a final HMAC of username + creation date + HMAC(username + creation date) again using secret key. Does that sound about right? I can post code if need be. –  James Sep 3 '12 at 20:41
2  
For the record, the standard ASP.NET functionality linked in the original question does involve a MAC. The method name, Encrypt(), is misleading. What it actually does includes both an an HMAC (with SHA256) and encryption (with AES). –  Erv Walter Sep 16 '12 at 22:18

In short, you should use a cryptographic strength one-time random token, and hash it in the database.

The token

  • must be allowed to be used only once,
  • must only be usable for the user it was created for,
  • must only be sent via HTTPS,
  • should have an expiry date (e.g. 7 days).

Once the user logs in with the token, it is invalid and a new token should be created and given to the user. In the case of an expired token, the user must be made to log in again, using their real credentials.

A more definitive and lengthy description of these rules can be found in part 2 of The Definitive Guide To Forms based Website Authentication:

Persistent Login Cookies ("remember me" functionality) are a danger zone; on the one hand, they are entirely as safe as conventional logins when users understand how to handle them; and on the other hand, they are an enormous security risk in the hands of most users, who use them on public computers, forget to log out, don't know what cookies are or how to delete them, etc.

[...]

Follow Charles Miller's 'Best Practices' article. Do not get tempted to follow the 'Improved' Best Practices linked at the end of his article. Sadly, the 'improvements' to the scheme are easily thwarted (all an attacker has to do when stealing the 'improved' cookie is remember to delete the old one. This will require the legitimate user to re-login, creating a new series identifier and leaving the stolen one valid).

And DO NOT STORE THE PERSISTENT LOGIN COOKIE (TOKEN) IN YOUR DATABASE, ONLY A HASH OF IT! The login token is Password Equivalent, so if an attacker got his hands on your database, he could use the tokens to log in to any account, just as if they were cleartext login-password combinations. Therefore, use strong salted hashing (bcrypt / phpass) when storing persistent login tokens.


Update: Sorry, I misunderstood the question. The method you linked looks reasonable, but it won't protect you from replay attacks or man-in-the-middle. You should use SSL alongside it.

share|improve this answer
1  
"cryptographic strength one-time random token" would you say the approach I linked to is secure enough for this? "Once the user logs in with the token, it is invalid and a new token should be created" Not quite sure if I understand how that would work. Are you saying tokens should be invalidated/re-issued on a per request basis? –  James Sep 3 '12 at 12:17
1  
@James When the user comes to the site and does not have a session, the cookie token is sent to the server. The server validates it, creates a new session as the logged in user, and invalidates the token. It then gives the user a new token. The session identifies them whilst they're using the site, but when they close their browser (or the session expires) the user is no longer logged in. When they come back, they have no session, and the new token you gave them allows you to create a new session (go back to step 1) –  Polynomial Sep 3 '12 at 12:21
    
@Polynomail There is no notion of a cookie, session or browser in my case. This is a REST API which is accessed via a mobile app. –  James Sep 3 '12 at 12:23
    
@James Sorry, misunderstood the question. The mechanism you linked is fine for this kind of situation, but it will not protect you against replay attacks. You need to use something like SSL to prevent MitM / replay. –  Polynomial Sep 3 '12 at 12:29
    
The API is running over HTTPS so is it safe to assume I wouldn't be vurnerable to those sort of attacks? I guess I am probably being overly paranoid, however, when it comes to security on the web I think it's a good thing to be like that! –  James Sep 3 '12 at 12:31

A pure RESTful API web service should use the underlying protocol standard features:

  1. For HTTP, the RESTful API should embrace and comply with existing HTTP standard headers, status codes and methods. Adding a new HTTP header violates the REST principles.

  2. RESTful services MUST be STATELESS. Any tricks, such as token based authentication that attempts to remember the state of previous REST requests on the server violates the REST principles.

Bottom-line: For authentication / authorization purposes, you should use HTTP authorization header. And you should add the specific HTTP authorization scheme header in each subsequent request that needs to be authenticated.

I have developed a RESTful web service for the Cisco Prime Performance Manager application. Search Google for the Cisco Prime Performance Manager REST API document that I wrote for that application for more details about RESTFul API compliance - see below. For this application, we have chosen to use the HTTP "Basic" Authorization scheme to authenticate and authorize requests. And obviously, we are using HTTPs to encrypt all the data in transit from the client to the server when using HTTP Authorization.

http://www.cisco.com/c/en/us/support/cloud-systems-management/prime-performance-manager/products-programming-reference-guides-list.html

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.