ASP.NET Identity Password Validation - asp.net-mvc

I am using Identity in my MVC project, and it's all well and nice. Except the fact that the form for registering a new user has some crazy password requirements
Passwords must have at least one non letter or digit character. Passwords must have at least one digit ('0'-'9'). Passwords must have at least one uppercase ('A'-'Z').
And here is the register model
public class RegisterViewModel
{
[Required]
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[StringLength(50, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 2)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Passord")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Repeat Password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
Account Controller
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
I see the length requirement for the password, but I don't understand how to change the password validation so I don't need a non letter or digit character.
All help greatly appreciated, thank you.
Bonus: What does the {0} and {2} mean? Thank you.

In Startup.cs where you add the Identity Service you can add options for password validation:
services.AddIdentity<ApplicationUser, IdentityRole>(Configuration,
options =>
options.Password = new PasswordOptions
{
RequireDigit = true,
RequiredLength = 6,
RequireLowercase = true,
RequireUppercase = true,
RequireNonLetterOrDigit = false
})
[...];

If you are using one of the ASP.NET template applications and have selected Authentication as 'Individual User Accounts' you will find the password options in a IdentityConfig.cs file in the App_Start folder in your application. Here you can change the password options as follows to turn off all requirements except the password length:
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};

Related

How to change default error messages of MVC Core ValidationSummary?

Using MVC Core with ASP.NET Identity I would like to change the defaults error messages of ValidationSummary that arrived from Register action.
Any advice will be much appreciated.
You should override methods of IdentityErrorDescriber to change identity error messages.
public class YourIdentityErrorDescriber : IdentityErrorDescriber
{
public override IdentityError PasswordRequiresUpper()
{
return new IdentityError
{
Code = nameof(PasswordRequiresUpper),
Description = "<your error message>"
};
}
//... other methods
}
In Startup.cs set IdentityErrorDescriber
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddErrorDescriber<YourIdentityErrorDescriber>();
}
The answer is from https://stackoverflow.com/a/38199890/5426333
You can use DataAnnotations in your RegisterViewModel class. In fact if you scaffold your application with authentication, you will get something like this:
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
Obviously, you can change ErrorMessage to anything you want it to be!

How to Configure validation logic for passwords in mvc?

I have created a new MVC project (default MVC5 Individual User Accounts template) and I have made changes to IdenitityConfig.cs
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 1,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = false,
RequireUppercase = false,
};
But still while registration it gives an error "The Password must be at least 6 characters long."
But I have changed length to 1.
Its not passing the viewmodel validation.
public class RegisterViewModel
{
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
//[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
If you remove this line [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)], you will not have this issue.

UserManager.CreateAsync() requires a complex password

I'm designing a register form and using ajax to send data to server.
My model:
public class RegisterViewModel
{
[Required]
public string Name { get; set; }
[Required]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
[Compare("Password")]
public string ConfirmPassword { get; set; }
}
and the action:
[HttpPost]
[AllowAnonymous]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// do stuff...
}
}
}
My problem: result.Succeeded returned false with error message (Password is helloworld):
Passwords must have at least one non letter or digit character.
Passwords must have at least one digit ('0'-'9'). Passwords must have
at least one uppercase ('A'-'Z').
As you can see above, I didn't set any regular expression to Password and ConfirmPassword. So why was I getting that?
Looks like you're using Identity. In the IdentityConfig.cs, there's a section where you configure the requirements for password. Look for this section:
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};

'...DataType' does not contain a definition for 'Email'

I'm using Identity, and the IdentityUsers properties are the next: https://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.entityframework.identityuser_properties%28v=vs.108%29.aspx
Well, the problem is I have in the AspNetUsers table "Email" and "PasswordHash", but appears the error'System.ComponentModel.DataAnnotations.DataType' does not contain a definition for 'Email' and 'PasswordHash')
if I put "Datatype.Email" instead of "DataType.EmailAddress" and "DataType.PasswordHash" instead of "DataTtype.Password".
public class RegisterViewModel
{
[Required]
[DataType(DataType.Email)]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The password must have at least {2} characters long.", MinimumLength = 6)]
[DataType(DataType.PasswordHash)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.PasswordHash)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "Different passwords.")]
public string ConfirmPassword { get; set; }
}
The error is telling you exactly what you need. DataType is an enumeration which only allows specific values. These in turn are used for validation in the MVC world to ensure that you have a valid EmailAddress in the field, whatever it happens to be called.
[DataType(DataType.Email)] // Not Valid
[DataType(DataType.EmailAddress)] // Valid
[DataType(DataType.PasswordHash)] // Not Valid
[DataType(DataType.Password)] // Valid
For the full list of valid values, see Intellisense or this URL:
https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.datatype%28v=vs.110%29.aspx

ModelState.IsValid is true if password is empty string

I am passing login model to mvc4 default login method
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
if (ModelState.IsValid && _webSecurity.login(model))
{
return RedirectToLocal(returnUrl);
}
// If we got this far, something failed, redisplay form
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
My Model looks like following
var _loginModel = new LoginModel
{
UserName = abc#gmail.com,
Password = ""
};
but ModelState.IsValid is returning true . I don't know why . Help me
Thanks in advance .
Edit
Here is my LoginModel
public class LoginModel
{
[Required]
[Display(Name = "User name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
The validation Attribute defined in the model will be apllied while Model Binding, u don't have to do this manualy.
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.",MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
For more complex validation you also could add a regex filter like this:
[RegularExpression(#"^[^\<\>]*$", ErrorMessage = "May not contain <,>")]
This would match windows group policy password filter for example:
(?=^.{6,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*

Resources