Is storing CSRF token in cookie enough to prevent CSRF? - angularjs

In order to prevent CSRF, Spring Security and AngularJS uses a method to store the CSRF token in cookie. Then, for each request, the web client sends the same token as a cookie and HTTP header to the server for validation. These come from this blog. https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii#csrf-protection
However, I think that from the other side, the hacker can fake the cookie and HTTP header to send a fake request. Is this correct?

What I understood from ASP .net side of CSRF token for validating anti forgery token is, there will be two places where this token is stored.
1. In the page, which when request is made from angular, we will include this token in the request header.
2. In cookie, which will be automatically picked up by the request when triggered from browser.
In the server side, when the request is received, server will decrypt both the tokens and validates the request if both have a meaningful relation(this relationship is decided in the server with an algorithm) between them.
Now, here, an attacker couldn't figure out those 2 strings at any cost of time because the anti forgery validation algorithm is not disclosed and every time new strings are generated on the go.And second thing is I think attacker cannot directly include the cookie into the request because cookie is picked up from the browser. Their might be tools to do that. But unless the algorithm which is used is not disclosed, attacker could not accomplish a csrf attack.
I think this might be same for the Java spring side.

Related

React frontend and REST API, CSRF

Using React on the frontend with a RESTful API as backend and authorisation by a JSON Web Token (JWT), how do we handle sessions? For example after login, I get a JWT token from REST. If I save it to localStorage I am vulnerable to XSS, if I save it to cookies, same problems except I set cookies to HttpOnly, but React can't read HttpOnly Cookies (I need to read cookie to take JWT from it, and use this JWT with REST requests), also I didn't mention the Cross Site Request Forgery (CSRF) problem. If you're using REST as backend, you can't use CSRF Tokens.
As a result, React with REST seems like a bad solution and I need to rethink my architecture. Is it possible to offer your users a secure React application that handles all business logic on the REST API side without fear of losing their data?
Update:
As far as I understood, it is possible to do this:
React makes an AJAX call to the REST API
React gets a JWT token from the REST API
React writes HttpOnly cookie
Because React can't read HttpOnly cookies, we use it as-is in all our REST calls where we need authentication
The REST API calls to check the XMLHttpRequest header, which is some kind of CSRF protection
The REST API side checks for cookie, reads JWT from it and does stuff
I lack theoretical knowledge here. The logic looks pretty secure, but I still need an answer to my questions and approve of this "workflow".
React makes AJAX call to REST API
assured, lots of restful resource client lib available
React gets JWT token from REST
assured, this is what JWT should do
React writes httponly cookie
I don't think so, It should not work, but session is not such a important thing, it'll soon get out of date, and recheck password on key operations, even the hackers got it in a very short time, you can bind session token together with IP when user login and check it in your backend apis. If you want it most secured, just keep token in memory, and redo login when open new page or page refreshes
Because react can't read httponly cookie, we use it as-is in our all REST call where we need authentication
assured, check user and permissions through login token, like csrf you can put your login token into your request header, and check it in your backend apis.
Bind login token to your own restful lib will save you a lot codes
REST on calls checks XMLHttpRequest header, what is some kind of CSRF protection
REST side check for cookie, read JWT from it and do stuff
assured, as most people do.
Also, bind csrf token to your own restful lib will save you a lot codes
use user token in header https://www.npmjs.com/package/express-jwt-token
Authorization JWT < jwt token >
use csrf token in header https://github.com/expressjs/csurf
req.headers['csrf-token'] - the CSRF-Token HTTP request header.
restful client https://github.com/cujojs/rest
react with jwt https://github.com/joshgeller/react-redux-jwt-auth-example
Your server can set the JWT cookie directly as a response to the login request.
The server responds to POST /login with Set-Cookie: JWT=xxxxxx. That cookie is http only and therefore not vulnerable to XSS, and will be automatically included on all fetch requests from the client (as long as you use withCredentials: true).
CSRF is mitigated as you mentioned, see OWASP for details.

