Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identity login uses PasswordSignInAsync with Input.Email as username so username and email of account need to be the same #44660

Open
1 task done
erxbout opened this issue Oct 20, 2022 · 14 comments
Labels
area-identity Includes: Identity and providers Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update.

Comments

@erxbout
Copy link

erxbout commented Oct 20, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);

This line above uses the Input.Email for logging in, but the PasswordSignInAsync method expects a username, therefore can not login if the username differs from the email..

Expected Behavior

After using the libraries with default configuration one should be able to login without scaffolding Login.cshtml.cs because this call is used wrongly..

Steps To Reproduce

  • Use libraries with default configuration
  • Add users with username and email (example user: foo, email: foo@test.com)
    Outcome in usertable: username = foo, NormalizedUsername = FOO, email = foo@test.com, NormalizedEmail = FOO@TEST.COM
  • Try to login with email

Exceptions (if any)

No response

.NET Version

6

Anything else?

Possible solutions are (in my opinion, maybe I miss something)

  • Edit PasswordSignInAsync to allow an email as first parameter
  • Edit PasswordSignInAsync to find user by email or by username
  • Use UserManager to select the user by email and pass it to PasswordSignInAsync correctly

Since this would be a small change (at least as far as I can see), I would volunteer to provide a PR, but I need to know which solution would be appreciated ;)

Also I do not know what DotnetVersion I should provide (I am currently using 6 but this bug might affect versions below too)
Have a nice day :D

@javiercn javiercn added the area-identity Includes: Identity and providers label Oct 20, 2022
@blowdart
Copy link
Contributor

The templates assume username and email are the same, if you're veering from that assumption you need to adjust the UI for your own circumstances.

@blowdart blowdart added the Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. label Oct 21, 2022
@ghost
Copy link

ghost commented Oct 21, 2022

Hi @erxbout. We have added the "Needs: Author Feedback" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

@erxbout
Copy link
Author

erxbout commented Oct 22, 2022

Ouh ok, that makes sense

But I also think it would be beneficial if different username/email combinations are possible out of the box..

In my case already have a database filled with user data, and people get access by an administrator.. I used the UserManager to insert a user in identity.AspNetUsers so these people can login (so I created the data not through the register process)
Since the username and email are stored in separated columns my assumption was that email would be used by default if that is what the login clearly requires by default..

After a while some users changed their user data, therefore locked them out of the system (took me some time to find out the username gets normalized during any change in user data)

After many hours of testing scaffolding I saw this line of code, and only this line of code would need the change.. So a lot of additional code generated only for one line to be changed.. To be fair, I could customize my page more now, but it is not very necessary since it works to 98% as I need it to work xD

I mean, now I know where and what I need to do now, but I would very appreciate this behavior out of the box since it is a very common feature amongst internet websites overall to have a username associated to an email (and sometimes even to login with both)..

Anyway, thank you for your time and have a nice day :D

@ghost ghost added Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. and removed Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. labels Oct 22, 2022
@erxbout erxbout changed the title Identity login uses PasswordSignInAsync the wrong way Identity login uses PasswordSignInAsync with Input.Email as username so username and email of account need to be the same Nov 3, 2022
@adityamandaleeka adityamandaleeka added this to the .NET 8 Planning milestone Nov 4, 2022
@ghost
Copy link

ghost commented Nov 4, 2022

Thanks for contacting us.

We're moving this issue to the .NET 8 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@MihaiDaniel
Copy link

This caused some issue for me aswell after I used scaffolding, untill I realised that PasswordSignInAsync actually needs the UserName and not the email. In my opinion this scaffolding is "broken" in a sense, because it should work out of the box, but it does not, so it would be nice to fix it.

@maskedmouse
Copy link

I'm kind of wondering about this as well. There's no point of separating the Username and Email if they're being confused when trying to log in.
SignInManager.PasswordSignInAsync requires the Username.
It would be nice to have this support either Username or Email.

Even with the new .NET 8 Identity Api endpoints I ran into the issue when the Username is not the same as the Email.
Thus failing to use the Login Api as it requests an e-mail as parameter but under the hood uses the Username due to PasswordSignInAsync.
I had to copy paste the new endpoints into my own class and modify them to actually make them work.
Sadly it isn't extendable / configurable as far as I know.

