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.
Related
I've been provided with a REST API which has authentication type bearer (Security Scheme Type: API Key, Header parameter name: Authorization) and which i use to authenticate the user and then fetch other data (i will only create the front end using react).
As a first step the user logs in and i sent his/her username-password to the prementioned REST API and get back an access and a refresh token.
Is anything wrong with storing these 2 tokens in a cookie in order to use them in subsequent requests? How does JWT comes into play regarding these 2 tokens? Is JWT of any use to me in this situation?
There's nothing wrong in storing the tokens in cookies, but if you're planning to have a Single Page Application with React it should be enough to store these tokens in memory. Once the user refreshes the page you can either make them sign in again or perform a silent login in the background to get a new set of tokens. In both cases the session kept on the Authorization Server should kick in and you should get new tokens without the need of user interaction.
Your tokens will be much safer if you don't keep them in cookies.
JWTs are not a requirement for access and refresh tokens. If you don't have to use them I would recommend going with opaque tokens. That said, since you do not have control over the API you might be limited to the format required by the API. If you don't want to be limited by this format you can set up your own gateway which you can use to perform token exchange or introspection and forward requests to the API with proper tokens (something which is called a Phantom Token pattern.
From my understanding of the question, you are using an identity provider which provides you with access token and refresh token for the users. That means it is a authentication as a service REST API at works here.
The REST API requires an authorisation header to be passed along with the username-password to exchange for access token and refresh token for the users. (correct me if I'm wrong) In this case, you might want to keep the authorisation header away from the users (consult the authentication as a service documentation).
You call the REST API with payloads (the user-password) along with headers like this:
Authorization: ACCESS_TOKEN
However the ACCESS_TOKEN is the one provided by the vendor for you to use the REST API. On success call of the REST API, it should return you with a set of access token and refresh token. You can then use this access token and refresh token to safe guard your own API, API that you control to provide service to your users.
The access token and refresh token might just be JWT tokens (again consult the vendor documentation).
Also if you are using an authentication as a service REST API, check the documentation if they provide a client sdk. In that case, it should show you the best practise of handling the access token and refresh token it returned.
I am new to web dev. I built a backend using Django Rest Framework and am using JWT to handle auth.
Now, I want to connect my backend to my frontend in React. But, I am confused how this should be done. Here are my question:
What is the whole flow of requesting and using JWT access and refresh tokens? Like, when should I request a new access token with my refresh token and when should I request a new refresh token? Thanks!
I will make a quick response:
Flow of requesting and using JWT:
A picture worth a thousand words.
The access token is not lasting forever. Whenever it expires, you have to request a new access token with your refresh token.
Refresh tokens can expire, although their expiration time is usually much longer than access tokens. To handle this case, almost all implementations I've seen return a known error code of 'invalid_grant' that you can check for on the client-side and handle by your business. (ex: Show login page...)
Regarding your questions:
What is the whole flow of requesting and using JWT access and refresh tokens?
I don't know you're using what's package about JWT, having too many packages about Django JWT on github (pyjwt, djangorestframework_simplejwt, ...). And Im using pyjwt in my application, because I want to custom my authentication in-app for security.
The workflow:
When FE send request to login/signup APIs, BE generate a token by using JWT, and return that token in the response.
FE store that token on local storage, using it for sending other requests.
BE will take the token by each request from FE to verify. The same as TokenAuthentication of DRF, we must be custom it when using pyjwt. Will verify the JWT token instead.
when should I request a new access token with my refresh token and when should I request a new refresh token?
You can request a new access token after that token is expired.
When you're using djangorestframework_simplejwt you can see the refresh token but in my case (pyjwt), I just need re-generate jwt token again :)
There could be options, but simple flow is next:
You do auth and get access and refresh tokens from a backend and save them as cookies.
You use your access token until you get error 401 because access token has expired
Then you try to refresh your tokens using your refresh token. If you use axios on frontend, good option to write a middleware for this case. This middleware will refresh tokens and repeat a last request. There should be recipes in google.
If success you got new pair of access and refresh tokens and continue your workflow.
If fail, you need to auth again to get tokens.
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.
Context: Angular site is hosted on S3 behind CloudFront, separate from Express server that is used as API and almost all requests are XMLHttpRequests. All requests are sent without cookies (withCredentials = false by default) and I use JWT Bearer token for authentication by taking it from cookies in angular and placing to Authorization header (This technique is kind of what is described in CSRF Wiki page).
On Express site I do not allow Cookie header in Access-Control-Allow-Headers.
Cookies have secure: true flag, and are NOT httpOnly because I need to manually access them in angular.
Also I've read in this Medium article that JSON-Web-Tokens(JWT )/Bearer Tokens
is without a doubt one of the best methods of preventing CSRF
Question 1: Will I add extra security if I'll add X-XSRF-Token header to each request and for example make the mechanism stateless by checking for that same value in JWT payload? (I'we read about it in this thread)
Question 2: Do I actually need extra security efforts agains CSRF taking all that I described?
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.