CSRF token exchange from server to AngularJS client - java

I'm going crazy trying to figure out how to implement a CSRF protection for my Web app. I've read tons of pages but still cannot decide on the solution in my particular context.
So, first my Web app is written in Angular, deployed statically on an Apache server. It calls some services on my server, Java type, deployed in a war on an application server. Both of them are deployed on the same domain. After authentication the usual session cookie (secure+HttpOnly) is set in the response.
Now, I would like to implement a CSRF protection based on either a synchronizer token or a double submit cookie pattern (but from what I saw the first is a better solution as I can handle a state on server side).
Most of the solutions I saw are proposing to generate the token server side and to store it in a cookie so it can be accessed on client side. The constraint for this to work, and I would that it is a big one, is that the cookie cannot be HttpOnly, as Javascript would not be able to access it. Moreover I have the feeling that sharing the token in a non fully protected cookie wouldn't be a good idea. But it seems to be the recommended solution from AngularJS ...
So, if I discard this solution what am I left with?
Putting the token not in a cookie but rather in the response header? Is it secure?
Exposing a service to fetch the token? Seems practical but not sure if it is a good idea?
Expose a servlet to build a Javascript to provide the token, like in OWASP Guard?
Anything else?
EDIT: It seems that Spring is going for the injection of the token name and value in the HTTP response as a solution.
Thanks for your help!

CSRF token should generated once per user session.
It should be stored in server side session (HttpSession in case of Java)
Client should store the token as a hidden parameter not in the browser's cookie.
Server should validate the presence of the CSRF token for each request and compare with the token stored in session.
More details : https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

Related

Securing REST api with Token

I have been struggling with this the last couple of days and haven't found a reliable, understandable solution on the web.
I have a web app that is comprised of a rest api and a presentation layer consuming it. Presentation layer has a login form, the data introduced by the user is sent to the REST api which then uses a third party service to authenticate the user. This part I have already set up.
What I want now is to inrtoduce a token-based authentication for every subsequent request so I don't have to send credentials on every request and then authenticate again against the third party service.
So basically, using Spring Security (v. 3.1.3), I am lost as to how to create a reliable, secure token, return it to the requester, then authenticate request based on said token.
Can you point me to the right direction? Or to some example online?
How do you generate the token? How do you return the token to the
client?
How would you send the token in subsequent requests?
How do you set the whole thing up so the first time you can
somehow send the credentials (user/pass) then the subsequent
requests send only the token?
How do you authenticate against the token?
I've seen implementations where token includes some expiryTime. So what happnes after expiryTime is exhausted? The user must login again, even if he's been making requests the whole time? Should I renew the token "behind the scenes"?
Is the server-side REST application stateful or stateless? If stateful, you won't need to do anything special using a regular HTTP Session. Just start using Spring Security and if the client and server are already exchanging session information, your protected API endpoints will work out of the box. The only caveat is if you have CSRF protection enabled, in which case you will need to tweak the client a little bit. Details for this are in the Spring Security documentation.
On the other hand, if the REST application is stateless, you will have to use a token-based approach like you have proposed. See my answer to a similar post for details. If you do choose to follow the steps in that answer, answers to your questions are:
The token has to be generated on the server-side. If you go through the sample code linked to my answer, you will see that I have replaced the default HTTP-session-dependent infrastructure of Spring Security with a cache-based infrastructure. In the session-based implementation, the unique conversation identifier, which is the session ID, is generated by the servlet container, whereas in the custom implementation, the identifier, which is the token, is generated within the application. Specifically, I have used a SecureRandom instance to generate strong tokens.
The token is sent back by the client as an HTTP header. This protects the content over an SSL channel.
The trick is to implement four very simple interfaces from Spring Security. My sample app has full details. The whole process took me less than an hour.
Authentication against the token is done automatically by Spring Security. We simply need to provide an implementation for storing and retrieving tokens, which is straightforward and takes only a few lines of code.
In my sample app I have used an expirable cache with sliding expiration for storing the tokens. If a client keeps sending requests periodically, the server keeps on accessing the cache for the authentication token, thereby keeping the token alive in the cache. Tokens are evicted from the cache only after a period of inactivity equaling or exceeding the cache expiration period.
So overall, a token-based authentication/authorization approach can be easily implemented with Spring Security and leveraging a caching library like EHCACHE.

How to force authentication challenging for every request in REST?

