Random Musings

June 2, 2009

ASP.NET 2.0 Membership – Resetting password without using question and answer

Filed under: Uncategorized — haditeo @ 8:52 pm

By default the ASP.NET PasswordRecovery control utilizes user’s question and answer to send back the password.

The current best practice now is sending a reset password link to the user’s email address. User’s might forget what is the question and answer, he/she provided when he/she creates the user account.

To customize this PasswordRecovery control, i have created a table let’s called PasswordRequest table with these fields :
1) Id. The purpose of this id is the primary key of this table. In this field, i stores a unique GUID to identify each records
2) RequestDate. The purpose of this field is to store when the request is logged by the user. Because the link that i will send to user, will be expired after certain times, let’s say 10 minutes. After the link is expired, user must request another password request link again
3) UserId. The purpose of this field is to store who is the user that requests the password reset

Whenever the user requests a password reset, it will invoke these codes :

        protected void PasswordRecovery1_SendingMail(object sender, MailMessageEventArgs e)
        {           
            string userName = PasswordRecovery1.UserName;
            MembershipUserCollection userColl = Membership.FindUsersByEmail(userName);

            foreach (MembershipUser user in userColl)
            {
                ResetPasswordRepository repo = new ResetPasswordRepository(Utilities.Utilities.RetrieveSqlConnString());
                Guid recordId = repo.Create(user.ProviderUserKey.ToString(), DateTime.Now);

                e.Message.Body = e.Message.Body + "\r\n http://localhost:8012/ForgotPassword.aspx?action=reset&id=" + recordId.ToString();                
            }
        }

The above codes is invoked at the point before the mail is sent, so that we can alter the message body to include the record id.

These codes are utilized to insert a record into the PasswordRequest table

        public Guid Create(string userId, DateTime requestDate)
        {
            try
            {
                using (TransactionScope tx = new TransactionScope())
                {
                    using (connection)
                    {
                        Guid id = Guid.NewGuid();

                        string strCommand = "INSERT INTO PasswordRequest(Id, RequestDate, UserId, IsActive) VALUES('" + id.ToString() + "', '" + requestDate.ToString() + "', '" + userId.ToString() + "', '0')";

                        SqlCommand command = new SqlCommand(strCommand, connection);

                        command.Connection.Open();
                        int numberOfRecordCreated = command.ExecuteNonQuery();

                        if (numberOfRecordCreated != 1)
                        {
                            throw new NoPasswordRequestRecordIsCreatedException("Fail to create a password recovery request record");
                        }

                        tx.Complete();

                        return id;
                    }
                }
            }
            catch (TransactionAbortedException trxExc)
            {
                throw trxExc;
            }
            catch (Exception exc)
            {

                throw exc;
            }
            finally
            {
                connection.Close();
            }
        }

After user’s click the link in the email and visit the page, we need to verify the request so that it’s indeed the actual user who requests the password reset and not somebody else

       protected void btnReset_Click(object sender, EventArgs e)
       {
            string recordId = Request["id"];

            ResetPasswordRepository repo = new ResetPasswordRepository(Utilities.Utilities.RetrieveSqlConnString());
            ResetPassword record = repo.RetrieveByRecordId(recordId);

            if (record.Id == null)
            {
                lblErrorMessage.Text = "The request has been expired. Please request another password reset email";
            }
            else
            {
                string tempPassword = record.MembershipUser.ResetPassword();
                record.MembershipUser.ChangePassword(tempPassword, txtPassword.Text);
            }
       }

I performed a check first by checking whether the record is exist in the PasswordRequest table. After that i invoked ResetPassword() method to get the temporary password. Finally i invoked ChangePassword() method to change the old password, to new password.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: