uglycode
uglycode

Reputation: 3082

Refreshing JWT in Express.js

I'm using JWT for authentication in my Angular.js application, with Express.js on the server side.

Basically, when user logs in, a new token is created (using https://github.com/auth0/node-jsonwebtoken) and send back to the client. If token is valid also on the client side (angular.js part, using https://github.com/auth0/angular-jwt), a new user is created and the token gets stored in a cookie.

So, each request to certain path on the server is protected by a token validation. However, my token has an expiration time. Now let's say for the sake of argument that expiration time is 30 seconds; user can actively use my application for 30 seconds and after that, he gets logged out. That's not exactly user friendly.

So what I did was that with each request to the server, I create a NEW token and send it back in the head of response. When I receive the response in my Angular.js client-side, I read the token and overwrite the token in the cookie. That way, as long as client is active (or rather, makes requests to the server side), the token gets refreshed.

Now I'd like to know the following:

  1. Is such an approach correct? The downside is, that token gets created at each request and send back in each head of response. Cookies get overwritten quite often (performance issues?)
  2. What would be the correct approach?
  3. Is it OK that the token expires if there are no requests to the server? Client might still be using the application, however, if he's only writing on client side something (or reading), the token does not get refreshed.

Thanks for your time and responses!

Upvotes: 3

Views: 905

Answers (2)

robertjd
robertjd

Reputation: 4903

The problem is also addressed by using refresh tokens. Your access token has a short life and is verified by signature. The refresh token has a longer life and is used to get new access tokens.

When the refresh token is used to get a new access token, that is a good time to do extra checks: has the refresh token been revoked? Is this user account still valid?

Both tokens can be stored in secure cookies and supplied on every request. Doing this allows your server to transparently use the refresh token when needed and set new access tokens in cookie responses.

This is the approach we've taken for Express-Stormpath and is documented in our Authentication section of the documentation. If you'd like to offload your authentication layer, I'd suggest Stormpath. (Disclaimer: I work there, and wrote that module).

Upvotes: 0

d.jamison
d.jamison

Reputation: 481

  1. Yes, that is a valid approach. It is the same approach many take, including the popular Angular module ng-token-auth. You might consider saving the tokens to local storage, with a fall back to cookie storage if the browser doesn't support it (see http://caniuse.com/#feat=namevalue-storage for coverage).

  2. I would do what you describe.

  3. One solution is to use $interval to basically ping the API. All you need to do is send in a token a get a new one back (i.e., in headers like you are now). Keep track of how many "pings" you've sent. You can reset the number of "pings" upon certain actions like on ui-router's $stateChangeSuccess (i.e., navigating to a new view) or anything you like, including submitting a form or other non-ping requests. When the number of "pings" reaches your threshold, warn the user that their session is expiring, and after a delay, erase the stored token and log them out. Check your ping responses for authentication errors from the API, indicating that the user might need to be logged out and/or redirected.

Perhaps you just gave 30 seconds as an example token lifespan. I would recommend getting closer to the browsing session timeout that you want. As points of reference, consider that the Ruby gem devise_token_auth defaults to 2 weeks and that .NET defaults to 10 hours. Your needs may vary.

Upvotes: 3

Related Questions