1

In my application,while registering the users i am saving username,password and jwt generated token with these fields in MONGO DB.When user tries to login with correct credentials then i will send the response with stored token.Then at client side(In my controller) i am using the localstorage to store the token so that i can send the same token for each and every request sent by the client.But I found some issues regarding this procedure:

  1. I am generating same token for one user every time.So if any third person is able to get the token then he can access the restricted page.
  2. Am i wasting space in db by storing the generated token in MONGODB
  3. Can Anyone access the token stored in localstorage other than the user.
  4. for each and every request in my single page application,I am again querying mongodb to get the token for that user and validating.Here,I am checking both client side and server side.

I am using jwt to generate tokens,Node,Express,Mongoose in my application

Am i following the good procedure.If not,can you please provide the solution for my approach or any new approach. I have searched many sites for token based authorization and session based authorization,But nothing worked for me. Note:I am beginner for Nodejs,AngularjS

HARSHA LANKA
  • 135
  • 1
  • 2
  • 13

3 Answers3

1

You should store token in advanced key-value cache tool like: Redis That would improve performance remarkably.

You will get token from database for 1st time then it should be stored in Redis. I used to set token as key and username as value. Next request , the token will be given from cache. with Redis you can set expire for token.

Maher Abuthraa
  • 17,493
  • 11
  • 81
  • 103
  • Storing token in database is good thing or bad thing?? Can i do the same thing with out storing token in database? i.e. When user logs in with correct credentials,I will generate a token with JWT.Sign("with some secret key") and store it in some where for server side access(Don't know where i can store this??can you please brief me) and i will send the response with generated token,So that at client side(In my controller) i can store the token in $rootScope(storing in local storage is not a good thing if am not wrong).For every request,i will check tokens at both side! Am i doing in right way! – HARSHA LANKA Jun 08 '15 at 18:28
  • can i set the expiry time for a token when page is idle for 15 sec's through Redis?Such that i will reset the tokens at client side and server side when user is in idle state for 15 seconds which again shows the login page. @Maher Abuthraa – HARSHA LANKA Jun 08 '15 at 18:45
  • Here is a working version of restify+mongoose+redis : https://github.com/rgallagher27/node-restify-oauth2-mongodb+oAuth2.0,try to see how to use Redis in that project. what you need really to understand is how oAuth2.0 is working. for me using database is good if expiry is long-term and if you don't need user to insert credentials frequently...many mobiles apps use this way. OR as in your case you can keep token in cache only because the idle time is only 15 sec. with Redist you can do that easily and quickly. – Maher Abuthraa Jun 08 '15 at 19:31
0

You do not want to store the JWT in mongoose because it appears in headers when logging in. You first generate a token then hash it using a module like crypto.

There are different ways to do this and they all use Passport which handles the tokens. Here's an example project Satellizer

I would recommend you generate the angular-fullstack project. Then go through the server/auth folder and the client/account folder. You will see how to securely handle authentication in a MEAN based app.

venturz909
  • 330
  • 2
  • 12
0

When a user registers, you would need to generate a JWT like you're doing now. That's OK. You don't need to save it to the database however. You didn't ask but I assume that the password should not be stored in clear text. You can use something bcrypt to encrypt before saving it to the database.

When user tries to login with correct credentials then i will send the response with stored token

Yes, that's correct way to do.

Then at client side(In my controller) i am using the localstorage to store the token so that i can send the same token for each and every request sent by the client.

Yes, on the client side, you can save the JWT to local storage and send it in subsequent requests to the server.

Now your bullet points:

  1. So that you won't have the same JWT each time, you can include an "exp" claim in the payload (I'm assuming you're using something like jwt-simple to generate a JWT). Something like:

    var payload = { sub: account.username, exp: moment().add(10, 'days').unix() }; var token = jwt.encode(payload, "secret");

  2. You don't need to store the JWTs in the database. In some cases, the token issuers (the authorization servers) are not the same as the resource servers. The resource servers only receives the JWTs in a request but there's no way for the resource servers to touch the database used by the authorization servers. Side note: If you eventually need to support refresh tokens, i.e. the JWTs that you hand to the clients will need to eventually expire, then you can store the refresh token in a database. Refresh tokens are not the same as JWTs (access tokens). The complexity to support refresh tokens will increase.

  3. Local storage is not where you store passwords, but it can be used to store JWTs. For that very reason, a JWT must and should expire after a certain time.

  4. Not sure what you mean by saying you check both client side and server side. When the client needs to access a resource (again it's fair to assume that the resource server might not be the same as the authorization server), the only thing that the resource server is passed is the JWT. Anyone can decode a JWT. For example, try to paste your JWT on this site http://jwt.io/. That's why a JWT should not contain any sensitive data. But if the resource server knows the secret that the authorization server uses when it encode the JWT, the resource server can verify the signature. Back to your third bullet, that's why it's OK to store the JWT in local storage of the client.

Update I'm updating this to answer to some of your questions in the comment box.

User clicks on 'Login' button triggers the Angular controller to post a request to the server, something like:

$http.post(url, {
    username: $scope.username,
    password: $scope.password
}).success(function(res) { ... })

Server receives the POST request, it checks username/password, then it generates a JWT, and sends back to the browser. Note that it does not have to save the JWT to the database. The code would be something like

var payload = {
    sub: account.username,
    exp: moment().add(10, 'days').unix()
};
var token = jwt.encode(payload, "secret");
res.status(200).json({      
  token: token
});

Back on the client side, in the success() callback above, now you can save the JWT in local storage:

.success(function(res) { $window.localStorage.setItem('accessJWT', res.token) })

The user is now authenticated. Now when user wants to access a protected resource, user don't have to provide username/password. With the JWT which can be retrieved from local storage, the client can now put the JWT in the Authorization header of the request using the bearer scheme, and sends the request to the server. In code, it would like:

headers.Authorization = 'Bearer ' + token;

The server receives the request. Again, this server receiving this request does not have to be the same as the server which generates the JWT above. The 2 servers can be in 2 different continents. Even if you save the JWT above, that does not do any good to this server which can not access the database where the JWT is stored. But this server can pull out the bearer token from the header of the request, validates the token and carries on with the normal tasks.

Hope this helps.

Kevin Le - Khnle
  • 10,579
  • 11
  • 54
  • 80
  • Without storing the token in database,How can i manipulate my token at server side every time user logs in. I think i can store the token in $rootscope,instead of local storage?if i am not wrong! or Should i need to go for sessions?? And also how can i generate token each time differently for a particular user?? – HARSHA LANKA Jun 08 '15 at 18:20
  • No, session is a never necessary with JWT which aims to work in mobiles devices. As I said, to get a different token, add an expire claim which is based on time. Time will be different each time when you generate a token, so the claim will be different, so the payload will be different, so the token will be different. Again you don't need to store the token. When user logs in, you check for valid credential. If valid, issue a token. When user wants to access a resource, a token is passed in the request header, the resource server can then validate the token. – Kevin Le - Khnle Jun 09 '15 at 13:36
  • Everything is fine,but how can i get the generated token for every request at serverside(in server.js),becoz i am not storing token which i was generated using jwt in my mongodb? – HARSHA LANKA Jun 10 '15 at 15:45