I found similar topics to this which I referenced below but really none of them 100% answered my question and they are pretty old.
I fallen in a scenario that
- User opens two tabs for login page and try to login on both
Instead of showing an error message to user (I can't think of a good meaningful message to explain antiforgery validation to end user anyways), I want them to redirected to home page of the application.
My first attempt was, instead of using ValidateAntiforgeryToken attribute, I just used AntiForgery.Validate(); in try catch block and catch the HttpAntiForgeryException exception and handled that by checking if user already logged in
if (ex is HttpAntiForgeryException && HttpContext.User != null && HttpContext.User.Identity.IsAuthenticated){ // logic goes here... }
then navigate them to home page. I also covered if the second login tab was trying to login as another user, then it shows a message that user already logged in with different account etc... Up to here things were good (at least I was feeling that way)
However, there was another scenario:
if user opens two tabs, and logs in on both of them
then click logout button on tab1
then go to tab 2 which automatically logs out right away.
after that I go back to tab1 and submit the login form with valid credentials
then I was getting an antiforgery exception again but this time user was not logged in so my above handling mechanism didn't work, and I was not able to redirect to home page.
If I cover this scenario with additional else condition above, then basically I let user to hit login logic regardless they were antiforgery validated or not. So that basically means, I have AntiforgeryValidation mechanism with no real use, because I by-pass the whole antiforgery mechanism just like it was not there at all.
Below is the sample code:
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> Login(LoginVm model, string returnUrl)
{
try
{
AntiForgery.Validate();
return await LoginProcess(model, returnUrl);
}
catch (Exception ex)
{
if (ex is HttpAntiForgeryException && HttpContext.User != null &&
HttpContext.User.Identity.IsAuthenticated)
{
if(isSameUserLoggedIn()){
return RedirectToHomePage();
}
// if you reach here, then another user already logged in another tab with an active session
return UserAlreadyLoggedInWithAnotherAccount();
}
else if(ex is HttpAntiForgeryException){
// below function basically bypasses the AntiforgeryToken Mechanism as it
// will do the same thing when AntifogeryValidated or Not
return await LoginProcess(model, returnUrl);
}
throw; // this already handled somewhere else..
}
}
I tried to simplify the code above..
It then raised a question as "do I really need an antiforgery validation on Login page?" Because I am already sanitizing the return URL (in case there is any) and there is currently no way to navigate to some external url (I already handled that)
And as far as I know, the antiforgery token is based on a username (and some other criteria) and I already assume that at login page, to be able to do something, attacker should already have the credentials to be able to CSRF on that page.
And I also saw this comment which really made sense to me actually but just not sure.
The only system state that is changed is the user's login status, and in order to even make that happen the attacker would need their username and password which would mean everything is already maximally compromised
And the rest of the actions other than the login already validates the antiforgery. I also read couple articles which was suggesting not to use it, but some of the answers were saying "we should use", and those posts are pretty old 8 years, 9 years etc.. so that makes me feel worried.
Here are some articles and SO discussions:
So "do I really need an antiforgery validation on Login page?"