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]