Okay I've been bashing my head against various hard surfaces trying to get this one figured out and eventually did.

After looking at the errors I was initially getting:

Value cannot be null or empty.

And then later

The provided identity of type 'System.Web.Security.FormsIdentity' is marked IsAuthenticated = true but does not have a value for Name. By default, the anti-forgery system requires that all authenticated identities have a unique Name. If it is not possible to provide a unique Name for this identity, consider setting the static property AntiForgeryConfig.AdditionalDataProvider to an instance of a type that can provide some form of unique identifier for the current user.

Were fairly simple fixes.

First off, I had initially set my login cookie to persist. This means that it wouldn't be deleted when the browser is closed and would not expire either. While this did not cause the Value cannot be null or empty error, it was contributory in that the site was finding it and assuming a user had authenticated.

FIX

To fix this, I simply cleared cookies from my browser set the cookie's persist to false. This allowed me to focus more on the actual problem.

Value cannot be null or empty

This problem was actually not as complicated as I thought. When I started taking a closer look at things, I noticed that there was an error in the following code:

[HttpPost] public ActionResult Login(User model, string returnUrl) { if (ModelState.IsValid) { if (model.Login()) { FormsAuthentication.SetAuthCookie(model.Username, true); if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "Invalid email address or password."); } } // If execution got this far, something failed, redisplay form return View(model); }

This post captures an instance of my User model from the form (which is the login form so only EmailAddress and Password values are included). It also uses the Username value from this model (which is null) to set the Authentication Cookie.

I changed my .Login() method to a function that returns a User if the email address is found and the stored hash matches a hash of the password entered for the login.

The code, thus, changed to the following (this is only the key point of the change)

// Account.Login Post if (ModelState.IsValid) { var user = model.Login(model.EmailAddress); if (user == null) { ModelState.AddModelError("", "Invalid email address or password."); } FormsAuthentication.SetAuthCookie(user.Username, true); // create session variables n such } // User.Login public User Login(string EmailAddress { var user = dbContext.Users.FirstOrDefault(u => u.EmailAddress == Email); if (user == null) throw new Exception("User not found."); if (Hashing.ValidatePassword(Password, user.Password)) return user; return null; // if we got here, something went wrong }

Once I'd fixed this, I got another problem later. Some issue to do with the Anti-Forgery system.

While not a solution, I managed a workaround and commented out the following line from my _LoginPartial View:

@Html.AntiForgeryToken()

I had concerns about security but I figured that Forms Auth on a basic asp.net website with a hashed and salted password has been sufficient for quite a number of years, so I shouldn't have any issues with it here.