Something is wrong with how my Spring web app handles CSRF tokens. When I try to login in browser, I get the following error:
There was an unexpected error (type=Forbidden, status=403).
Could not verify the provided CSRF token because your session was not found.
Strangely, the error goes away if I use incognito mode in Chrome or another machine. So I figured maybe I'm stuck with an outdated CSRF cookie, and I deleted the only cookie associated with the login page in Chrome. When I refresh, I can see that the server provided me with a fresh cookie that is different from the original one. How is it possible that the error still persists?
I was able to reproduce the issue on another machine earlier and when I deleted everything in Chrome, it started working. I don't want to delete everything from Chrome on this machine, and also, I would like to understand what caused the issue in the first place.
I can see the following field in both Incognito mode and normal:
<input type="hidden" name="_csrf" value="96dddccc-4425-40b2-9947-462877c94238">
However, when I refresh the page in normal mode, I get a new CSRF value every time, whereas when I refresh the page in incognito mode, I get the same value every time.
I went through all the configs in my Spring app and I haven't configured CSRF tokens anywhere. Spring is doing that inside some black box that I can't access to see what's wrong.
Related
I have a basic Spring (v5.3.23) web app running in an Apache Tomcat container (v9), and using eclipse as IDE. It uses Spring security for processing logins.
Everything runs almost correctly, but sometimes, after a successful login, the browser shows a white page, while there is no exception logged server-side or any other message. The problem appears both in development environment and production environment, so I don't think it's eclipse-related.
I have managed to pin down the problem to the following sequence :
Start tomcat container
Open login page in browser
After login, the secured home page is displayed correctly
Re-start tomcat (the problem occurs both when changes are made to the web app or not)
Refresh the browser, which redirects to login
Login again
The blank page is shown, no exception logged, no log messages in console
In this sequence, the problem occurs most of the time. If between steps 5 and 6 I refresh the page one more, meaning the login page is reloaded, the white page problem does not occur anymore, and the proper page is displayed.
A strong possibility is that it's something related to either the CSRF token in the login form or the JSESSION cookie of the container, but short of debugging through Spring code, I can't figure it out.
LATER EDIT
I narrowed down the issue to the CSRF token; if I change the value in the login form, I always get the blank page.
I have noticed the _csrf token has one value in the login form, then a different, but single value across all form that are used while the user is connected. Seems like the _csrf token is linked to the user session somehow.
The same happens when the login page is refreshed: different tokens in login & other app forms, but somehow,, sometimes, the initial token does not match what the server expects.
We've recently deployed a Laravel Application and experienced some weird issues with Some Safari Versions on our application.
When surfing on our applications, especially if the user is not authorized, we sometimes have on Safari the Problem that the XSRF-Token is not present within the Request/Response-Header.
On application Forms, the missing token results in a 419 Page expired issue.
The Problem only appears sometimes in some versions of Safari. Mostly a Reset Cache & Cookies fixes the Problem for 1 or 2 form request.
I did a complete reset of Safari
Allowed Cookie
Allowed Tracking
Disabled Plug-Ins
Technology
We use PHP 8.0 and the latest Laravel release. For the Frontend, there is a vue.js application with inertia.js as a connector. Regarding passing csrf-tokens to the Frontend, there is no further configuration needed to pass down the csrf-token. (Soruce)
I tried to capture the TokenMismatchExpection but no chance only the HTTPException works.
The question I have:
Does anybody experience similar problems? How can I prevent them?
Attached some Laravel Debugbar Screenshots.
left side Safari 14.03 | right side Chrome
Page expired screen
I ran in the same issue. I pinned the problem down to Safari ignoring the 'Set-Cookie' response header if the page was opened via a link from another site. (In my case, it's a link in an email opened in MailHog). If the link is opened in a new tab by hand, the problem is gone.
Due to the missing XSRF-TOKEN cookie, axios doesn't set the X-XSRF-TOKEN header in the requests leading to the 419 from Laravel.
So far I haven't found a feasible solution to inject the X-XSRF-TOKEN header by hand because the the VerifyCsrfToken Middleware expects the token to be an encrypted cookie.
I am working on Laravel 4 application and using Sentry for authentication. I need to add Keep Me Logged In functionality into my application. I have googled around and found that passing second variable to Sentry::login($user, $remember) sets up a cookie. I have done that and can verify that it is working from the browser (Chrome). But somehow whenever I try Sentry::check() after a day it returns null for cookies. Even when the cookie is present in the browser. Can anyone point out what am I doing wrong? Same happens when I attach my custom cookie to the response.
This scenario happens on my production server. Whereas it works fine on my local server.
PS: Lifetime of the cookie is set to forever (5 Years)
After working around for sometime on the issue I was finally able to resolve the issue by creating and attaching custom cookie to the response after login. And then wrote a middleware to check for that cookie. If present then login user and continue.
I've spent about a full day attempting to get a very basic Spring Boot app with Spring security up and running to no avail. I cannot find a single example of code that works when I run it.
This example is from spring.io. Here is what I'm seeing in that example:
I start at http://localhost:8080 and see the welcome screen.
I click a link to http://localhost:8080/hello, which redirects me to http://localhost:8080/login.
I enter "user" and "password" as specified in WebSecurityConfig.java, which redirects me back to the welcome screen. I was expecting to be redirected to http://localhost:8080/hello.
When I click the same link to http://localhost:8080/hello I get the login screen again.
I've tried debugging via #EnableWebSecurity(debug = true) but there are no errors.
The above experience is endemic of what I experience when I download every example. Admittedly I'm new to Spring, and presumably I'm making some kind of newbie configuration mistake. Any help would be greatly appreciated.
I downloaded the code and ran using maven and it works perfectly fine. After logging in, for all subsequent page loads of http://localhost:8080/hello loads the page and not the login page again unless of course I log out. The problem you have mentioned may be caused by ( with quite high probability since you have mentioned it's endemic) is that your browser may be having issue with transmitting the default JSESSIONID cookie (which is set on first page visit and updated ( as good security practise by Spring security) on first login. For subsequent visits same JSESSIONID is sent to the server and it is a key for the session object stored on server which contains the now authenticated/authorized user. If some how this cookie is not transmitted back to server ( one reason could be it's disabled in browser setting) then your application (protected by spring security) would not know that you are an already authenticated user and will show you the login page again. For e.g, for Chrome you can see the cookie settings at Settings --> Content Settings --> Cookies --> Allow sites to save and read cookie data (recommended). You can also view the cookie header getting passed on each page load post successful login by using Developer tool in respective browser.
I am currently working on a small project using keycloak 2.5.0
I've already set up the user login and i'm now trying to implement a page wide logout button.
As the documentation states, is simply called the route
http: //my-auth-server/auth/realms/master/protocol/openid-connect/logout?redirect_uri=http: //application-root.com/
For the sake of simplicity i used an anchor tag to make this GET Request.
If i take a look into the Network tab of the firefox developer tools everything seems to be working fine. I am getting back a 302 status code for the redirection request. And after that, the application successfully requests the http: //application-root.com/ with a status code of 200 and redirects me to this page.
But when i want to request the locked content again (the one secured by keycloak) its still accessible.
But whenever i manually delete the JSESSIONID and KEYCLOAK_ADAPTER_STATE cookie after the redirection, everything works fine and i'm being logged out correctly. Sadly i can't delete those cookies programmaticly because they are HttpOnly
What is the expected behaviour of this request ?
Am i missing something ?
Has anyone experienced anything similar ?
Thanks for any help
I implemented logout using Keycloak 4.8.3 version. Mandatory parameter is id token (id_token_hint). Optional parameter is redirect url (post_logout_redirect_uri).
Example:
http: //my-auth-server/auth/realms/master/protocol/openid-connect/logout?id_token_hint=eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJEY0gyNnl0OFV0OEJQTGxoR&post_logout_redirect_uri=http:%2F%2Fapplication-root.com%2F