Brian
asked on
Password Policy's
Hello Experts,
I would like to have a password policy for users stored passwords. I have all users passwords Salted + Hashed along with a Secret Salt thanks to a friend from EE who helped me out with that. I would like to take it one step further though. I would like to have the current users in my DB to have their password need to be reset/changed every 90 days. I don't know what method would be best to handle this task. I could use the email address that is stored with their profile to send them an email to reset their password before 90 days but not sure how I would use a date to go by.
I would like to have a password policy for users stored passwords. I have all users passwords Salted + Hashed along with a Secret Salt thanks to a friend from EE who helped me out with that. I would like to take it one step further though. I would like to have the current users in my DB to have their password need to be reset/changed every 90 days. I don't know what method would be best to handle this task. I could use the email address that is stored with their profile to send them an email to reset their password before 90 days but not sure how I would use a date to go by.
I can think of this simplest approach:
-Add one column 'LastPasswordChangeDate' and whenever user changes password update it with that current datetime.
-Then you have Password change date with you for each user, now you can achieve password reset/change in two different methods:
1) you need to check 'LastPasswordChangeDate' and compare with current date to determine password change days are 90 or more and display appropriate message to user for that at the time of login.
2) you can run a piece of code everyday to determine list of users whose password change days are 90 or more and send them emails / reset their password accordingly.
-Add one column 'LastPasswordChangeDate' and whenever user changes password update it with that current datetime.
-Then you have Password change date with you for each user, now you can achieve password reset/change in two different methods:
1) you need to check 'LastPasswordChangeDate' and compare with current date to determine password change days are 90 or more and display appropriate message to user for that at the time of login.
2) you can run a piece of code everyday to determine list of users whose password change days are 90 or more and send them emails / reset their password accordingly.
To setupt he expiry days for passwowrd
Group Policy > User Settings > Security Settings > Account Policies > Password Policy > Maximum Password Age
To setup the password policy here as you like...
Computer Configuration\Windows Settings\Local Policies\Security Options under Interactive Logon: Prompt user to change password before expiration
WHen evern users logon, if the password is going to expire, windows automatically alert the user to change their password...
Group Policy > User Settings > Security Settings > Account Policies > Password Policy > Maximum Password Age
To setup the password policy here as you like...
Computer Configuration\Windows Settings\Local Policies\Security Options under Interactive Logon: Prompt user to change password before expiration
WHen evern users logon, if the password is going to expire, windows automatically alert the user to change their password...
Frosty555 has suggested similar approach. I would like to add one more thing, you can set public constant in common library to access Password Change Days (i.e. 90 or 30) this way you will have to change only one value at one place or you can store this in sql table also.
@Murali1984
This question is of asp.net web application users' password policy and not of Windows OS.
This question is of asp.net web application users' password policy and not of Windows OS.
ASKER
@Frosty555 and gery128:
Should I start by adding a field in my DB called "users_password_date"? Then everytime the password gets changed then I update that field using the SQL getDate() function in SQL?
Also, when I signup users should I use the getDate() function in SQL to set the Date that the user row was created?
Also, should I have code in Page_Load that checks the User when he/she logs in against Today's Date and the value for users_password_date?
What I don't understand is how I can lock the appication down until user changes his/her password if it goes past 90 days.
Should I start by adding a field in my DB called "users_password_date"? Then everytime the password gets changed then I update that field using the SQL getDate() function in SQL?
Also, when I signup users should I use the getDate() function in SQL to set the Date that the user row was created?
Also, should I have code in Page_Load that checks the User when he/she logs in against Today's Date and the value for users_password_date?
What I don't understand is how I can lock the appication down until user changes his/her password if it goes past 90 days.
The field name may differ according to programmer: you can create one like "users_password_date" or "change_password_date" it depends on you. Yes, you need to update this field each time user changes password.
You can use getDate() function to insert the date in user row for field say "user_registration_date" (example)
Ideally, you should check if user's password is older than 90 days and do not authenticate user(i.e. by creating auth cookie/ticket in formsauthenctication or using windows authentication), instead redirect them to the Change Password page on login. So you only need to place this check on login event. Not on every page.
If you implement above check, then user would be redirected to "Change Password" page automatically, so he won't be able to log on to system until he changes his password.
You can use getDate() function to insert the date in user row for field say "user_registration_date" (example)
Ideally, you should check if user's password is older than 90 days and do not authenticate user(i.e. by creating auth cookie/ticket in formsauthenctication or using windows authentication), instead redirect them to the Change Password page on login. So you only need to place this check on login event. Not on every page.
If you implement above check, then user would be redirected to "Change Password" page automatically, so he won't be able to log on to system until he changes his password.
Hello asp_net2, I have made this class for your, this will help you to check the complexity required in your passwords, copy the PasswordPolicy class to a new file in your App_Code folder:
How to use? before you save a new password for an user, example:
And about password expiring policy's I recommend to follow Frosty555 recommendations (comment 37062738), but remember that your hash is saved as bytes, so the table structure that he recommend must be like:
public static class PasswordPolicy
{
// Settings
const int MinRequiredPasswordLength = 7;
const bool MinRequiredAtLeastOneLetter = true;
const bool MinRequiredAtLeastOneDigit = true;
const int MinRequiredNonAlphanumericCharacters = 0;// <-- If you set it to one or more can be anoying for some users, but it will increase the password security.
public static void CheckPassword(string password)
{
// Check length
if (string.IsNullOrEmpty(password) || password.Length < MinRequiredPasswordLength)
throw new PasswordPolicyException("The password is too short, must be at least " + MinRequiredPasswordLength + " characters long.");
int letterCount = 0;
int digitCount = 0;
int nonAlphanumericCharacterCount = 0;
foreach (char c in password)
{
if (char.IsLetter(c))
letterCount++;
if (char.IsDigit(c))
digitCount++;
if (!char.IsLetterOrDigit(c))
nonAlphanumericCharacterCount++;
}
// Check if at least a letter is required
if (MinRequiredAtLeastOneLetter && letterCount == 0)
throw new PasswordPolicyException("The password must contain at least one letter.");
// Check if at least a digit is required
if (MinRequiredAtLeastOneDigit && digitCount == 0)
throw new PasswordPolicyException("The password must contain at least one decimal digit.");
// Check if special characters are required (everything that is not a letter or digit)
if (nonAlphanumericCharacterCount < MinRequiredNonAlphanumericCharacters)
throw new PasswordPolicyException("The password must contain at least " + MinRequiredNonAlphanumericCharacters + " special character.");
}
public class PasswordPolicyException : Exception
{
public PasswordPolicyException() { }
public PasswordPolicyException(string message) : base(message) { }
}
}
The code above can also be accomplished with regular expressions but I have made it in this way to make it easy to understand for you.How to use? before you save a new password for an user, example:
try
{
PasswordPolicy.CheckPassword(TextBoxMyPassword.Text);
}
catch (PasswordPolicy.PasswordPolicyException ex)
{
// Display this error to your user
MyLabel.Text = ex.Message;
return; //<-- Important
}
... Here code that save the new password to your DB....
And about password expiring policy's I recommend to follow Frosty555 recommendations (comment 37062738), but remember that your hash is saved as bytes, so the table structure that he recommend must be like:
PasswordHistory
UserId int
DateChanged datetime
PasswordHash binary(96)
ASKER
Hi yv989c,
Thanks for replying. I'm a little confused of course. Is the first code snippet above that you posted for Checking the Password strenght itself only? If so, do I need to tie that in to my creation of a new user? I was planning on using regular expressions using AJAX to control the password strength but I also like your solution as well.
Also, I'm not sure if this is oky to do but I added another field in my table called "users_password_date" which is tied to SQL (getDate()) function. So if a user would change his/her password then it would change the users_password_date to the current data it was changed without user adding the date.
Also, I don't understand Frosty555's method but I do like gery128 method in post 37069710.
Thanks for replying. I'm a little confused of course. Is the first code snippet above that you posted for Checking the Password strenght itself only? If so, do I need to tie that in to my creation of a new user? I was planning on using regular expressions using AJAX to control the password strength but I also like your solution as well.
Also, I'm not sure if this is oky to do but I added another field in my table called "users_password_date" which is tied to SQL (getDate()) function. So if a user would change his/her password then it would change the users_password_date to the current data it was changed without user adding the date.
Also, I don't understand Frosty555's method but I do like gery128 method in post 37069710.
ASKER
@gery128,
I like your method from post 37069710. However, I'm not sure how I would check against the date in the DB to current date using FormsAuthentication. Can you be a little more specific since I don't understand?
I had alot of help from yv989c in regards to Salt + Hash my password and then authenticate against that so I'm a little confused how I would use your method for FormsAuthentication to the code below that i'm using for authentication.
private bool IsValidPassword(string userName, string password)
{
byte[] correctHash = null;
using (SqlConnection conn = new SqlConnection(Configuratio nManager.C onnectionS trings["He althCourse s"].Connec tionString ))
{
SqlCommand cm = new SqlCommand("[dbo].[HealthC ourses_Get UserPasswo rd]", conn);
cm.CommandType = CommandType.StoredProcedur e;
cm.Parameters.Add("@users_ username", SqlDbType.VarChar, 50).Value = userName;
conn.Open();
correctHash = cm.ExecuteScalar() as byte[];
}
if (correctHash == null)
{
// User not found.
return false;
}
else
{
return PasswordHash.ValidatePassw ord(passwo rd, correctHash);
}
}
protected void btn_ProgramInfoLogIn_Click (object sender, EventArgs e)
{
if (IsValidPassword(txtUserNa me.Text, txtPassword.Text))
{
Session["UserNameSessionID "] = txtUserName.Text;
FormsAuthentication.Redire ctFromLogi nPage(txtU serName.Te xt, false);
}
else
{
lblLogInError.Text = "Invalid Credentials!";
}
}
I like your method from post 37069710. However, I'm not sure how I would check against the date in the DB to current date using FormsAuthentication. Can you be a little more specific since I don't understand?
I had alot of help from yv989c in regards to Salt + Hash my password and then authenticate against that so I'm a little confused how I would use your method for FormsAuthentication to the code below that i'm using for authentication.
private bool IsValidPassword(string userName, string password)
{
byte[] correctHash = null;
using (SqlConnection conn = new SqlConnection(Configuratio
{
SqlCommand cm = new SqlCommand("[dbo].[HealthC
cm.CommandType = CommandType.StoredProcedur
cm.Parameters.Add("@users_
conn.Open();
correctHash = cm.ExecuteScalar() as byte[];
}
if (correctHash == null)
{
// User not found.
return false;
}
else
{
return PasswordHash.ValidatePassw
}
}
protected void btn_ProgramInfoLogIn_Click
{
if (IsValidPassword(txtUserNa
{
Session["UserNameSessionID
FormsAuthentication.Redire
}
else
{
lblLogInError.Text = "Invalid Credentials!";
}
}
You may need to change IsValidPassword method or introduce new method for CheckPasswordExpiry check.
Your login method may look like this:
Your login method may look like this:
protected void btn_ProgramInfoLogIn_Click(object sender, EventArgs e)
{
if (IsValidPassword(txtUserName.Text, txtPassword.Text))
{
if(CheckPasswordExpiry(txtUserName.Text))
{
//Password expired, do not authenticate user. just redirect to password change page
Response.Redirect("ChangePasswordPage.aspx");
}
else
{
Session["UserNameSessionID"] = txtUserName.Text;
FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);
}
}
else
{
lblLogInError.Text = "Invalid Credentials!";
}
}
private bool CheckPasswordExpiry(string userName)
{
//Check password expiry with userName against user_password_change field in your table
If ( passwordIsMoreThan90DaysOld) //implement your logic to check user password is older than 90 days.
return true; //its expired
else
return false;
}
Hello asp_net2:
Thanks for replying. I'm a little confused of course. Is the first code snippet above that you posted for Checking the Password strenght itself only? If so, do I need to tie that in to my creation of a new user? I was planning on using regular expressions using AJAX to control the password strength but I also like your solution as well.Yes, wherever you save the user password you must check it to be sure that it is secure enough, is simple, just use this code before you reach your DB saving method (of course replace the control names with the correct ones):
try
{
PasswordPolicy.CheckPassword(TextBoxMyPassword.Text);
}
catch (PasswordPolicy.PasswordPolicyException ex)
{
// Display this error to your user
MyLabel.Text = ex.Message;
return; //<-- Important
}
Dont rely only in javascript validations, that can be easily bypassed, you always must check your validations on the server side.I'm not sure what you mean with this, but if you are talking about a default column value it only works for inserts not updates.
Also, I'm not sure if this is oky to do but I added another field in my table called "users_password_date" which is tied to SQL (getDate()) function. So if a user would change his/her password then it would change the users_password_date to the current data it was changed without user adding the date.
Also, I don't understand Frosty555's method but I do like gery128 method in post 37069710.Frosty555 suggestion is good because will can control that an user don't use the same password twice in a sort time period. The simplest thing that you can do without that implementation is to check that the new password is not like the current one.
ASKER
@ gery128:
Is there anyway you can show me how to compare the two dates in the CheckPasswordExpiry Event Handler. I would need to compare the current date with the data stord in the DB labeld users_password_date.
Is there anyway you can show me how to compare the two dates in the CheckPasswordExpiry Event Handler. I would need to compare the current date with the data stord in the DB labeld users_password_date.
ASKER
@yv989c,
Thank you yv989c, I understand what you are saying now. I think the only think left now is to compare the two dates, current data and date stored in DB labeled users_password_date and to if the data is older than 90 days and if it is redirect to ChangePassword page.
Thank you yv989c, I understand what you are saying now. I think the only think left now is to compare the two dates, current data and date stored in DB labeled users_password_date and to if the data is older than 90 days and if it is redirect to ChangePassword page.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
And remember, all the users must have access to your ChangePassword.aspx page, so your web.config must have these entry:
<location path="ChangePassword.aspx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
@asp_net2
I think, yv989c's suggested changes in SP will give you an idea about how to compare the two dates for password expiry check.
I think, yv989c's suggested changes in SP will give you an idea about how to compare the two dates for password expiry check.
ASKER
Is there a way to do the two date checks in code instead of SQL?
ya, certainly,
DateTime changePasswordDate = new DateTime(2011, 09, 11); //here I am using it for just testing. you //should fetch value from database in changePasswordDate variable from filed users_password_change field
if (changePasswordDate.AddDays(90) > DateTime.Today)
{
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi yv989c and gery128,
I'm very sorry that I have been away from this post. I got caught into trying to learn how to Encrypt / Decrypt Data in my DB (Not Hashing) and I have been beating my head on that. I'm going to close this post and award the points but before I do if either of you two can help me with another post in regards to Encrypting / Decrypting data then I would REALLY appreciate it. I'm trying to go by the books example, the book is called "Pro ASP.NET 4.0 using C# 2010" by APress and I'm able to get the data to Encrypt but not able to Decrypt. Anyway let me know if either of you two could help, below is the link to that post.
https://www.experts-exchange.com/questions/27452720/Encrypt-Decrypt-using-Rigndael-Algorithm.html
I'm very sorry that I have been away from this post. I got caught into trying to learn how to Encrypt / Decrypt Data in my DB (Not Hashing) and I have been beating my head on that. I'm going to close this post and award the points but before I do if either of you two can help me with another post in regards to Encrypting / Decrypting data then I would REALLY appreciate it. I'm trying to go by the books example, the book is called "Pro ASP.NET 4.0 using C# 2010" by APress and I'm able to get the data to Encrypt but not able to Decrypt. Anyway let me know if either of you two could help, below is the link to that post.
https://www.experts-exchange.com/questions/27452720/Encrypt-Decrypt-using-Rigndael-Algorithm.html
ASKER
Thank you both very much for all your help!!!
If you want to futureproof this design, you can have a separate "password change history" table which stores all of the user's passwords, schema something like this:
PASSWORDHISTORY
char passwordmd5hash
datetime datechanged
int userid
By adding to this table every time the user changes their password, you can maintain a history of passwords and prevent the user from changing their password back to something they used in the past. You can also authenticate the user by testing against the most recent password in the table for that user.