Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Forgot your password help

Posted on 2012-08-31
9
Medium Priority
?
550 Views
Last Modified: 2012-09-06
Hello Experts,

I have an application that I need to give users the ability to reset their password. So far I have a process that works half way. Please see what I have below along with code. My question(s) is I need help with encrypting/decrypting the usersid when they recieve an email. I don't want the user to be able to reset anyone elses password by guessing another usersid.

Step 1: User needs to enter his/her username and email address. If correct an email will be sent with a link to the user.

Step 2: User recieves link and will need to click on the link and they will be prompted to enter a new password. This is the step that I'm having trouble with. I would like the usersid to be encrypted in the email. When the user clicks on the link I would like to be able to retrievce his/her userid and store it in a HiddenField and have it decrypted at that point. Then user can enter new password to have it reset.

Also, please note that when I enter the actual usersid into the querystring it does not retrieve the users information.

Forgot Password CodeBehind:

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Net.Mail;
using System.Net.NetworkInformation;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;

public partial class application_forgotpassword : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        lblForgotPasswordError.Visible = false;
    }

    protected void SendForgotPasswordEmail()
    {
        SmtpClient smtpClient = new SmtpClient();
        MailMessage message = new MailMessage();

        MailAddress fromAddress = new MailAddress("no-reply@domain.org", "Reporting System");
        MailAddress toAddress = new MailAddress(HttpUtility.HtmlEncode(txtWorkEmail.Text));

        message.From = fromAddress;
        message.To.Add(toAddress);

        string EMPURL = "<span style=\"font-size: 14px; color: #0c9b19; font-family: Arial\"><font face='arial' color='#666666'>" + "Click <a href='http://application/resetpassword.aspx?emp_id=" + hf_emp_id.Value + "'>here </a>to reset your password.";

        message.Subject = "Reset your Password";
        message.IsBodyHtml = true;
        message.Body = "<html><head><title>" + "</title></head><body>" + "<p>" + "<span style=\"font-size: 16px; color: #0c9b19; font-family: Arial\"><b>Forgot your password?</b><font face='arial' color='#666666'>" + "<br /><br />" + EMPURL + "<span style=\"font-size: 12px; font-style: italic; color: #de1919; font-family: Arial\"><br />" + "<span style=\"font-size: 14px; font-style: italic; color: #de1919; font-family: Arial\"><br /><br />" + "** Passwords are secure. Please make sure that you remember your password or store it in a safe place. **" + "</body></html>";

        smtpClient.Host = "mail.domain.org";
        smtpClient.Send(message);
    }

    protected void btn_forgotpassword_Click(object sender, EventArgs e)
    {
        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["WellnessTracker"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "RetrieveForgottenPassword";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            cmd.Parameters.Add("@emp_username", SqlDbType.VarChar, 50).Value = txtUserName.Text;
            cmd.Parameters.Add("@emp_email", SqlDbType.VarChar, 100).Value = txtWorkEmail.Text;

            try
            {
                conn.Open();

                SqlDataReader rdr = cmd.ExecuteReader();

                if (rdr.Read())
                {
                    hf_emp_id.Value = EncryptDecryptQueryString.EncodeTo64(rdr["emp_id"].ToString());

                    SendForgotPasswordEmail();
                    Response.Redirect("forgotpasswordsuccess.aspx");
                }
                else
                {
                    lblForgotPasswordError.Text = "We are unable to locate your account.";
                }
            }

            catch (Exception ex)
            {
                lblForgotPasswordError.Text = ex.Message.ToString();
            }
        }
    }
}

Open in new window


EncryptDecryptQueryString Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Security.Cryptography;

/// <summary>
/// Summary description for EncryptDecryptQueryString
/// </summary>
public class EncryptDecryptQueryString
{
    public static string EncodeTo64(string toEncode)
    {
        byte[] toEncodeAsBytes = System.Text.Encoding.Unicode.GetBytes(toEncode);
        string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

        return returnValue;
    }

    /// <summary>
    /// The method to Decode your Base64 strings.
    /// </summary>
    /// <param name="encodedData">The String containing the characters to decode.</param>
    /// <returns>A String containing the results of decoding the specified sequence of bytes.</returns>
    public static string DecodeFrom64(string encodedData)
    {
        byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
        string returnValue = System.Text.Encoding.Unicode.GetString(encodedDataAsBytes);

        return returnValue;
    } 
}

Open in new window


RetrieveForgottenPassword Stored Procedure:


ALTER PROCEDURE [dbo].[RetrieveForgottenPassword]

(
@emp_username varchar(50),
@emp_email varchar(100)
)

AS 

SELECT emp_id, emp_username, emp_email
FROM Employees
WHERE emp_username = @emp_username AND emp_email = @emp_email

Open in new window


Reset Password CodeBehind:

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Net.Mail;
using System.Net.NetworkInformation;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Cryptography;

