Explanation of GetNormalizedUserNameAsync and SetNormalizedUserNameAsync Functions in ASP.NET Identity UserStore
I'm a little confused about how I should implement features like:
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 UserStoreBase class for the ASP.NET base identity, 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 just extracting the normalized name from the already populated user object and additionally updating the normalized name on the already populated user object. I don't see the purpose of these functions can someone explain?
Also do I need to actually store NormalizedUserName and NormalizedRoleName in my User / Role tables, or are they not required?
source to share
The answer can be found in the way to find users and roles UserManager
and RoleManager
. Since they both work in the same way, I'll focus on UserManager
.
When called, first normalizes the key before passing it to : UserManager.FindByNameAsync
UserManager
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 to ensure that regardless of input, the DB query always uses the agreed upon key.
Please note: the UpperInvariantLookupNormalizer
default structure uses UpperInvariantLookupNormalizer
(via ). IdentityServiceCollectionExtensions.AddIdentity<TUser, TRole>
This means, when implemented, IUserStore<User>.FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
normalizedUserName
it is not a string passed to the method UserManager
, but an uppercase version.
To finally answer your questions:
-
GetNormalizedUserNameAsync
not used anywhere in the Identity framework. -
SetNormalizedUserNameAsync
used during user creation / update and invoked with the uppercase version of your username. You don't need to insist on this, but it may be preferable since the user's search is based on the normalized version. -
GetUserNameAsync
- the string to be normalized before callingGetNormalizedUserNameAsync
. Not used anywhere in the Identity framework.
Final note: you can change ILookupNormalizer
by adding a service from AddIdentity
before calling AddIdentity
:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
services
.AddIdentity<User, Role>()
.AddUserStore<MyUserStore>()
.AddRoleStore<MyRoleStore>();
}
source to share