diff --git a/src/Identity/Extensions.Core/src/IdentityErrorDescriber.cs b/src/Identity/Extensions.Core/src/IdentityErrorDescriber.cs
index 919ea59f4288..7e8787551146 100644
--- a/src/Identity/Extensions.Core/src/IdentityErrorDescriber.cs
+++ b/src/Identity/Extensions.Core/src/IdentityErrorDescriber.cs
@@ -95,13 +95,14 @@ public virtual IdentityError LoginAlreadyAssociated()
/// Returns an indicating the specified user is invalid.
///
/// The user name that is invalid.
+ /// The characters that are allowed in the username.
/// An indicating the specified user is invalid.
- public virtual IdentityError InvalidUserName(string? userName)
+ public virtual IdentityError InvalidUserName(string? userName, string? allowedUsernameCharacters)
{
return new IdentityError
{
Code = nameof(InvalidUserName),
- Description = Resources.FormatInvalidUserName(userName)
+ Description = Resources.FormatInvalidUserName(userName, allowedUsernameCharacters)
};
}
diff --git a/src/Identity/Extensions.Core/src/PublicAPI.Shipped.txt b/src/Identity/Extensions.Core/src/PublicAPI.Shipped.txt
index b30ce145ace6..6b99eef2de8c 100644
--- a/src/Identity/Extensions.Core/src/PublicAPI.Shipped.txt
+++ b/src/Identity/Extensions.Core/src/PublicAPI.Shipped.txt
@@ -387,7 +387,7 @@ virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.DuplicateUserName(s
virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.InvalidEmail(string? email) -> Microsoft.AspNetCore.Identity.IdentityError!
virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.InvalidRoleName(string? role) -> Microsoft.AspNetCore.Identity.IdentityError!
virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.InvalidToken() -> Microsoft.AspNetCore.Identity.IdentityError!
-virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.InvalidUserName(string? userName) -> Microsoft.AspNetCore.Identity.IdentityError!
+virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.InvalidUserName(string? userName, string? allowedUsernameCharacters) -> Microsoft.AspNetCore.Identity.IdentityError!
virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.LoginAlreadyAssociated() -> Microsoft.AspNetCore.Identity.IdentityError!
virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.PasswordMismatch() -> Microsoft.AspNetCore.Identity.IdentityError!
virtual Microsoft.AspNetCore.Identity.IdentityErrorDescriber.PasswordRequiresDigit() -> Microsoft.AspNetCore.Identity.IdentityError!
diff --git a/src/Identity/Extensions.Core/src/Resources.resx b/src/Identity/Extensions.Core/src/Resources.resx
index fe35a8b7868a..46406e5db842 100644
--- a/src/Identity/Extensions.Core/src/Resources.resx
+++ b/src/Identity/Extensions.Core/src/Resources.resx
@@ -1,17 +1,17 @@
-
+
-
@@ -162,8 +162,8 @@
Error when a token is not recognized
- Username '{0}' is invalid, can only contain letters or digits.
- User names can only contain letters or digits
+ Username '{0}' is invalid, can only contain the following characters '{1}'.
+ User names can only contain characters defined in 'AllowedUsernameCharacters'. By default these are 'a-Z0-9._@+-'
A user with this login already exists.
diff --git a/src/Identity/Extensions.Core/src/UserValidator.cs b/src/Identity/Extensions.Core/src/UserValidator.cs
index cf530106a663..1bbb9d2b3262 100644
--- a/src/Identity/Extensions.Core/src/UserValidator.cs
+++ b/src/Identity/Extensions.Core/src/UserValidator.cs
@@ -56,13 +56,13 @@ public virtual async Task ValidateAsync(UserManager manag
if (string.IsNullOrWhiteSpace(userName))
{
errors ??= new List();
- errors.Add(Describer.InvalidUserName(userName));
+ errors.Add(Describer.InvalidUserName(userName, manager.Options.User.AllowedUserNameCharacters));
}
else if (!string.IsNullOrEmpty(manager.Options.User.AllowedUserNameCharacters) &&
userName.Any(c => !manager.Options.User.AllowedUserNameCharacters.Contains(c)))
{
errors ??= new List();
- errors.Add(Describer.InvalidUserName(userName));
+ errors.Add(Describer.InvalidUserName(userName, manager.Options.User.AllowedUserNameCharacters));
}
else
{
diff --git a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs
index 933dad56f92c..8ac99f5979f2 100644
--- a/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs
+++ b/src/Identity/Specification.Tests/src/UserManagerSpecificationTests.cs
@@ -248,7 +248,7 @@ public async Task CheckSetUserNameValidatesUser()
var newUser = CreateTestUser(username, useNamePrefixAsUserName: true);
IdentityResultAssert.IsSuccess(await manager.CreateAsync(newUser));
- var error = _errorDescriber.InvalidUserName("");
+ var error = _errorDescriber.InvalidUserName("", manager.Options.User.AllowedUserNameCharacters);
IdentityResultAssert.IsFailure(await manager.SetUserNameAsync(newUser, ""), error);
IdentityResultAssert.VerifyLogMessage(manager.Logger, $"User validation failed: {error.Code}.");
diff --git a/src/Identity/test/Identity.Test/UserValidatorTest.cs b/src/Identity/test/Identity.Test/UserValidatorTest.cs
index 30bbfd8b6a55..04d355beb778 100644
--- a/src/Identity/test/Identity.Test/UserValidatorTest.cs
+++ b/src/Identity/test/Identity.Test/UserValidatorTest.cs
@@ -32,7 +32,7 @@ public async Task ValidateFailsWithTooShortUserNames(string input)
var result = await validator.ValidateAsync(manager, user);
// Assert
- IdentityResultAssert.IsFailure(result, new IdentityErrorDescriber().InvalidUserName(input));
+ IdentityResultAssert.IsFailure(result, new IdentityErrorDescriber().InvalidUserName(input, manager.Options.User.AllowedUserNameCharacters));
}
[Theory]