public partial class application_resetpassword : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        RetrieveEmployeeIDFullName();
        lblResetPasswordError.Visible = false;
    }

    protected void RetrieveEmployeeIDFullName()
    {
        string empid = EncryptDecryptQueryString.DecodeFrom64(Request.QueryString["emp_id"].ToString());

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["WellnessTracker"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "RetrieveEmployeeFirstLastName";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            cmd.Parameters.Add("@emp_id", SqlDbType.Int).Value = empid;

            try
            {
                conn.Open();

                SqlDataReader rdr = cmd.ExecuteReader();

                if (rdr.Read())
                {
                    hf_emp_id.Value = rdr["emp_id"].ToString();
                    lblUsersFullName.Text = rdr["emp_firstname"].ToString();
                }
            }

            catch (Exception ex)
            {
                ex.Message.ToString();
            }
        }
    }

    protected void btn_ResetPassword_Click(object sender, EventArgs e)
    {
        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["WellnessTracker"].ConnectionString))
        {
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = "UpdateEmployeesPassword";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn;

            cmd.Parameters.Add("@emp_id", SqlDbType.Int).Value = hf_emp_id.Value;
            cmd.Parameters.Add("@emp_password", SqlDbType.Binary, 96).Value = PasswordHash.HashPassword(txtPassword.Text);

            try
            {
                conn.Open();
                cmd.ExecuteNonQuery();

                Response.Redirect("resetpassword.aspx");
            }

            catch (Exception ex)
            {
                lblResetPasswordError.Text = ex.Message.ToString();
            }
        }
    }
}

Open in new window


Reset Password Stored Procedures:

ALTER PROCEDURE [dbo].[RetrieveEmployeeFirstLastName]

(
@emp_id int
)

AS 

SELECT emp_id, emp_firstname, emp_lastname
FROM dbo.Employees
WHERE emp_id = @emp_id

Open in new window

0
Comment
Question by:asp_net2
  • 5
  • 4
9 Comments
 
LVL 18

Expert Comment

by:Rajar Ahmed
ID: 38354631
As you explained so many things [i think its a complete process ]  its difficult to follow where your lost / having issue . Better tell, where we need to look at it ?
However, There is no need of hidden field assignment, just encrypt/decrypt assign it on varaible use it accordingly
    string  encUserId = yourEncrptLogic(username.text);
          string mailBody ="<a href="resetPage.aspx?ssid="+encUserId>Reset Password</a>";

Open in new window

   string decUserID = yourDecryptLogic(Request.QueryString["ssid"]);
            //pass this to update your password 

Open in new window

Meeran03
0
 
LVL 4

Author Comment

by:asp_net2
ID: 38354787
So I don't need to use a hiddenfield on either page of those pages or code?
0
 
LVL 18

Expert Comment

by:Rajar Ahmed
ID: 38354823
Yes, As you can
  1.Retrieve username from textbox itself while encrypting.
  2.Retrieve username from querystring  itself while decrypting

So, there is no need of hidden field .
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 4

Author Comment

by:asp_net2
ID: 38354878
What did you think about the encryption/decryption that I'm using. Actually I think it only encodes/decodes.

Do you know of a more secure or better approach?
0
 
LVL 18

Expert Comment

by:Rajar Ahmed
ID: 38355505
0
 
LVL 4

Author Comment

by:asp_net2
ID: 38355585
Thanks, which algorithim do you suggest for a more secure site?
0
 
LVL 18

Accepted Solution

by:
Rajar Ahmed earned 2000 total points
ID: 38355679
AES is more secure i prefer AES .

You can take decision , by carefully studying these discsussion .
1.http://stackoverflow.com/questions/5554526/comparison-of-des-triple-des-aes-blowfish-encryption-for-data
2.https://www.cpug.org/forums/ipsec-vpn-blade-virtual-private-networks/49-difference-between-3des-aes.html
3.http://blogs.msdn.com/b/ace_team/archive/2007/09/07/aes-vs-3des-block-ciphers.aspx

Also google more Like,
AES or 3des  which  is better
AES or des which  is better
and so on.....


Meeran03
0
 
LVL 4

Author Comment

by:asp_net2
ID: 38357177
Hi meeran03,

Ok, what algorithim do you suggest is better for hashing? That is how I store my passwords now. I can upload the code I'm using to show you if  you like if you wouldn't mind looking at it.
0
 
LVL 18

Expert Comment

by:Rajar Ahmed
ID: 38357271
hi asp_net2,

 what algorithim do you suggest is better for hashing?
  1. SHA256
   2. SHA1
 
  Using SALT on either of your hashing algorithm will give more security .

http://stackoverflow.com/questions/1756188/how-to-use-sha1-or-md5-in-cwhich-one-is-better-in-performance-and-security-fo 


I can upload the code..
   Yes,  i wouldnt mind if that was another thread lol . As it varies more than to  the original question asked .

Meeran03
0

Featured Post

NEW Veeam Agent for Microsoft Windows

Backup and recover physical and cloud-based servers and workstations, as well as endpoint devices that belong to remote users. Avoid downtime and data loss quickly and easily for Windows-based physical or public cloud-based workloads!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
This video shows how to quickly and easily deploy an email signature for all users in Office 365 and prevent it from being added to replies and forwards. (the resulting signature is applied on the server level in Exchange Online) The email signat…
Loops Section Overview
Suggested Courses
Course of the Month15 days, 2 hours left to enroll

578 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question