@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@wtgodbe wtgodbe removed the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@dotnet-policy-service dotnet-policy-service bot added the pending-ci-rerun When assigned to a PR indicates that the CI checks should be rerun label Feb 6, 2024
@erxbout
Copy link
Author

erxbout commented Feb 7, 2024

Is there anything I should do? Or is this just an error as this is an issue not a pr? xD

@martincostello
Copy link
Member

#53859

@etriebe
Copy link

etriebe commented Aug 27, 2024

Any update on when this will be fixed? This feels pretty broken for core identity.

@etriebe
Copy link

etriebe commented Sep 19, 2024

Anyone have a recommendation for fixing?

I have a fix in my local GitHub repo of aspnetcore but wondering if an extension method might also work?

Or perhaps creating an entirely new signinmanager? Does anyone have an example of this?

@h1nson
Copy link

h1nson commented Sep 24, 2024

What a rubbish framework.

@etriebe
Copy link

etriebe commented Sep 24, 2024

@h1nson I have a solution without needing to modify anything from Microsoft!

I made BetterSignInManager.cs

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using Pickem.Shared.Account;
using System.Diagnostics.CodeAnalysis;
using System.Security.Claims;
using System.Text;

namespace Microsoft.AspNetCore.Identity;

/// <summary>
/// Provides the APIs for user sign in.
/// </summary>
/// <typeparam name="TUser">The type encapsulating a user.</typeparam>
public class BetterSignInManager : SignInManager<ApplicationUser>
{
    public BetterSignInManager(UserManager<ApplicationUser> userManager, IHttpContextAccessor contextAccessor, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor, ILogger<SignInManager<ApplicationUser>> logger, IAuthenticationSchemeProvider schemes, IUserConfirmation<ApplicationUser> confirmation) : base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger, schemes, confirmation)
    {
    }

    /// <summary>
    /// Attempts to sign in the specified <paramref name="userName"/> and <paramref name="password"/> combination
    /// as an asynchronous operation.
    /// </summary>
    /// <param name="email">The email to sign in.</param>
    /// <param name="password">The password to attempt to sign in with.</param>
    /// <param name="isPersistent">Flag indicating whether the sign-in cookie should persist after the browser is closed.</param>
    /// <param name="lockoutOnFailure">Flag indicating if the user account should be locked if the sign in fails.</param>
    /// <returns>The task object representing the asynchronous operation containing the <see name="SignInResult"/>
    /// for the sign-in attempt.</returns>
    public virtual async Task<SignInResult> PasswordSignInWithEmailOrUserAsync(string email, string password,
        bool isPersistent, bool lockoutOnFailure)
    {
        var user = await UserManager.FindByEmailAsync(email);

        if (user == null)
        {
            user = await UserManager.FindByNameAsync(email);
        }

        if (user == null)
        {
            return SignInResult.Failed;
        }

        return await PasswordSignInAsync(user, password, isPersistent, lockoutOnFailure);
    }
}

And then in Program.cs did the following.

builder.Services.AddIdentityCore<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager<BetterSignInManager>()
    .AddDefaultTokenProviders();

I updated all the references to SignInManager in my solution to BetterSignInmanager and finally in Login.razor I changed which method was being used.

    public async Task LoginUser()
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await BetterSignInManager.PasswordSignInWithEmailOrUserAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            Logger.LogInformation("User logged in.");
            RedirectManager.RedirectTo(ReturnUrl);
        }
        else if (result.RequiresTwoFactor)
        {
            RedirectManager.RedirectTo(
                "Account/LoginWith2fa",
                new() { ["returnUrl"] = ReturnUrl, ["rememberMe"] = Input.RememberMe });
        }
        else if (result.IsLockedOut)
        {
            Logger.LogWarning("User account locked out.");
            RedirectManager.RedirectTo("Account/Lockout");
        }
        else
        {
            errorMessage = "Error: Invalid login attempt.";
        }
    }

And this should fix login for users with a different username from their email! Hope this helps!

@erxbout
Copy link
Author

erxbout commented Sep 25, 2024

Nice approach ;)

I used scaffolding to overwrite the behavior
Still I think it should be fixed in framework but since it has been moved to .net 10 planning there is no prio on that apparently..

@etriebe
Copy link

etriebe commented Sep 25, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-identity Includes: Identity and providers Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update.
Projects
None yet
Development

No branches or pull requests

12 participants