I'm trying to wrap my head around restful API design on a bigger scale than one simple installation.
My setup would look something like his:
The question is, after a user has been authorized to do requests they get the access token. Should EVERY following request first go to the proxy, then to the auth server to check the token and finally get the data from the resource server?
Considering you need somewhere to store the users permissions/roles on what URIs he is allowed to use.
I was thinking if you move the tokens and the permission/roles to the rest proxy. Stored in a memory cache like Redis? And when a permission/role is updated on the auth server, it pushes those changes to the proxy. The proxy would not need to make additional calls to the auth server every single time reducing it to just 1 call to the resource server. Or maybe this is how everyone does it, two internal calls every request?
It is not a great idea to authenticate the token on every request. Instead , save the token in some fashion either in Redis or in a map on your resource server whose expiry time can be set in synch with the token expiry time.
Using Redis you can store these tokens along with the role against a single key say userId and set token's expiration time(by setting the expiry time of a key) .In this way once the token expires the calls will automatically be redirected to the authentication server on its own.
User roles and permissions should be saved on the resource server either as a separate set in Redis for maintaining permissions list to check against the user role which you will pick from Redis again (or depending on how you rest API facilitates setting permissions on resources as certain Rest API facilitators have inbuilt APIs for restricting resources via annotations). This permission list can be updated as and when modified.
Related
I am trying to understand statelessness in restful APIs in the context of authentication. Here's the scenario:
The user logs in.
The server verifies the username and the password, and generates an opaque access token. It caches some information related to this token - for example, the expiration time, the userId, whether this token was explicitly invalidated before it expired, etc.
The token is sent to the client, and the client sends it with every future request.
List item
Fielding's dissertation defines statelessness as:
"...such that each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client."
In my example, the client is sending the token with every request, so the first condition is satisfied. However, my server has a context associated with this session that is stored in the sessions cache.
Does this make my application stateful?
If yes, then is it that true statelessness be achieved only if we are using JWTs? I am pondering upon this as JWTs are quite new, so how were architects building truly stateless services before they were invented?
That's right. If you you maintaining the session you are keeping the state in server which makes the application hard to scale. True stateless applications can be scaled out and any server should be able to handle the request.
JWT is popular way to avoid sessions and everything is encapsulated inside the token for any server to auth/Authorize the request and help us achieve stateless application, they come with their own challenges however OpenID connect is the new way for Auth/Authorization.
Before jwt to make application stateless we used to keep session in DB (or Shared Cache) , and any server would like to check the session would have to contact DB.
Hope that Helps!
Briefly: No, such usage of token does not make your application stateful.
Detailed: When we talk about stateless/stateful, we consider usually only the data that affect business logic. Business logic does not usually depend on authentication data. For example, a user sends a request that contains all data needed to place some order. Normally creating an order does not depend on when this user has logged in, on his user ID, etc.
I am using play framework to develop a web app. Now I need to implement authentication/authorisation without database (really strange requirement). There will only be log in and log out function, no registration. The username/password pair will be authenticated using external service.
Due to limited experience, my current idea is to use token to authenticate and a local file to store username/password.
Is my idea feasible? Is there any recommended libs? If I use token, do I need to pass that token in Http request/response every time and authenticate the token in every controller?
Thanks!
Why store user name and passwords in a local file? I don't see the point and this constitutes a database, which you want to avoid it seems... Deciding to work with local files will be an important limitation if you ever want to deploy more than one server and have some load-balancing done.
Playframework is stateless, meaning that the server doesn't keep session state. To work around that play uses signed session cookies (the browser is storing the session data, and cannot modify it as the session data is signed).
Here's what you can do:
on login: set some data in the session
on each subsequent request, determine the state (logged-in or not) based on the session cookie, see https://www.playframework.com/documentation/2.6.x/ScalaActionsComposition#Authentication
on logout: reset the session cookie
Now this approach has a serious downside, it allows people to replay (reuse) old session cookies to pretend being logged. Another (could be less serious depending on your requirements) is that it is not straightforward to implement session expiration after a certain inactivity.
This is probably enough to answer your question and give you a starting point.
I have some general/how-does-it-work-inside questions about WebAPI and OWIN (specifically, the default configuration which is set up when you create new WebAPI project in VS2013 and select Individual user account authentication). I did that, then I registered (using jQuery post) and even logged in (received token which I included in Authorization header, receiving access to protected resource. I just have some more questions about it:
Are my data stored inside authentication token? I know my password isn't, but is token containing encrypted data, or is just a random string? These are the only 2 options that I can think of: either token contains encrypted data (userId, expiration date, etc.) and server app deciphers it and grants me access to resources, or token is a random string and all user data are stored on server (token is used as a key to obtain correct user data entry). If the second theory is right, the token <-> userData lookup must be stored somewhere - is it session, cache or database maybe?
If i wanted to make a RESTful API, what about Roles, etc. (in general - data beyond simple who-are-you identification that I need for every request)? Again: first thing that comes to mind is to store them inside token. But if the data grows large isn't that too much overhead to send with each request (plus headers themselves probably are limited in size)? Second thing is using external OAuth service (like Facebook or Twitter) - if the user authenticates using external token, I can't control what information does it contain. Alternative is to get the data I need from the database each time, but isn't it bad practice? Every single request would need an extra database call to collect user's role and check if he even has access to this particular part of application. I could store it in session, but RESTful API is supposed to be stateless.
Thanks for any help as I'm just starting to dig into OAuth and WebAPI authentication. I know that I can customize everything to work as I want (so use session to store user data, etc.), but I wanted to know what the good practices are and which of them are provided out of the box with default WebAPI project in VS2013 and which need to be implemented manually.
(1) the latter is correct. The server verify token by machine key and can decipher and validate its contents.
(2) You got that correct. Its best to keep the token size min. tbh I am looking to see what others are doing about this. (+1 for the question.)
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.
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.
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.
You can store token in Redis. If you are going to store it in DB, make sure you optimise server (if you are managing it) for read operations. I have couple of implementation where folks have used key value store as well. Hashtable is also good idea.
I have built a simple test API for a CakePHP application that will let a user login from a mobile device (or any device for that matter) and get a JSON response. This API could be used for a mobile app built in PhoneGap.
The login method looks like so:
public function login()
{
if($this->request->is('post'))
{
// Use custom method in Model to find record with password params
$findUser = $this->User->findUser(
$_POST['username_or_email'],
AuthComponent::password($_POST['password'])
);
// If a user exists and matches params
if($findUser)
{
$this->User->id = $findUser['User']['id'];
$this->autoRender = false;
$this->response->type('json');
$this->response->body(json_encode(array('authenticated'=>true,'message'=>__('You have been logged in successfully'))));
}
else
{
$this->autoRender = false;
$this->response->type('json');
$this->response->body(json_encode(array('authenticated'=>false,'message'=>__('Username or password is incorrect'))));
}
}
else
{
$this->autoRender = false;
$this->response->type('json');
$this->response->body(json_encode(array('message'=>'GET request not allowed!')));
}
}
The mobile device (or any API user) can send their login details and then they get the request as JSON as true or false for authenticated. This boolean is NOT used to give the user access, it instead tells the mobile app if they can see certain screens and they ONLY get the data or can send data if the session exists!
As just stated, they are also actually logged into the API itself on the device so if they visit the website directly (from that device) they will have a session and see the same response for the JSON.
So essentially a user remains logged in for the duration of the session on the device they communicated with the server on. This is different to a token which would need to be passed for every request, where as in this example they have a session.
Now the questions...
Is it bad practice for the user to be 'actually' logged into the API
with a session like shown above? It seems like the most secure way to handle authentication for a device as it's using the same logic as the direct web root.
I've seen some APIs use access tokens instead which I've also
implemented (user gets their token returned instead of the boolean
and no session is created). But from what I can tell, this seems
like more work as then I need to check for the access token against
a user record every time a request is made.
edit
For the sake of clarity, I am not a supporter of REST, I AM a supporter of RESTful/RESTlike services. If you look at all of the API's on the internet, very few actually stick to one standard. Whatever scheme you choose will depend on your specific problem-space. Just try to be secure and use intuitive design choices (ie dont name a service "cats" if it returns info about "dogs")
end edit
It is good practice in RESTful API's to manage some form of session/tokenizing scheme. Really the ideal (at least in my opinion, there are many schools of thought on this problem) setup involves rolling tokens.
If you are at all concerned with the security of your API, then permissions should be managed out of your database layer. Yes, this creates a bottleneck, BUT THAT IS ACTUALLY A GOOD THING. Needing to hit the database every single time to validate a client's token adds an extra step in the entire process. This slows down the API, which is actually desireable in a secure system. You don't want a malicious individual to be able to hit your API 3000 times a second, you want their requests to hang for a (somewhat) sizeable fraction of a second.
This is similar to MD5 hashing algorithms. Many of them recalculate the hash a few hundred times, with random pauses in between. This helps to keep a malicious client from attempting to brute force a password (by making it take more time to test each variation of the password string). The same applies to your API.
The other benefit, is that if you DO have a malicious user trying to log in over and over again, if you are managing them from the database layer, then you can red flag their IP Address/username/what-have-you and just drop their requests at step 1.
Anyway, for a suggested process (with rolling tokens, you can cut out parts of this if it seems overkill, but this is hella secure):
User hits a 'login' service, this requires a username/password, and returns two tokens, a Private Access Token and a Public Request Token (the server stores these tokens in the db).
The client stores these Tokens in a secure place
User accesses another endpoint to push/pull some data
Request includes a timestamp
Request includes the Public Request Token
Request includes an Access Token=> This token should be a MD5 hash of the string resulting from concatenating the timestamp string to the end of the Private Access Token string
The server takes the Public Request Token, uses that to lookup the Private Access Token that was stored
The server takes that Private Access Token, and concatenates on the Timestamp String, it then takes the MD5 of this string
If the new Access Token matches the one that the client sent the server, HURRAY, this client is validated, so push/pull the data
(Optional) The server generates new tokens on every request, and returns them to the client. This way every transaction invalidates the old tokens, and if there was some kind of man-in-the-middle attack occurring, if the VALID user has already completed their request, the malicious user now has invalid tokens and can't start messing with your API. This scheme tries to ensure that a malicious user can not expect to intercept a single communication between the server and the client, and still gain access to the system. If they do, then the REAL user should immediately get invalidated tokens. Which should then trigger their API client to hit the 'login' service AGAIN, getting new valid tokens. This once again kicks the malicious user out of the system.
This scheme is not 100% secure, no user access system ever will be. It can be made more secure by adding expiration dates on tokens. This scheme also has the added benefit that you can assign specific permissions to users/tokens (ie Read-Only access, only certain End-Points can be seen, etc)
This is not the only way you can do things, I would look up other Authentication Schemes and take what you want from each of them (OAUTH is a good place to start, then I'd look at Facebook/Twitter/Instagram)
Make your app login everytime, but not with login-pass pair as Swayok lastly suggested. When you login, server generates a token and returns it back to the client. Client then uses this token whenever it makes a request. On each request, server checks whether the token is valid and if so, executes the request.
This is very similar to how sessions work in that, server side frameworks manage it internally and these tokens expire from time to time. However, as Swayok rightuflly pointed out, you don't want session mainly because you're RESTful API should have no state. You get the same utility without storing any user specific data regarding user and logging user in with every request.
Here's a good article on this, or you can try the Facebook Graph API explorer to see it in action
Restful API restricts using sessions and saving system state at all. Each request must log-in user.
Access tokes are great but also require additional handling.
The easiest way is to send authorisation data via HTTP Basic Auth ("Authorization" HTTP header)
http://www.httpwatch.com/httpgallery/authentication/
Mobile Applications can easily do that and it is easy to add this header for each request to API.
On server side:
$username = env('PHP_AUTH_USER');
$password = env('PHP_AUTH_PW');
And process user log-in with this data in ApiAppController->beforeFilter()
To answer your questions
Its not a bad practice as long as you close their session on app close and recreate it when needed. it is same as if they were logged in on a browser they would know and have facility to log out however the same should be available on the app as well otherwise they might have closed the app but not actually ended their session. You can handle this in many ways by asking them to log out automatic checking when they close app
Tokens are an enhanced way of doing the above however you have to consider how secure the token is when transmitted and server need to verify the token on each request. You have said that it seems like more work so yes its more work and if you have time or money constrains and looking for an answer to say if the session style would harm your application in future it wont as long as you are in control of session and not leaving user without ending the session. If you have time then implement tokens and you would like that.