Spring webapp loads white page after login due to incorrect CSRF token - spring

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.

Related

asp.net core 3.1 Identity - redirecting to login after SignInAsync() when referrer is Stripe

We have an issue with a asp.net core 3.1 MVC application. The application is using the built in asp.net Identity feature. The application is working well for existing users. If you hit any [Authorized] route, you are redirected to the login page as expected.
However, rather than have a registration process in our app, for new users, we onboard them via Stripe Checkout. Upon successful payment, stripe redirects to a specific route in our application /conversion/success/{sessionid} where sessionid is the Stripe session. This action is marked as [AllowAnonymous].
We then pull the necessary customer details from Stripe, create a user in our repository via UserManager<T>. We then call SignInManager<T>.SignInAsync() to sign in the new user, before redirecting the new user to the [Authorized] home page.
This process works perfectly when running locally on our test machines. Also, when running on our production server (Azure App Service) it also works perfectly when we hit the route manually through the browser.
However, when we actually run the process through Stripe, complete a payment and let Stripe redirect the customer, we get a strange behaviour.
The conversion route is hit, the user record is created, the sign in process completes but upon redirection to home page, the authentication middleware takes over, says it's not authenticated and redirects to the login page.
Just to compound matters further, if you then simply type in the home page route in the browser, the user is in fact logged in exactly as expected and the application works perfectly.
Using Fiddler to intercept the calls and look at headers, etc. we can't see why there would be a different behaviour when coming from Stripe as opposed to typing directly. We've even tried redirecting from a different website to our registration process and that works as expected too.
Any idea why we are seeing this behaviour?
---- Update ---
If, rather than redirect to home page at the end of the onboarding process, we simply show a simple View with an anchor link to home page, the user can then go to home page as expected.
Is it possible that you're rendering the page before authentication has been completed? Since UserManager uses a cookie to establish the user's session, authentication needs to complete before any response headers or body is set so that the Set-Cookie header can be sent in the response.
Based on what you described it sounds like the user is hitting the homepage after the redirect without having the authentication cookie. Where I'd start debugging this is by using your web inspector with "Preserve log" turned on and going through the Stripe Checkout process. Then, inspect the headers sent to the browser when you land on the redirect page & make sure the authentication cookie is set.
Between requests to Stripe and SignInAsync it seems possible that there might be a missing await, so the redirect is happening before the authentication context is updated. Hard to say more without seeing your code!

Redirection after login in Spring Authentication (Environment problem, Tomcat vs Jetty)

The app I am maintaining has a custom Single Sign On implementation.
After receiving a valid token (which it provided earlier and stored to db),
the app executes a CustomAuthenticationFilter successfully.
The app works fine at "Jetty" on Eclipse. After a valid url request sent, the app successfully opens the welcome page which is just after login page.
Url request:
http://99.99.99.99:8090/MyApp/j_spring_security_check?tokenId=19d79b76-0d1e-4327-871b-0e8792e03be2
But when deploy it to a "tomcat", do a valid url request, instead of opening welcome page, it stucks at login page (below)
http://99.99.99.99:8090/MyApp/login.xhtml;jsessionid=3B8C865260E86F3609F75199A23A1120
The application deployed to both, ports purely the same. No exception in logs. Even I can read successful login logs in tomcat. I can't figure out why it behaves different?

Securing Spring Boot Web App With Spring Security Doesn't Work

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.

How to prevent SpringSecurity remembering Ajax urls in a Grails app

I've had some odd issues lately where after logging in to my application, rather than seeing the expected page, I get a json response rendered in the browser.
What's happening is I have a javascript routine on every page of the application that polls via ajax for new messages for the user.
There is a point when the user has signed out manually.. or is logged out when this ajax call is made and spring security is remembering this URL as the URL to redirect to again when logged in. So when the user signs in again, instead of being redirected to their dashboard, they are presented with the JSON response.
I need to prevent Spring Security from remembering Ajax called URLS, can anyone tell me if this can be done?

Spring/Tomcat 6 Session Expiration Issue

I'm using Spring MVC for a personal webpage with a local Tomcat 6 server. I'm using a default Tomcat configuration(what eclipse would setup by default).
In my controllers(using one controller for each page, and creating Session beans to pass information between them) I have two methods, one for capturing a POST and one for capturing a GET Request Method. The page logic will have the user click a submit button and will use a "redirect:abc.htm" return to send them to a new page or back to the GET method.
I'm not explicitly handling cookies, but do have all the information in Session Beans and am using Spring Security to handle security/user management.
I have a spring security configuration to redirect the user back to the login page if they are not authorized. I also have an ExceptionHandler catching HttpSessionRequiredException, though this is not what is triggering when I expire the user sessions(it's using the logic of my Spring Security configuration).
When the session is expired(I'm doing this through Tomcat manager) the user is redirected back to the login page. They are redirected after they try to do something(click a submit, or revisit any page except login.htm).
My issue is that once they get back to the initial page that their session expired at, if at the time of expiration they clicked a submit button, it is redirecting them past the initial page and handling the POST event from the submit.
Example:
User is logged in, and on the main page
User Session Expires
User, on the main page, click a submit button
User is redirected back to the login.htm page
User logs in and navigates back to the main page.
Instead of following the logic of the GET for the main page, they are treated to the POST of the main page, and I'm not sure where the POST variables are coming from.
Is there any way to trace where this error is coming from or what exactly is causing it?
This is done by spring-security. Spring security stores the request details in the session before redirecting the user to the login page. On successful login it will retrieve the request details from the session and redirect to that.
You can set the always-use-default-target attribute of the form-login configuration to override this behavior.

Resources