Identity - forcing the Normalized Email & Username to lower case

David Thielen 3,211 Reputation points
2023-06-16T23:30:16.38+00:00

This is really weird.

I call the following (in a unit test hence the calling async methods as sync):

			var identityUser = new IdentityUser(email)
			{
				Email = email,
				PhoneNumber = phone
			};
			identityUser.NormalizedEmail = identityUser.Email.Normalize().ToUpperInvariant();
			identityUser.NormalizedUserName = identityUser.UserName?.Normalize().ToUpperInvariant();
			// activate user
			identityUser.EmailConfirmed = true;
			identityUser.PhoneNumberConfirmed = true;
			identityUser.LockoutEnabled = false;

			var result = _store.SetUserNameAsync(identityUser, identityUser.Email, CancellationToken.None);
			result.Wait();
			if (!result.IsCompletedSuccessfully)
				throw new Exception($"Failed to create username {identityUser.UserName}: {result.Exception?.Message}");
			var identityCreateResult = _userManager.CreateAsync(identityUser, password).Result;
			if (!identityCreateResult.Succeeded)
				throw new Exception($"Failed to create user {identityUser.UserName}: {identityCreateResult.Errors.First().Description}");

And on exit from _userManager.CreateAsync(identityUser, password) the NormalizedEmail and NormalizedUserName in identityUser are now lowercase. And in the database they are lower case.

Ok, so I then "fix" it with the following:

			identityUser = identityContext.Users.First(x => x.Id == identityUser.Id);
			identityUser.NormalizedEmail = identityUser.Email.ToUpperInvariant();
			identityUser.NormalizedUserName = identityUser.UserName?.ToUpperInvariant();
			// activate user
			identityUser.EmailConfirmed = true;
			identityUser.PhoneNumberConfirmed = true;
			identityUser.LockoutEnabled = false;
			identityContext.SaveChanges();

And now the identityUser object and the database has them in upper case until I call the following:

			var claim = new Claim("Manager", "_states");
			_ = _userManager.AddClaimAsync(identityUser, claim).Result;

On exit from _userManager.AddClaimAsync(identityUser, claim).Result both the identityUser object and the database now have them as lower case.

What in the world is going on here? All the documentation says the Normalized properties are the regular property with Normalize().ToUpperInvariant() applied to them. This makes no sense.

More details:

			var optionsIdentityBuilder = new DbContextOptionsBuilder<UserDbContext>();
			optionsIdentityBuilder.UseSqlServer(identityConnectionString);
			using var dbIdentityContext = new UserDbContext(optionsIdentityBuilder.Options);

			_store = new UserStore<IdentityUser>(dbIdentityContext);
			_userManager = new UserManager<IdentityUser>(_store, null!, new PasswordHasher<IdentityUser>(), 
				null!, null!, null!, null!, null!, null!);

And after calling the above I looked at _userManager.KeyNormalizer and it has a value of null. So I added the following line (h/t @Viorel ):

_userManager.KeyNormalizer = new UpperInvariantLookupNormalizer();

And now it works.

So that fixes it. But it does leave the follow on question - should that be the default setting?

thanks - dave

Developer technologies | ASP.NET | ASP.NET Core
{count} votes

Accepted answer
  1. Viorel 122.9K Reputation points
    2023-06-17T05:28:32.3966667+00:00

    What is _userManager? Maybe you should set or clear its KeyNormalizer.

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.