CSRF protection in a angular SPA using Double Submit cookie

We are struggling with trying to implement CSRF protection in a SPA using AngularJS and Restful services.
Scenario:
1. user logs in a JWT is created that contains a CSRF Token as part of the payload.
JWT is put in a HTTP Only Secure cookie and sent back on the response header
Additionally the same CSRF Token is sent back in the response.
The javascript (angular) code puts the CSRF token in $rootScope
User/program whatever... makes a request of a protected api. Send the CSRF token from $rootScope in the request.
Cookie travels back along with the request.
Server looks at the cookie unpacks the csrf token in the JWT compares CSRF token with the token that was in the request body.
Generates a new CSRF token... puts it in the jwt, puts jwt back in a cookie returns cookie along with the CSRF token in the response.
Client receives response, stashes the CSRF token in the $rootScope.
Repeat
Question: If I have many requests in a short period of time (sub second) from a client (, using an interceptor, maybe) which gets the CSRF token from the $rootScope. Could the csrf token in my request EVER be out of sync with the CSRF token that is in the Header/Cookie/JWT?
P.S. I understand the concept of promises etc.
The bottom line is I want every request to the API to have a CSRF token in the body that will match the CSRF token in the Header/Cookie/JWT.
Yes it could, and based on my past experience, it will happen sometimes, resulting in hard to catch bugs.
You can work around this by using multiple tokens and accepting each etc. to overcome timing issues, but it will be very complex and complexity is the enemy of security.
However, you can just use the same CSRF token for the user session. If there is enough entropy in the token (ie. it's long enough), it will still be infeasible for an attacker to successfully guess it, so you don't have to generate a new one for each request. That solves all related problems while it is very simple and reasonably secure. OWASP also states (somewhere in the middle) that this is good enough.

Session Token Authentication Security

I need some advice regarding using session tokens to authenticate users. I am building an AngularJS app which uses an API to tie in with the backend. I am only building the front end, not the backend. The documentation states that all calls to the API have a session token attached in the body of the request (POST).
I would like to know about the security of storing this token in localStorage. That is where I am storing it now and retrieving and attaching it to each API request. After login, the server sends the session token in the body and I save it from there.
There is no documentation about an x-access-token header that should be sent with the request made to the server. It is not being checked server side. What are the implications of this? I feel that it is susceptible to attacks without this added layer of security.
My main concern is the security of this setup. I want to know what the best setup is to make sure this app is as secure as possible and recommend changes to the way the backend is setup to facilitate this.
Thanks!
As you tell, you are only working on the UI part and not the backend. It is up to the backend team to ensure headers are properly evaluated and security is enforced (btw request headers do not belong to request body). Just put the token into the x-access-token header as they tell.
Storing the token inside the localStorage gives you a little more control over the cookie: You will not accidentally send it to unnecessary URLs. However, older browsers do not support it - you may need to use a shim for that.
In a case of SPA, you may consider not storing the token at all: It could be fetched each time your application is accessed and then stored within a service in angularjs, but it depends how your fetch/login operation is implemented (is it always interactive, how long does it take, etc).
I would suggest use $cookies rather than localstorage. As localstorage does not support some legacy browser.
I am using cookies to store token in my project

how to implement csrf protection for cross domain requests

I have two web apps, one for the Web UI in AngularJS and one for the REST webservices in Java. Both are deployed on separate domains.
The applications uses cookie for authentication. Whenever user enters a valid username and password, server returns a http only cookie back containing the token and that cookie is passed across all requests. I have enabled CORS on both apps, thats why the session cookie is working properly.
Now, I am trying to add CSRF protection for this. I was trying to use the csrf cookie where in the server will send the csrf cookie(not httponly) as part of REST response and the UI will read the value from the cookie and pass that in a csrf token header for the other REST calls.
The problem with this approach I am facing is that since the server is in different domain, I cannot read the cookie using $cookies in AngularJs. Is there a way to read a value of that cookie?
If not, then can I implement CSRF in some other way?
I also tried to implement the creation of the csrf cookie on the Web UI itself in the browser but the browser does not send the cookie to the webservice as its in different domain.
So, my question is how to implement csrf protection for this kind of situation?
You were on the right track with this:
I also tried to implement the creation of the csrf cookie on the Web UI itself in the browser but the browser does not send the cookie to the webservice as its in different domain.
The CSRF cookie isn't meant to be "sent" to the server, it is meant to be read by the client and then supplied in a custom HTTP request header. Forged GET requests (triggered by HTML tags such as <img src="">) from other domains cannot set custom headers, so this is how you assert that the request is coming from a javascript client on your domain.
Here is how you can implement the idea you were working on, imagine you have api.domain.com and ui.domain.com:
1) User loads the Angular client from ui.domain.com
2) User posts authentication information from Angular client to api.domain.com
2) Sever replies with an HttpOnly authentication cookie, called authCookie, and a custom header e.g. X-Auth-Cookie, where the value of this header is a unique value that is linked to the session that is identified by the authCookie
3) The Angular client reads the X-Auth-Cookie header value and stores that value in a XSRF-TOKEN cookie on its domain, ui.domain.com
So now you have:
XSRF-TOKEN cookie on ui.domain.com
authCookie cookie on api.domain.com
4) User makes a request of a protected resource on api.domain.com. The browser will automatically supply the authCookie value, and Angular will automatically send the X-XSRF-TOKEN header, and will send the value that it reads from the XSRF-TOKEN cookie
5) Your server asserts that the value of X-XSRF-TOKEN is linked to the same session that is identified by the value of the authCookie
I hope this helps! I've also written about token authentication for Angular, Token Based Authentication for Single Page Apps (SPAs) (Disclaimer: I work at at Stormpath)
Angularjs has built-in support for CSRF but unfortunately it doesn't work cross domain, so you have to build your own.
I managed to get it working by first returning a random token in the headers and cookies on the first request. In order to read the header you need to add it to Access-Control-Expose-Headers. This is then added to all posts
$http.get('url').
success(function(data, status, headers) {
$http.defaults.headers.post['X-XSRF-TOKEN'] = headers('XSRF-TOKEN');
});
Then on the server you can compare the cookie value with the value in the header to ensure they are the same.
$http docs : Angular provides a mechanism to counter XSRF. When performing XHR requests, but will not be set for cross-domain requests.
This is a small lib put together might help you https://github.com/pasupulaphani/angular-csrf-cross-domain

