I am wondering if there is a more efficient route to take here. Using AspNet.Identity
I would like to allow the user to sign in to the same text box using either their UserName
or Email
. I went ahead and addressed this issue in the AccountController Login ActionResult
. I run the check before calling:
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: true);
The Check:
//TODO: determine if there is a more efficient way to allow user to login either with Email || UserName
if (model.UserName.Contains("@"))
{
using (var context = new ApplicationDbContext())
{
model.UserName = (context.Users.Any(p => p.Email == model.UserName)) ?
context.Users.SingleOrDefault(p => p.Email == model.UserName).UserName :
model.UserName;
}
}
My concerns here are two fold:
I am including the entire
ActionResult
below for reference.
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
//TODO: determine if there is a more efficient way to allow user to login either with Email || UserName
if (model.UserName.Contains("@"))
{
using (var context = new ApplicationDbContext())
{
model.UserName = (context.Users.Any(p => p.Email == model.UserName)) ?
context.Users.SingleOrDefault(p => p.Email == model.UserName).UserName :
model.UserName;
}
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: true);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
related github issue #2 and #4
ASP.NET Core Identity: Is an API that supports user interface (UI) login functionality. Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.
You need to set FormsAuthentication. SetAuthCookie(PrimaryKey, false); when user is loggedIn. Here, PrimaryKey is the key that you can use throughout the session for identification of the user using User.Identity.Name . Also, when user log out of the application, you will call FormsAuthentication.
The Identity framework is another dependency that we will add to our application in the project. js file. This framework allows us to add features where users can register and log in with a local password. The framework also supports two-factor authentication, third-party identity providers and other features.
There will be one security issue. You can get the username of another user if you know his email:
I would declare new variable instead of model.UserName reuse. And your query will be a little more effective if you use FirstOrDefault:
var userName = model.UserName;
using (var context = new ApplicationDbContext())
{
var user = context.Users.FirstOrDefault(p => p.Email == model.UserName);
if (user != null)
{
userName = user.UserName;
}
}
var result = await SignInManager.PasswordSignInAsync(userName, model.Password, model.RememberMe, shouldLockout: true);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With