I am working on a logout feature in the application we are using ASP.NET Identity login. I can login successfully but when I logout and then try to login again I get the following message:
The provided anti-forgery token was meant for a different claims-based user than the current user.
Here is my logout code:
public ActionResult Logout()
{
SignInManager.Logout();
return View("Index");
}
**SignInManager.cs**
public void Logout()
{
AuthenticationManager.SignOut();
}
After the user press the logout button he is taken to the login screen. The url still says “http://localhost:8544/Login/Logout“. Since we are on the login screen maybe it should just say “http://localhost:8544/Login“.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
What worked for me was switching the order of the middlewares used. Add first app.UseAuthentication() and then the antiforgery stuff. This is how I did it:
app.UseAuthentication();
app.Use(next => ctx =>
{
var tokens = antiforgery.GetAndStoreTokens(ctx);
ctx.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() { HttpOnly = false });
return next(ctx);
});
Doing it the other way around creates a token that is not meant for authenticated users.
Method 2
You are returning a View, rather than calling RedirectToAction(). So what is happening is the view is running under the context of the logout request, where the user is still logged in. They won’t be logged out until the request finishes.
So, try
public ActionResult Logout()
{
SignInManager.Logout();
return RedirectToAction("Index", "Home");
}
Method 3
Try this:
public ActionResult Logout()
{
AuthenticationManager.SignOut();
Session.Abandon();
return RedirectToAction("Index");
}
That will reload your login page which will provide you a new CSRF token.
Method 4
I found that users were experiencing this issue when they would submit the login page when already authenticated. I replicated this error by:
- Opening two tabs when logged in,
- Logging out from one,
- Reloading both,
- Logging in to one,
- Trying to log in with the other. The error occurred before entry to the POST: /Account/Login action.
The majority of my users use the web app on a mobile device, so it made sense that they had bookmarked the login page and pulled it up and submitted when they had a tab opened in the background already logged in. I also surmised that sometimes they would have a dormant tab loaded with the login form and just pull that tab up and submit.
I realize that there are many ways to solve this issue. I solved this with two changes:
- I added a check on User.Identity.IsAuthenticated to my “GET: /Account/Login” action:
if (User.Identity.IsAuthenticated)
{
try
{
return RedirectToLocal(returnUrl);
}
catch
{
return RedirectToAction("index", "Home");
}
}
- In my controller I created a “check if logged in” action:
[AllowAnonymous]
public JsonResult CheckLogedIn()
{
try
{
return Json(new { logged_in = User.Identity.IsAuthenticated }, JsonRequestBehavior.AllowGet);
}
catch
{
return Json(new { logged_in = false }, JsonRequestBehavior.AllowGet);
}
}
And I called it repeatedly in the view to redirect all open login forms away from the login page when already logged in:
<script type="text/javascript">
setInterval(function () {
$.ajax({
url: '@Url.Action("CheckLogedIn", "Account")',
type: "GET",
}).done(function (data) {
if (data.logged_in) {
window.location = '/';
}
});
}, 5000);
</script>
This worked well for me. Hope it helps you.
Method 5
I’ve been getting this same error on the login for a LONG time now, but haven’t been able to work out why. Finally I found it, so I’m posting it here (although it’s a slightly different cause) in case someone else has it.
This was my code:
//
// GET: /login
[OutputCache(NoStore = true, Location = System.Web.UI.OutputCacheLocation.None)]
public ActionResult Login()
{
return View();
}
//
// POST: /login
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
if (!ModelState.IsValid)
{
return View(model);
}
//etc...
This worked fine for 99.99% of the logins, but every now & then I got the above-mentioned error, although I couldn’t reproduce it, until now.
The error only happens when someone clicks the login button twice in quick succession. However, if I remove the AuthenticationManager.SignOut line in the Login action, then it’s fine. I’m not sure why I put that line in there, but it’s causing the issue – and removing it fixes the problem.
Method 6
I didn’t have the AuthenticationManager.SignOut command as Sean mentioned in my Login method. I was able to reproduce by clicking on the login button more than once before hte next View loads. I disabled the Login button after the first click to prevent the error.
<button type="submit" onclick="this.disabled=true;this.form.submit();"/>
Method 7
Try this:
public ActionResult Login(string modelState = null)
{
if (modelState != null)
ModelState.AddModelError("", modelState );
return View();
}
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model)
{
AuthenticationManager.SignOut();
return RedirectToAction("Login", "Controller", new { modelState = "MSG_USER_NOT_CONFIRMED" });
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0