RESTful Token Authentication Clarification

I've read almost every answer on SO and some blog postings, but I can't figure out one simple thing. In a simple token authentication scheme where the server generates a token and sends it back to the user after verifying credentials, how does the client store and then resend that token in each request? I have seen both cookie examples and header examples. I would like to use the HTTP Headers if possible, but I can't figure out the mechanics of how to send the token to the client, where it will sit, and then have it sent back in the header upon requesting a REST resource.
I am using Jersey/Guice with AngularJS on the front end. Here are the resources I started with:
http://porterhead.blogspot.co.uk/2013/01/writing-rest-services-in-java-part-6.html
Session management : How to generate Authentication token for REST service ? (Jersey)
It depends on your needs. You can use HTTP basic or digest auth, if it is appropriate for you. If not, then if you don't need a permanent storage, you can store credentials in memory. If you need a permanent storage, then you can store them in localstorage, or any other client side storage, but aware, that they are considered not secure.
Anyways I think if your client or service is compromised somehow with xss, then you lost, and it does not matter what else you do about it. Otherwise you can send the credentials in plain text securely as long as you use HTTPS with proper settings. (But that's just an opinion, I am not a security expert, at least not in this topic.) So I think you should concentrate on not being xss vulnerable. For example you should use the proper headers and filter the input against js injection (and by firefox data URI injection). And use TextNode in your client instead of innerHTML wherever it is possible.
For example if you are using Javascript you can store the token in localstorage like window.localStorage["token_id"] on the client side.

Resources