I'm implementing a set of RESTful services for some developments and one of these is an authentication service.
This authentication service authenticates two kinds of identities:
- Applications. AppKey-based authentication so clients must register for a key in order to access to the rest of the services.
- Users. Well-known credentials (user+password)-based user authentication so humans and machines can work with these RESTful services through client applications.
These RESTful services are stateless.
When a client application authenticates against the authentication service, or when a human or machine authenticates as an identity using credentials, both operations generates an AppToken and UserToken respectively.
These tokens are a salted hash so subsequent requests to the RESTful infrastructure will be authenticated without sharing AppKeys and credentials.
Form the point of view of a fully stateless approach, these tokens should be stored no where in the service layer but in some kind of client-side state (f.e., a Web client would store it using HTTP cookies). This is how my current implementations are working right now.
Because re-authenticating each request using these tokens and let the service layer receive the token coming from the client so it can compare what token comes from the client and check if it's a valid token re-generating it in the service layer and compare with the one owned by the client is too expensive, I've implemented a service layer AppToken and UserToken, both having an expiration date and an owner (the application or user for which the token have been created for), in order to check if the token coming from the client exists in the token store.
How does clients interactively unauthenticate? Just dropping client-side security state. If it's a Web client, it drops the authentication cookie and just refreshing the page, client detects no authentication cookie and user is redirected to the login page.
From the point of view of RESTful services, this is a stateless unauthentication: clients aren't aware about the trick of having a service layer pseudo-authentication state. It's just a service implementation detail - a performance optimization -.
I'm not going to list the pros of stateless services because I'm absolutely sure that this approach is the way to go, but I find a problem: stateless authentication/unauthentication means that clients don't notify server that they close their session, so the security store ends with a lot of useless records.
This isn't a great problem if service clients are ones that would have limited time sessions (f.e., 1 hour, 3 hours, a day...), but what happens if an user must be authenticated forever (8 months, a year)?. How do you distinguish what's an an expired token?
There're some approaches in order to solve this situation:
Whenever the service layer receives a request, it updates token expiration date, so an automated process may drop those tokens that have expired defining an arbitrary expiration of tokens (f.e. 24 hours).
Compromise stateless nature of the architecture and let clients notify service layer that they don't want to be authenticated anymore, so service can drop the associated token to the client session (But wait... what happens if client closes a Web client? User will never actively notify service that the token must be dropped... So... Zombie tokens are there yet, so an automated process should drop them, but... what's a zombie token? I don't like this approach).
Completely stateless authentication, no store, per-request authentication.
This is the question! What's your suggested approach - even if it's not 1., 2. or 3. - and why?
Thanks for this long reading - I honestly believe that question's conclusions are going to be extremely useful to anyone -!