Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation of GetNormalizedUserNameAsync and SetNormalizedUserNameAsync functions in ASP.NET Identity UserStore

I am a bit confused as to how I am supposed to implement functions like the following:

GetNormalizedRoleNameAsync(TRole, CancellationToken)
SetNormalizedRoleNameAsync(TRole, String, CancellationToken)
GetNormalizedUserNameAsync(TUser, CancellationToken)
SetNormalizedUserNameAsync(TUser, String, CancellationToken)
GetUserNameAsync(TUser, CancellationToken)
SetUserNameAsync(TUser, String, CancellationToken)

In the ASP.NET Core CustomIdentityProvider Sample and the Actual ASP.NET Core Identity UserStoreBase class they do the following:

public Task SetNormalizedUserNameAsync(ApplicationUser user, string normalizedName, CancellationToken cancellationToken)
{
    cancellationToken.ThrowIfCancellationRequested();
    if (user == null) throw new ArgumentNullException(nameof(user));
    if (normalizedName == null) throw new ArgumentNullException(nameof(normalizedName));

    user.NormalizedUserName = normalizedName;
    return Task.FromResult<object>(null);
}

public Task<string> GetUserNameAsync(ApplicationUser user, CancellationToken cancellationToken)
{
    cancellationToken.ThrowIfCancellationRequested();
    if (user == null) throw new ArgumentNullException(nameof(user));

    return Task.FromResult(user.UserName);
}

Are these functions about just simply extracting the Normalized Name from an already populated User object and additionally updating the Normalized Name on an already populated User object. I am not seeing the purpose of these functions can someone explain?

Also do I need to actually persist the NormalizedUserName and NormalizedRoleName in my custom User/Role tables or are they not required?

like image 377
Blake Rivell Avatar asked Jul 27 '17 02:07

Blake Rivell


People also ask

What is Userstore?

The user store or the identity store is a repository of user accounts and credentials. ArcGIS Server connects to the user store to authenticate a user requesting access to a resource.

What is AspNet identity?

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.

What is IdentityDbContext?

IdentityDbContext() Initializes a new instance of the IdentityDbContext class. IdentityDbContext(DbContextOptions) Initializes a new instance of IdentityDbContext.


1 Answers

The answer can be found in the way the UserManager and RoleManager lookup users / roles. Since they both work similarly, I'll focus on the UserManager.

When calling UserManager.FindByNameAsync, the UserManager first normalize the key before passing it to your UserStore:

public virtual async Task<TUser> FindByNameAsync(string userName)
{
    userName = NormalizeKey(userName);
    var user = await Store.FindByNameAsync(userName, CancellationToken);
    return user;    
}

where

// injected via dependency injection
ILookupNormalizer keyNormalizer; 

public virtual string NormalizeKey(string key)
{
    return (KeyNormalizer == null) ? key : KeyNormalizer.Normalize(key);
}

The goal is probably to ensure that no matter the input, the DB request always uses a consistent key.

Note that Identity framework actually uses UpperInvariantLookupNormalizer by default (via IdentityServiceCollectionExtensions.AddIdentity<TUser, TRole>).

That means that when you implement IUserStore<User>.FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken), normalizedUserName is not the string you passed to the UserManager method, but its upper case version.

So to finally answer your questions:

  • GetNormalizedUserNameAsync isn't used anywhere in the Identity framework.
  • SetNormalizedUserNameAsync is used during creation / update of a user, and is called with the upper case version of your user name. You don't need to persist it, but it might be preferable, since the User lookup is based on the normalized version.
  • GetUserNameAsync the string that will be normalized before calling GetNormalizedUserNameAsync. Not used anywhere else in the Identity framework.

Final note: you can change the ILookupNormalizer by adding a scoped service before calling AddIdentity:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
    services
        .AddIdentity<User, Role>()
        .AddUserStore<MyUserStore>()
        .AddRoleStore<MyRoleStore>();
}
like image 107
Métoule Avatar answered Oct 08 '22 19:10

Métoule