Spring Security - CSRF token on GET request - spring

I configured CSRF protection in my Spring 5 (Boot 2) RESTful web service because I want to prevent CSRF attacks (I am using JWT cookie for authentication and authorization). On each request I am getting a new XSRF cookie. The value of that cookie I am sending back through the X-CSRF-TOKEN header.
I noticed that POST, PUT and DELETE methods require the value of this token (in the X-CSRF-TOKEN header) in order to work properly, but GET method works just fine without X-CSRF-TOKEN header.
Is this behavior intentional because GET method should not change state or I did something wrong?

CSRF token is intentionally excluded from GET to avoid token leakage to a 3rd party

Related

CSRF Token keeps refreshing every 2nd request. (Spring boot 3 and Next.JS)

I've been creating a Spring boot 3 and Next.JS app with Spring Security. Been having some problems with the "Set-Cookie" header being refreshed on every 2nd request I make to the backend. I can illustrate the problem as:
Make a request to /finances (with XSRF-TOKEN provided post-successful login)
The request goes through (contains all the necessary data for a valid request [CSRF cookie, JWT token, etc..]). The response contains a "Set-Cookie: XSRF-TOKEN= ...." header without the TOKEN.
I refresh the page (make a new request using the useEffect hook) and the CSRF cookie appears again, a new one.
If i refresh the page (make a new request using the useEffect hook) again, the CSRF cookie is deleted.
And so on.
I pass the cookie value on every request to the backend (whenever it is available) and the backend operates on it correctly. So there are no problems with the token validation.
I've also read that the spring security will provide a new XSRF cookie/value if the request from the client does not provide a cookie of the same name.
Could some one please help?
I've tried configuring the response on the backend to attach a new cookie with the same value, and also saving the cookie value in the session storage for later use. None of the options seem to work.
Making two requests to the server would solve the issue (probably) but that would not be an optimal solution. To the problem.

CSRF token value when same page is opened in two tabs on same machine?

From my understanding, when CSRF is enabled on server side, the server creates a token (say token1) and injects it in to the form and saves the same in the cookie of the client browser.
When the client sends the form request to the server, it sends the csrf token (token1) from browser cookie and also send the same token as in the form. The server validates the request by checking that the token in cookie and the token in form match and then processes the request.
Now, if i open the same form in another tab, will the server generate another token (token2) and inject it in to the form and cookie. Then, in the cookie, token1 will be overwritten by token2. So the submission of the form in first tab will not work in this case? But from experience i see that the submission of form in tab 1 still succeeds.
So can some one explain how it's succeeding in the above scenario??
Since you have added the Spring Security tag, I will describe how Spring Security uses the Synchronizer Token Pattern to protect against CSRF attacks.
the server creates a token (say token1) and injects it in to the form and saves the same in the cookie of the client browser.
That's not exactly what happens. The server will create a CSRF token (token1) and store that token in the HttpSession. The CSRF token (token1) is also be embedded in the form on the client side. The client is also given a Session ID (session-id1) which is stored in a cookie.
When the client submits the form, it sends token1 and session-id1. The server will then use session-id1 to look up the HttpSession and get the expected CSRF token for that session. It will compare the expected CSRF token to token1 and if the values do not match, the HTTP request will be rejected.
If you open the same form in another tab, the browser will still have access to the Session ID (session-id1). That form will get the same token (token1) that was associated with session-id1.
In the end, there is only one CSRF token (token1) that is used in both tabs.
You can find more information about protection against CSRF attacks in the Spring Security reference documentation.

Regarding Cross site Scripting Forgery

I am working on csrf and using spring 5. Spring 5 automatically provide supports for csrf and on enabling csrf protection on the server side I am getting
403: Invalid X-CSRF token
So this means a token needs to come from frontend?
My understanding is that backend generates csrf token and sends as a response to frontend browser and then it uses this token and send it as cookies to the backend server and then backend will validate it. is my understanding is correct?
when manually generating the hidden token for csrf, How backend will know it is a valid csrf token?
Second Scenario: Suppose two users are logged in to my website and frontend is sending this token to backend then how the application will differentiate which token is for which user?
Also please explain how it works internally means we enabled csrf protection in the backend and manually generated a token on the front end then what it does behind the scenes?
consider my frontend is JS pages
Is there is any specialty of Spring 5 which take care's of sessions for each user and validate tokens automagically for each user?. I tried finding it on the official website but didn't get it anywhere
Hi Zaib the csrf token is generated from back-end as you stated, once it is generated is automatically sent to the front-end which must take care to retrieve from the model and re-post for each "POST" requests.
You can share the csrf token via different way mostly i used header or html parameter.
A token is related to a specific session so is not really important if you have a logged user or not , even not authenticated users must send the csrf token for "POST".
The csrf token is validated via a filter placed in the front of the filter chain defined by Spring security itself, if you search in the documentation there is a table showing you the position of each "default" filter enabled by Spring security. Moreover if you enable debug on Spring ( </debug> is enough in your xml configuration) you will have printed all the filters used while processing an http request.
So each time a request with "POST" method pass through that filter , it will check if in the parameters there is the csrf token or header.
I never used as cookie so it may a different case for you if specifically need that but it does not differ on how it works.
Here is the details of csrf implementation on Spring:
https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/htmlsingle/#csrf-configure
I said "POST" method but actually the token is checked for any method that is related to a change of state , you can refer to doc here:
https://docs.spring.io/spring-security/site/docs/4.2.5.RELEASE/apidocs/org/springframework/security/web/csrf/CsrfFilter.html
Hope this help clarifying a bit the usage of the csrf token.

Spring Security set CSRF in login response with new session token

I'm using spring security in my spring boot application. I have a front end single page app that logs in via rest. I have no problem logging in, but once I've logged in, my session token changes, BUT THE CSRF TOKEN DOES NOT.
Is there any way to force spring security to set the csrf token since the old token associated with the un-authenticated session token will not work with the new authenticated session token?
I'm storing the CSRF token in a cookie, and sending it back from the client in the header of every state altering request. I can't login and logout without an intervening request (non-post) to retrieve the csrf token. This seems like a crock.
SO a simple solution is to redirect the login request once it's successful. This puts the request through another loop through the security filter chain ensuring a new CSRF is added to the new session token. A good night sleep does wonders.

Missing CSRF token in REST request

I'm writing a REST API using Spring MVC. I'm trying to access a controller method via a POST request.
I always receive a 403error:
Invalid CSRF Token '' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
How can I deliver a CSRF token within my REST request?
I tried to use the default security password which is displayed during application startup as the value for _csrf but it wasn't successful.
How can I retrieve the CSRF token and is it correct to send the token in the _csrf parameter?
You will need to provide the correct header and CSRF token when making the request e.g.
request.setRequestHeader('${_csrf.headerName}', '${_csrf.token}');
You can also send the token as a request parameter using _csrf.parameterName.

Resources