dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.2k stars 9.93k forks source link

ASP.NET Core identity UI requests email but uses username #11786

Closed weitzhandler closed 5 years ago

weitzhandler commented 5 years ago

Describe the bug

Hi folks,

I'm setting up the identity as follows:

services
        .AddDefaultIdentity<Tenant>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<CatalogDbContext>();

Then in the OnModelCreating I'm initializing a user like this:

builder.Entity<Tenant>(t =>
  {
    var tenant = new Tenant { ... }
    var hasher = new PasswordHasher<Tenant>();
    tenant.PasswordHash = hasher.HashPassword(tenant, "mypass");
    t.HasData(tenant);
  });

When I go to the login page and try to login with the provided email/password, I get an error "Invalid login attempt". Why is that?

I tried using a custom sign-in manager, and I see that the public override Task<SignInResult> PasswordSignInAsync(string userName, string password, bool isPersistent, bool lockoutOnFailure) overload is called, but the argument for userName is the email. Typing in a username in the identity UI causes a client-side validation error.

Expected behavior

The identity UI should ask for username instead of email

Screenshots

image

image

Additional context

P.S. I'm using IdentityServer in my project, but in a different scheme.

Include the output of dotnet --info: https://gist.github.com/weitzhandler/f3287c91722ec442d645b6320405c774

weitzhandler commented 5 years ago

I notice something weird:

public override async Task<SignInResult> PasswordSignInAsync(
  string userName, string password, bool isPersistent, bool lockoutOnFailure)
{
  userName = userName.Split("@")[0];
  //val gets the user I'm after
  var val = await UserManager.Users.SingleOrDefaultAsync(u => u.UserName == userName);
  //val2 remains null!
  var val2 = await UserManager.FindByNameAsync(userName);

  if (val == null)
  {
    return SignInResult.Failed;
  }
  return await PasswordSignInAsync(val, password, isPersistent, lockoutOnFailure);
}
enetstudio commented 5 years ago

The identity UI should ask for username instead of email

As far as I know, username and email are interchangeable. In other words, username is the email. The field username in the database is filled with the email data.

blowdart commented 5 years ago

By default in the templates username and password are synchronized. If you want to move away from this expectation you need to adjust the UI according to your needs.

weitzhandler commented 5 years ago

Something ain't right, that's for sure. Either display username field, or use email for user retrieval. You can't ask for an email and check the username field for it, that makes no sense.

blowdart commented 5 years ago

We're away it's not ideal, and in 3..0 the templates get a little overhaul, so we consider if solved in 3.0