Reputation: 55
I am having problems with my anti-forgery token after a form has been submitted. I keep on getting this error message:
The provided anti-forgery token was meant for user “{user}”, but the current user is “”
The difference between what other have asked here and with mine is that it's say the current user is blank and the anti-forgery token is looking for a user. This makes no sense because when I checked HttpContext.Current.User.Identity.Name and Membership.GetUser().UserName, they do have the user anti-forgery token is looking for. This is not really making any sense.
NewRecordEntry.cshtml
<h2>New Record</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div id="new-record-entry">
@Html.DropDownListFor(model => model.recordTypeID, Model.GetRecordTypeList())
</div>
<input type="submit" name="NewRecordEntry" id="continue" size="11" />
}
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult NewRecordEntry(FormCollection frm, NewRecordEntryViewModel nrevm)
{
TempData["NewRecordEntry"] = nrevm;
return RedirectToAction("NewRecord", "FakeController");
}
Authentication Filter
public class FakeAuthenticationFilter : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
// Get userData stored in a session. Workplace environment does not allow cookies
UserData userData = (UserData) filterContext.HttpContext.Session[UserInfo.SessionUser];
if (userData != null)
{
// Get identity and principal
var identity = new GenericIdentity(UserInfo.SessionUser, "Forms");
var principal = new FakePrincipal(identity);
principal.UserData = userData;
// Set the context user.
HttpContext.Current.User = principal;
}
else
{
filterContext.Result = new RedirectResult("~/Login");
}
}
public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
{
}
}
Membership
public class FakeMembershipProvider : MembershipProvider
{
public override bool ValidateUser(string username, string password)
{
// Check if this is a valid user.
// The application sends the username and password to an LDAP DLL which
// reurns "Success" if it was a match.
string result = LoginService.AuthenticateUser(username, password);
if (result == "Success")
{
return true;
}
return false;
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
if (LoginService.UserData != null)
{
return new MembershipUser("FakeMembershipProvider",
username, LoginService.UserData.UserID,
null, null, null, true, false,
DateTime.MinValue, DateTime.MinValue, DateTime.MinValue,
DateTime.MinValue, DateTime.MinValue);
}
return null;
}
}
Login Post Controller
#region Login Post Controllers
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(FormCollection frm, LoginViewModel lvm, string returnUrl)
{
List<string> errorList = null;
try
{
if (ModelState.IsValid)
{
string result = Services.ValidateLogin(lvm);
if (result == "Success")
{
if (Url.IsLocalUrl(returnUrl)
&& returnUrl.Length > 1
&& returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//")
&& !returnUrl.StartsWith("/\\"))
{
return base.Redirect(returnUrl);
}
return base.RedirectToAction("Index");
}
else
{
TempData["errors"] = result;
ModelState.AddModelError("", result);
}
}
else
{
errorList = Services.AddErrorMesagesToView(ModelState);
TempData["errors"] = errorList;
}
//return base.RedirectToAction("Admin", new { section = section });
ModelState.Clear();
return View(new LoginViewModel());
}
catch (NullReferenceException ne)
{
if (ne.Source != null)
Console.WriteLine("NullReferenceException source: {0}", ne.Source);
}
catch (HttpException he)
{
if (he.Source != null)
Console.WriteLine("HttpException source: {0}", he.Source);
}
catch (Exception e)
{
if (e.Source != null)
Console.WriteLine("Exception source: {0}", e.Source);
}
finally
{
ModelState.Clear();
}
return base.RedirectToAction("Login");
}
#endregion
ValidateLogin
public static string ValidateLogin(LoginViewModel lvm)
{
/* string ldapServer = WebConfigurationManager.AppSettings["LDAPServer"];
string result = Fakeauthenticate.Fakeauth.LdapAuth(lvm.Login, lvm.Password, ldapServer);
*/
string result = null;
const int INACTIVE = 1;
FakeEntities db = new FakeEntities();
// This is the only feasible way to call an SQL user-defined scalar function
string sqlQuery = "SELECT [dbo].[Util_GetUserActivationStatus] ({0})";
Object[] parameters = { lvm.Login };
int status = db.Database.SqlQuery<int>(sqlQuery, parameters).FirstOrDefault();
if (status == INACTIVE)
{
return "The user is currently locked out.";
}
if (Membership.ValidateUser(lvm.Login, lvm.Password))
{
HttpContext.Current.Session[UserInfo.SessionUser] = LoginBusiness.GetUserData(lvm.Login);
HttpContext.Current.Session.Timeout = UserInfo.Timeout;
result = "Success";
}
else
{
result = LoginBusiness.AuthenticateUser(lvm.Login, lvm.Password);
if (result == "Login_Failure")
{
if (HttpContext.Current.Session[lvm.Login] == null)
{
HttpContext.Current.Session[lvm.Login] = 1;
}
else
{
uint loginFailures = (uint)HttpContext.Current.Session[lvm.Login];
HttpContext.Current.Session[lvm.Login] = ++loginFailures;
// If the maximum number of login failures have been reached, then lock the user out.
if ((uint)HttpContext.Current.Session[lvm.Login] == UserInfo.MAX_LOGIN_FAILURES)
{
db.Util_LockUserOut(lvm.Login);
return "Your account has been temporarily locked.";
}
}
}
}
return result;
}
Upvotes: 3
Views: 5938
Reputation: 335
The problem lies in your FakeAuthenticationFilter. I'm guessing you are using this filter on the controller action which loads the page. FakeAuthenticationFilter sets HttpContext.Current.User = new FakePrincipal(identity). This principal probably has a Name property, which is the user you see in the error message. .NET uses this Principal to generate the tokens on the page, but when you submit the tokens, the HttpContext will not have the same Principal.
A solution could be to put FakeAuthenticationFilter on your NewRecordEntry Action.
Upvotes: 0
Reputation: 20033
You should check if there is more than one @Html.AntiForgeryToken()
in your form. If yes, remove all but one.
Also make sure that you are not submitting the form twice. This will mess up the AntiForgeryToken
.
If you want to disable this check, add the following to your Application_Start
method:
AntiForgeryConfig.SuppressIdentityHeuristicChecks = true
Upvotes: 1