Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to store authentication token in RESTful API

I have started to design a RESTful API and I'm thinking about how to handle authentication. I want to use some kind of authentication token but I can't use OAuth o similar infrastructures so I have to handle it myself.

One of the requirements for this API is that it must have good performance, enough to handle a high volume of requests before there is the need to scale; my concern is how to make on each request the time needed to verify the token (integrity, expiration, IP Address, etc...) as little as possibile.

I suppose the token should some kind of hash and not an encrypted string containing the user information because the decryption time would be to heavy.

I've read that I could store the tokens in an in-memory hashtable where the key is the token and the value is the user info needed to process the request, but how can I make this work in a clustered environment where there will be an hashtable on each "node"?

Should I put tokens on a DB table an hit the DB every time also Handling manually the retention of expired tickets?

Probably it's not that important for the question but I'm using Spring MVC for the RESTfull API.

Thanks in advance.

like image 579
Nicola Avatar asked Oct 16 '13 21:10

Nicola


2 Answers

I solved my problem by using both an in-memory cache and a db cache. Here is a summary of my solution that may help anyone with the same task.

  • the user logs in and in that moment a unique key is generated and sent back to the user.
  • that login token (which is basically a GUID with some processing) is also store in a db table with additional info like exipiration and with the user's info and roles. the same pieces of information are also store in memory (google guava hashtable where the token is the key)
  • the token must be passed along with every api call in the authorization token as @ipa suggested
  • the server code checks if the token is in its memory cache the user info are already available otherwise (e.g. the api call is done on another node in the cluster) the token is search in the token db
  • once the token is found you can check expiration, roles, etc...

This grants a good level of performance and security, the token can be generated with any arbitrary algorithm even a relative slow one since you don't have to recalculate it on every api call. Also this works with a stateless service wich can be scaled up horizontally.

like image 24
Nicola Avatar answered Oct 24 '22 21:10

Nicola


I assume you use https and therefore all the traffic is encrypted. I'd suggest one of the following principles.

Basic Authentication

You can add the credentials in the Authorization header of the request. This credentials are encoded with Base64 (see below). This credentials could be sent on every request and then checked with your DB. To get this faster and less IO intensive you can still use a cache. Once I implemented an API like this without a cache and was able to handle thousands of requests per second.

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Authorization Token

There are different ways to implement your idea with a token. A common one is that every API user has his own token usually called api key which never expires. Another one is that you first have to authorize (Basic Authentication) and then get a token back which expires. This one is then used as api key for a certain time.

Either way you have to decide whether to use a cache or not. I would keep it simple and go for basic authentication and check the db every time. Almost every framework has very good support for this approach because it's simple http. If this causes performance issues (I'd recommend performance tests anyway) try to add the table with your credentials to the JPA cache. If you want to implement something with expiring tokens have a look at Infinispan.

like image 89
ipa Avatar answered Oct 24 '22 23:10

ipa