Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a secure token for api access

I need to generate a secure token for access to an api. User will auth and on successful auth I will need to generate a token.

Important: I do have a requirement that I need to be able to revoke a users access to the api at any time.

Option 1:

I can generate a random string and use that as the token. Store the token and the user in the db. When the user passes the token I check the DB for the token, if it exists go to go...

This gives me the ability to revoke access by removing a users token. If they tried to log back in and the token was gone they won't have access. I can also expire tokens from the DB based on time.

I am using nodejs and have seen this:

Secure random token in Node.js

require('crypto').randomBytes(48, function(ex, buf) {
  var token = buf.toString('hex');
});

Is that really secure in that someone could not guess a token that I have generated?

Option 2:

Use something like jwt. On auth generate a jwt with the users id. When the user passes that jwt on a request I make sure jwt is valid and if so grab user id and good to go. This seems a lot more secure as jwt prevents tampering.

Problem is revoking access to the api. I could store all jwts (until they expire) in the db, on request validated jwt and make sure its in my db. If I want to revoke I can just remove it from the db. Con here is that I now have the overhead of validating the jwt and looking it up to ensure its in my db.

Is there a good way to revoke access using jwt?

like image 689
lostintranslation Avatar asked Aug 22 '15 06:08

lostintranslation


1 Answers

This question will probably invoke a lot of opinion in the answers, so ultimately its up to you and your security requirements.

One solution I like is generating random characters in the same way you've suggested, and include with it something the user has (such as an email address or an ID). Then also include a timestamp to know when it was generated. Take those things and concat them together into a single string (perhaps using some character to split the parts up). So you'd end up with something like:

<random-string-of-characters>|<user-email-address>|<timestamp>

Now encrypt that string, perhaps using something like bcrypt, and that blob ends up being what you would call the "token". The internal users of this don't have to understand it, they just need to store it and later access it to send it to your security layer to validate. You validate it by unencrypting it and verifying the parts.

This solution gives you complete control on how you grant the user access. You can continue to store the generated characters in the database and revoke it at any time, or look at the timestamp to see if they are "timed out".

I suppose there are a lot of solutions to this, so this is just one :)

like image 86
dylants Avatar answered Oct 19 '22 15:10

dylants