My understanding is that a RESTful service should be totally stateless. Every time I invoke the service, I must pass all the information it needs to operate properly.
However, when it comes to authentication I get rather confused about how this should work, particularly in terms of session management.
I am using basic authentication and the first time I make a request, the client gets challenged (or I can pass the authentication information in the header from the beginning). But once the user has been authenticated, the server will not challenge this client anymore as long as the session is alive.
This means that I need to provide some mechanism for the current user to logout (terminate his/her session).
It would look like the right way of doing this would be to change my configuration somehow so that every request is challenged for authentication, but I have no clue how this plays with session management.
Am I supposed to invalidate the session manually after every request?
Or is there way to force the clients to be challenged every time a request is made?
You can find lots of questions out there about security with REST, and even books about how to implement different models of authentication. But I have not found a good answer on how to deal with session management, logging in and out. So either I am doing something wrong or I am misunderstanding something important here.
I would appreciate any thoughts or guidance on how this should be properly handled.
I am using Jersey 2.4 with Tomcat 7.
If you're authenticating with HTTP Basic, the client is challenged the first time only because the Authorization header isn't being sent from the client. Once it's sent and the server sends something other than a 401, the client caches those credentials and re-sends them with every request.
You shouldn't create sessions in a stateless app, not only because they aren't used, but because they require overhead to manage (even empty ones). The servlet architecture, however, cannot prevent code from creating sessions, such as when the code calls either httpServletRequest.getSession() or httpServletRequest.getSession(true). So you need to ensure that you don't use any code (or frameworks) that do this.
Interestingly enough, Tomcat will still generate a JSESSIONID cookie for the client to use, and under most configurations of the container, you can't turn this off. However, if sessions aren't created, the cookie is essentially ignored (and a new JSESSIONID cookie will be generated on every request).
And, because the app is stateless, there is no concept of login or logout. All authentication is done per request.
Note that, depending on your particular app, pragmatism may trump pure RESTfulness. There are cases where "a little bit" of server state is really the only way to provide some types of security to the app (such as cross-site request forgery, anything with nonces, etc.)
If you are doing a RESTful webservice you shouldn't handle sessions.
The first time you connect to the API you need to pass the authentication check in order to obtain an authentication key.
This key is how your API will identify its users.
You shouldn't invalidate the session and you shouldn't force your users to re-authenticate.

Spring Security OAuth2 cookies

I have OAuth2 implemented in my app with Spring Security. Currently, it works with the "access_token" request parameter. Where can I add some customization to also accept the token from a cookie?
You cannot get the token from a Cookie - using oAuth, the only way to get it is via a call to the oAuth server, getting a code, and then getting the token...
You can read the oAuth spec.
If you talk about the application-end (and not the oAuth), it might be possible.
Checking the token is the responsibility of the application that holds the protexcted resource. There, rather than getting the token from the header of the request, it can check a Cookie instead.

Java REST service using authentication token

On my web app using Java EE 6. I want to expose some of my functionality as a Json Rest Service. I want to use authentication tokens for login, User will send their username, password and server will send back a token, which will be used to authorize the user on their further requests for a given time..
A few questions bothering me so far;
When the server creates the token and sends to client, should server save it in a DB OR in a Bean using something like a hashtable as userid-token pairs?
Can I get some help using any Java EE specific API or this has to be all custom code?
Heres my input:
I would save the token in DB, in case you need to restart the server you don't want to lose all your user's tokens. You could potentially save it in memory as well to speed up requests and only look it up in DB if it is not found in memory.
I would accept the token in the header. I would put the rest service on HTTPS so the request is encrypted and then you don't need to worry about encrypting the token manually in the request
I would probably look at JAX-RS and see what features it offers
I recently blogged on how to set up Role-based authorization in a JAX-RS REST API using both a simple session token approach and a more secure method of signing requests using the session token as a shared secret.
It boils down to:
Get a session token from the server along with some identifier for the user
Use the token to encrypt the information in the request
Also use a timestamp and nonce value to prevent MITM attacks
Never pass the session token back and forth except for when retrieving it initially
Have an expiry policy on session tokens
Saving the token in a bean or hash table would not be persistent. A DB would persist between executions.
If you are going to be using REST then you can either pass the authentication in the parameters to the method, or in the request header itself. Encryption is a different matter. I guess it depends on the scale of the system, and how open it is. If security is a top importance, then yes, you should find some form of encryption.
I have done similar things using the Spring Framework, and Spring Security. These things are relatively simple using this. To write custom code is to reinvent the wheel. There are many frameworks out there which will help you. However, you would then have the learning curve of the framework.

Authentication in Apache Jersey without using Http-Authentication?

I am building a RESTful Webservice using Apache Jersey. Now I want that you need an authentication for some requests to it. Using the typical REST-approach the Authentication should be done via HTTP-Authentication. But a post here mentions that a better way how this can be done is by using cookies. I think there are some valid points in the discussion. (How) Can I make my Jersey Authentication work with Cookies? Do I need another framework for it?
Jersey uses the authentication mechanism declared in the enclosing web application's web.xml, practically either HTTP Authentication (over SSL) or Form-based Cookie authentication.
If you want to used cookie-based session authentication, users must authenticate with the web service first to create a session which can be used to check their identity for future calls. The servlet spec provides a standardized way to authenticate using cookies and session using a web form, which however, is not compatible to a web service type of application. So you would probably want to cook up some custom solution to let users submit their credentials via POSTing an XML or JSON document. A problem with this method is that if a user performs a call to a resource without first authenticating or after the session has expired, they will need to be redirected or receive some type of error code. Not impossible but it adds complexity to your web service.
At this point you have to wonder if using HTTP Auth is not the better choice for web service style apps. We recently built a web service using Jersey and HTTP Auth as the authentication mechanism. We then build a Javascript front end on top of it. The Javascript client always submits the Authentication headers to the web service so that the user is never confronted with the HTTP Auth authentication window from the browser. Perhaps the best of both worlds.

Categories