Any password is working with SmartAdmin MVC - c#

I'm able to authenticate using anything for a password. The email has to be a valid registered email, but the pwd doesn't matter. Everything else is working normally.
Any suggestions on where to start trouble shooting this? I haven't found any similar issues in web searches.
My view...
My action in the account controller...
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(AccountLoginModel viewModel)
{
if (!ModelState.IsValid)
return View(viewModel);
var user = _manager.FindByEmail(viewModel.Email);
if (user != null)
{
await SignInAsync(user, viewModel.RememberMe);
string uid = user.Id;
return RedirectToLocal(viewModel.ReturnUrl);
}
ModelState.AddModelError("", "Invalid username or password.");
return View(viewModel);
}
and the signinasync method...
private async Task SignInAsync(IdentityUser user, bool isPersistent)
{
// Clear any lingering authencation data
FormsAuthentication.SignOut();
// Create a claims based identity for the current user
var identity = await _manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Write the authentication cookie
FormsAuthentication.SetAuthCookie(identity.Name, isPersistent);
}
I did create a seperate MVC web project to see the scaffolded login action, which is quite a bit different. The SmartAdmin template is customized enough that its difficult to start changing things without knowing what I'm effecting. Any direction is appreciated.

If username in your system is email, you should use
var user = _manager.FindAsync(viewModel.Email, viewModel.Password);
and then signin the user if it's not null.
If username is not email, you should first get the user and then check for password
var user = _manager.FindByEmail(viewModel.Email);
bool isPasswordCorrect = await _manager.CheckPasswordAsync(user, viewModel.Password);

Related

C# login function implemented using SignInManager

I am trying to implement a login function using the SignInManager I tried the below code Everytime the
result.Succeeded
is failed. I cannot figureout whats wrong. The model state is valid and the database connection is also working.
Controller
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.UserName,
model.UserPassword, model.RememberMe,false);
if (result.Succeeded)
{
if (Request.Query.Keys.Contains("ReturnUrl"))
{
return Redirect(Request.Query["ReturnUrl"].First());
}
else
{
return RedirectToAction("Shop", "Main");
}
}
}
else
{
ModelState.AddModelError("", "Failed to login");
}
return View();
}
You cannot directly insert a user record with a plain password in the User table. You have to do it via the ASP.NET Identity register user api. See Here
For instance, if your password is helloworld, the library will hash it to some gibberish string. That is for security purpose, that it wouldn't compromise users' passwords if someone get access to the User table.
Try to set EmailConfirmed as True in your AspNetUsers table like below:
result:
Read this to know more.

ASP.Net Core - How do I wait for User Identity to be available immediately after signing in?

I have a fairly standard Login action, but I want to change the redirect depending on the user role.
However, there's some sort of race condition going on: HttpContext.User says it yielded no results, causing the admin user to be redirected to the wrong homepage.
How do I 'wait' correctly until the HttpContext.User is available after signing in?
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginDto loginDto)
{
if (!ModelState.IsValid)
{
return View(loginDto);
}
var result = await _signInManager.PasswordSignInAsync(loginDto.Username, loginDto.Password, true, false);
if (!result.Succeeded)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(loginDto);
}
// This check doesn't always work because User = null
if(HttpContext.User.IsInRole(RoleEnum.Administrator.ToString())){
return LocalRedirect(Url.Action("Index", "Home", new { area = "Admin" }));
}
return LocalRedirect(loginDto.ReturnUrl ?? Url.Action("Index", "Home"));
}
User UserManager instead of HttpContext in this scope like below
var userInRole = await _userManager.IsInRoleAsync(user, role);

What actually happens when you log-in while already logged in with OWIN in ASP.NET MVC 5?

While testing an ASP.NET MVC 5 app with user login and authentication, I forgot to make sure that my logged-in users wouldn't be able to access the login form again. So out of curiosity, I decided to test what would happen if I log-in as "USER B" while being logged-in as "User A". The result was that apparently "User A" was logged-out and "User B" got logged-in instead. I emphasize "apparently" because that is what it looks in the front-end, but I'm not sure if the back-end state of the app truly reflects that behavior.
This is my login code (Credits to another StackOverflow post):
[HttpPost]
public ActionResult Login(LoginViewModel login)
{
if (ModelState.IsValid)
{
var userManager = HttpContext.GetOwinContext().GetUserManager<AppUserManager>();
var authManager = HttpContext.GetOwinContext().Authentication;
AppUser user = userManager.Find(login.Email, login.Password);
if (user != null)
{
var ident = userManager.CreateIdentity(user,
DefaultAuthenticationTypes.ApplicationCookie);
authManager.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
return RedirectToAction("Index");
}
}
ModelState.AddModelError("", "Invalid username or password");
return View(login);
}
As you can see, I straight up call the auth.SignIn function without proper validation. What truly happened behind the scenes? Or could someone please recommend me documentation that explains this.

Seeding database with admin user--but he can't log in

I am creating an MVC application and want to seed the database with a single admin user, who will have the ability to create other users. I'm currently doing as follows:
ApplicationUser admin = new ApplicationUser
{
UserName = "whatever",
Email = "whatever#mailinator.com",
EmailConfirmed = true
};
string pwd = "password";
var chkUser = await _userManager.CreateAsync(admin, pwd);
if (chkUser.Succeeded)
{
await _userManager.AddToRoleAsync(admin, Constants.Roles.Administrator);
}
This creates a user in the database, exactly as would be expected. But when I try to login with that user, I fail.
Screenshot of the failure
This is especially puzzling to me, because I use almost the exact same code when users register themselves through the GUI, but there everything is working fine.
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
a bunch of stuff regarding sending a confirmation email
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);'
In both methods, the variable _userManager is of type UserManager<ApplicationUser> and is supplied to my method through dependency injection.
When a user logs in, he is looked up by username. For the users that are created through the GUI, their email address and username are identical. But my "seed" user has a username that is different from his email address. So when he tries to login, the system tries to find a user whose username matches my seed user's email address--and fails.

.NET Core MVC: validate external login without creating account

I'm trying to take advantage of Microsoft.AspNetCore.Authentication.MicrosoftAccount in a .NET Core MVC app as explained here, but I would like to skip the storage layer, so that users are not entered in the database.
What I would like to achieve is: ok, my users are just external Microsoft accounts, I don't do any management of them, I just let them login to the app and check, somehow (a list or whatever) which ones are the allowed ones (like john#boo.com can login, and since his identity is verified by the Microsoft account, well, then he can enter).
What I did was to start with the typical
dotnet new mvc --auth Individual
Them modify it to support Microsoft accounts and that worked.
But, I would like to bypass creating the user in the database, and just log him in. I tried the following:
// GET: /Account/ExternalLoginCallback
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
return View(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
var user = new ApplicationUser { UserName = email, Email = email };
// var result = await _userManager.CreateAsync(user);
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(3, "Microsoft account logged in.");
return RedirectToLocal(returnUrl);
}
But if I don't do the
_userManager.CreateAsync
it fails miserably :-S
So, is there a way to achieve this or what I'm trying simply goes against the Identity principles?
Thanks!
This article show how to use the ASP.NET OAuth providers without ASP.NET Identity, in other words without a DB.

Categories

Resources