How should I store a token generated by a RESTful API?

10,204

Solution 1

Upon successful login, a unique, one-use token should be created server side and stored in the database against a user id and timestamp. You store the token in a cookie client-side. You then pass the token up to every subsequent API call. The server should then check the token is valid (ie not expired, say issued or update less then say 30 minutes ago). If it is valid, you can retrieve the user details stored against that token and perform whatever backend functionality you need (as the user is authenticated). You then update the timestamp for that token (refresh the session as you want the login to time out after say 30 minutes of no user interaction). If a token is expired or non-existent when you get the API call, redirect to the login page.

Also, you probably know this already, but make sure the token is unique and non-guessable, I tend to generate new random GUIDs and encrypt them, do not use sequentail ids or anything like that.

Solution 2

I think that this link could help you:

In fact, you should have a token with an expiration date, so you don't have to get a new token each time before sending a request. When the token expires, you simply need to get a new one from a service "refresh token".

Regarding the question about how to store the token in the client application, I think that you could keep it in memory (map or embedded database).

Otherwise to finish, I don't think that it's a good idea to use cookies in such use case.

Hope it will help you. Thierry

Solution 3

We're working on an application that uses a very similar approach. The client application is a static HTML5/JS single-page application (with no server-side generation whatsoever) and communicates with an API server.

The best approach is to store the session token in memory: that is, inside a variable in the JS code. If your client application is a single page, it shouldn't be a problem.
In addition to that, we also keep the session token in sessionStorage to preserve it in case the user refreshes the page. To preserve the token when new tabs are created (sessionStorage is specific to a browser window), we also store it in localStorage when the page is being closed, together with a counter for open tabs (when all tabs of the application are closed, we remove the token.

// Handle page reloads using sessionStorage
var sess = sessionStorage.getItem('session-token')
if(sess && sess !== 'null') { // Sometimes empty values are a string "null"
    localStorage.setItem('session-token', sess)
}

// Set a counter to check when all pages/tabs of the application are closed
var counter = parseInt(localStorage.getItem('session-counter') || 0, 10)
counter++
localStorage.setItem('session-counter', counter)

// Event fired when the page/tab is closing
window.onbeforeunload = function() {
    var counter = parseInt(localStorage.getItem('session-counter') || 0, 10)
    counter--
    localStorage.setItem('session-counter', counter)

    // All pages are closed: remove the session token
    if(counter <= 0) {
        // Handle page reloads using sessionStorage
        sessionStorage.setItem('session-token', localStorage.getItem('session-token'))

        localStorage.removeItem('session-token')
    }
}

For more information about localStorage and sessionStorage: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API

Why not cookies? Cookies are bad for two reasons: 1. They are generally more persistent, being shared across browser windows and tabs, and they can persist even after the browser is closed. 2. Most importantly, however, by the HTTP specifications they must be sent to the web server every time a request is made. If you're designing an application where the client is completely separated from the API server, you don't want the client's server to see (or log!) the session token in any case.

Some extra advices:

  1. Session tokens must expire. You can achieve that by storing session tokens in the database on the server and verifying them on every request and/or "signing" them (adding a timestamp to the token in plain text, then adding a signed part, for example a HMAC hash, with the timestamp encoded with a secret key you only know).
  2. Tokens can be reused as many times during their life. However, after a certain number of seconds you may want your server to refresh the tokens, invalidating the old one and sending a new token to the client.
Share:
10,204

Related videos on Youtube

IgorSousaPT
Author by

IgorSousaPT

Updated on September 19, 2022

Comments

  • IgorSousaPT
    IgorSousaPT over 1 year

    I have built an API that generates an authentication token for the users that log in. At this time I also have a client application written in Node.JS.
    When I make the request with the user credentials from the client application to the API I get the authentication token: how should I store it in the client application? I'm not supposed to request a token every time I want to make a request for the API, correct?
    I thought about putting the token in a Cookie, but I don't think that's the best solution. What would you recommend?

  • IgorSousaPT
    IgorSousaPT about 9 years
    Yeah, I know about the unique and non-guessable part, but thanks for pointing it out anyway. My question about the cookies method is, is it safe? Isn't it possible to steal the cookie value and access other users private information?
  • C. Ridley
    C. Ridley about 9 years
    Assuming you are using SSL, it would be difficult to intecerpt the value using a man-in-the-middle attack. Using a unique expiring token renders the token useless after use, so is relatively safe. You could also ip validate against the token assuming the user keeps the same ip for the duration of the session (likely). But yes, there could be malicious code on the client which uploads all cookie info to a 3rd site, but I'd say using cookies is safe enough for most web applications if implemented correctly. OR, you could look at OAuth, which is another headache, but widely used auth method.
  • IgorSousaPT
    IgorSousaPT about 9 years
    Actually, I am using OAuth2.0 to validate credentials and generate the tokens. But still I need to store the token on the client side. Unless, I'm getting this terribly wrong!
  • C. Ridley
    C. Ridley about 9 years
    The following question is similar to this one, the answer and comment are similar to mine and are stating that the risk is minimal using a cookie as long as the token is a throw-away one. stackoverflow.com/questions/1283594/… Most sites do this, you need to store the token somewhere. With client-side code that place is cookies.
  • ItalyPaleAle
    ItalyPaleAle about 9 years
    I'd advise against storing the token in a cookie, as that is transmitted to the server on any request. And I don't think session life should be updated: just let it expire and refresh it!