Tuesday, 5 July 2011

Sending reset password link for one time use only in asp.net


Introduction: Hello developers, in this article i will explain that how we can create and send reset password link that will use onle one time in asp.net,after one time use this link will dispose and say that this link is wrong. This is very helpful article for every .net developer

Implementation: Create two pages named forgetpassword.aspx and reset.aspx. Paste the code that below am giving, separately inside the both pages. This is a sample program you can change it accoring to your requirement. Inside your table there will be a colimn named code is necessary.
Code for forgetpassword.aspx page:
<head runat="server">
    <title>Forget Password</title>
    <style type="text/css">
        .style1
        {
            width: 100%;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
   
       &nbsp;&nbsp;
      
        <br />
        <br />
        <br />
       
   
        <table class="style1">
            <tr>
                <td>
                     Enter email id</td>
                <td>
                    <asp:TextBox ID="txt_email" runat="server"></asp:TextBox>
        <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"
            ControlToValidate="txt_email" ErrorMessage="Enter Valid Email address"
            ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"></asp:RegularExpressionValidator></td>
            </tr>
            <tr>
                <td colspan="2">
                   
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                    OR&nbsp;</td>
            </tr>
            <tr>
                <td>
                    Enter username</td>
                <td>
                    <asp:TextBox ID="txt_uname" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td>
                    &nbsp;</td>
                <td>
        <asp:Button ID="btn_send" runat="server" onclick="btn_send_Click" Text="Send" />
       
   
                </td>
            </tr>
            <tr>
                <td>
                    &nbsp;</td>
                <td>
        <asp:Label ID="lbl_msg" runat="server"></asp:Label>
                </td>
            </tr>
            <tr>
                <td>
                    &nbsp;</td>
                <td>
                    &nbsp;</td>
            </tr>
        </table>
       
   
    </div>
    </form>
</body>
Code for forgetpassword.aspx.cs page:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;
using System.Text;

public partial class forgetpassword : System.Web.UI.Page
{
    SqlCommand cmd;
    DataTable dt;
    SqlConnection con = new SqlConnection();
    SqlDataAdapter adp;

    protected void Page_Load(object sender, EventArgs e)
    {
        con = new SqlConnection();
        con.ConnectionString = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;
        con.Open();
        if (con.State == ConnectionState.Closed)
        {
            con.Open();
        }

    }
    protected void btn_send_Click(object sender, EventArgs e)
    {
        if (con.State == ConnectionState.Closed)
        { con.Open(); }
        try
        {
            // here in SqlDataAdapter i am executing sql query if after the execution of this query there will be any data inside the datatable then
            // execute the else condition. otherwise it enter in the if condition and display message "Enter valid email address or uname".
            // in the below query i am checking uname and email address entered by the user with the values inside the database
            adp = new SqlDataAdapter("select uname,email from tb_employee_with_code where email=@email or uname=@uname", con);
            //here a i am passing parameter named email from the txt_email.Text's value
            adp.SelectCommand.Parameters.AddWithValue("@email", txt_email.Text);
            //here a i am passing parameter named uname from the txt_uname.Text's value
            adp.SelectCommand.Parameters.AddWithValue("@uname", txt_uname.Text);
         
            dt = new DataTable();
            adp.Fill(dt);
            if (dt.Rows.Count == 0)
            {
                lbl_msg.Text = "Enter valid email address or uname";
                txt_email.Text = "";
                txt_uname.Text = "";
                return;
            }
            else
            {
                // if the values entered by the user will be correct then this code will execute.
                // below inside the code variable i am catching the autogenerated value which will different evertime.
                string code;
                code = Guid.NewGuid().ToString();
                // and am updating the code column of the table with this value. i mean inside the code column i'll store the value
                // that was inside the code variable
                cmd = new SqlCommand("update tb_employee_with_code set code=@code where  email=@email or uname=@uname", con);
                cmd.Parameters.AddWithValue("@code",code);
                cmd.Parameters.AddWithValue("@email", txt_email.Text);
                cmd.Parameters.AddWithValue("@uname", txt_uname.Text);
                // here i am difinning a StringBuilder class named sbody
                StringBuilder sbody = new StringBuilder();
                // here i am sendind a image as logo with the path http://usingaspdotnet.blogspot.com
                sbody.Append("<a href=http://usingaspdotnet.blogspot.com><img src=http://a1.twimg.com/profile_images/1427057726/asp_image.jpg/></a></br>");
                // here i am sending a link to the user's mail address with the three values email,code,uname
                // these three values i am sending  this link with the values using querystring method.
                sbody.Append("<a href=http://usingasp.net/reset_pwd.aspx?email=" + txt_email.Text);
                sbody.Append("&code=" + code + "&uname=" + txt_uname.Text + ">Click here to change your password</a>");
                //in the below line i am sending mail with the link to the user.
                //in this line i am passing four parameters 1st sender's mail address ,2nd receiever mail address, 3rd Subject,4th sbody.ToString() there will be complete link
                // inside the sbody
                System.Net.Mail.MailMessage mail = new System.Net.Mail.MailMessage("sender’s email address", dt.Rows[0]["email"].ToString(), "Reset Your Password", sbody.ToString());
                mail.CC.Add("any other email address if u want for cc");
                //in the below  i am declaring the receiever email address and password
                System.Net.NetworkCredential mailAuthenticaion = new System.Net.NetworkCredential("sender’s email address ", "password");
                // in the below  i am declaring the smtp address of gmail and port number of the gmail
                System.Net.Mail.SmtpClient mailclient = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
                mailclient.EnableSsl = true;
                mailclient.Credentials = mailAuthenticaion;
                // here am setting the property IsBodyHtml true because i am using html tags inside the mail's code
                mail.IsBodyHtml = true;
                mailclient.Send(mail);
                cmd.ExecuteNonQuery();
                cmd.Dispose();
                con.Close();
                lbl_msg.Text = "Link has been sent to your email address";
                txt_email.Text = "";
                txt_uname.Text = "";
               

            }
        }
        catch(Exception ex)
        {
            // if there will be any error created at the time of the sending mail then it goes inside the catch
            //and display the error in the label
            lbl_msg.Text = ex.Message;
        }
        finally
        {
            con.Close();
        }
    }
}

Code for reset.aspx page:
<head runat="server">
    <title>Change Your Password</title>
    <style type="text/css">
        .style1
        {
            width: 100%;
        }
        .style2
        {
            width: 180px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Panel ID="Pane_image" runat="server" Visible="false">
        <%--here you can set image according to your requirement--%>
        <img src="images.jpg" alt="" />
        </asp:Panel>
        <asp:Panel ID="Panel_reset_pwd" runat="server" Visible="false">
            <table class="style1">
                <tr>
                    <td class="style2">
                        Enter Your New Password:</td>
                    <td>
                        <asp:TextBox ID="txt_pwd" runat="server" TextMode="Password"></asp:TextBox>
                        <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
                            ControlToValidate="txt_pwd" ErrorMessage="Reqiired"></asp:RequiredFieldValidator>
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                        Retype Password</td>
                    <td>
                        <asp:TextBox ID="txt_retype_pwd" runat="server" TextMode="Password"></asp:TextBox>
                        <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
                            ControlToValidate="txt_retype_pwd" ErrorMessage="Required"></asp:RequiredFieldValidator>
                        <asp:CompareValidator ID="CompareValidator1" runat="server"
                            ControlToCompare="txt_pwd" ControlToValidate="txt_retype_pwd"
                            ErrorMessage="Enter Same Password"></asp:CompareValidator>
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                        &nbsp;</td>
                    <td>
                        <asp:Button ID="btn_change_pwd" runat="server" onclick="btn_change_pwd_Click"
                            Text="Change Password" />
                    </td>
                </tr>
                <tr>
                    <td class="style2">
                       </td>
                    <td>
                        <asp:Label ID="lbl_msg" runat="server"></asp:Label>
                    </td>
                </tr>
            </table>
       
        </asp:Panel>
    </div>
    </form>
</body>
Code for reset.aspx.cs page:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Data.SqlClient;
using System.Text;

public partial class reset_pwd : System.Web.UI.Page
{
    SqlCommand cmd;
    DataTable dt;
    SqlConnection con = new SqlConnection();
    SqlDataAdapter adp;

    protected void Page_Load(object sender, EventArgs e)
    {
        //with the help of the last page a link will be sent to the user's email address. the user can use this link only
        //one time to change his/her password
        con = new SqlConnection();
        //  here i am declairing connection  with the database
        con.ConnectionString = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;
        con.Open();
        if (con.State == ConnectionState.Closed)
        {
            con.Open();
        }
        // at the .aspx i am creating two panels. inside the second panel am holding a image named images.jpg that will show thae there is a invalid link,if
        // any user use this link second time.
        //if any user use this link first time then he will see the design that will show the structure of change password
        try
        {
            // here in SqlDataAdapter i am executing sql query if after the execution of this query there will be any data inside the datatable then
            // it will go inside the else condition otherwise it will go inside the if
            adp = new SqlDataAdapter("select uname,email,code from tb_employee_with_code where code=@code and(email=@email or uname=@uname )", con);
            adp.SelectCommand.Parameters.AddWithValue("@code", Request.QueryString["code"].ToString());
            adp.SelectCommand.Parameters.AddWithValue("@email", Request.QueryString["email"].ToString());
            adp.SelectCommand.Parameters.AddWithValue("@uname", Request.QueryString["uname"].ToString());

            dt = new DataTable();
            adp.Fill(dt);
            if (dt.Rows.Count == 0)
            {
                //if this condition will be setisfy then Pane_image will true and  Panel_reset_pwd will false

                Pane_image.Visible = true;
                Panel_reset_pwd.Visible = false;

                return;
            }
            else
            {
                //if this condition will be setisfy then Pane_image will be false and  Panel_reset_pwd will be true
                Pane_image.Visible = false;
                Panel_reset_pwd.Visible = true;

}
        }
        catch
        {

        }
        finally
        {

        }
}
    protected void btn_change_pwd_Click(object sender, EventArgs e)
    {
        //if the else condition will be setisfy then   Panel_reset_pwd will be true and after entering the new password by the user,
        //this code will be executed
         if (con.State == ConnectionState.Closed)
        { con.Open(); }
         try
           
         {
             // in the below quesry, after changing the password by the user, i am clearing the code column's value from the table tb_employee_with_code
             // if there will be no value inside the code column of the table and user will try to open the link again then at the time of
             //page load the user goes inside the first panel
             // and the first panel dislay message thar this link is invalid
             cmd = new SqlCommand("update tb_employee_with_code set code='',pwd=@pwd where   code=@code  and (email=@email or uname=@uname)", con);
             cmd.Parameters.AddWithValue("@pwd", txt_pwd.Text);
           
             cmd.Parameters.AddWithValue("@code", Request.QueryString["code"].ToString());
             cmd.Parameters.AddWithValue("@email", Request.QueryString["email"].ToString());
             cmd.Parameters.AddWithValue("@uname", Request.QueryString["uname"].ToString());
          
             cmd.ExecuteNonQuery();
             cmd.Dispose();
             con.Close();
             lbl_msg.Text = "Your Password has been Changed successfully";
             txt_pwd.Text = "";
             txt_retype_pwd.Text = "";

         }
         catch
         {

         }
         finally
         {
             con.Close();
         }
       
    }
}
Sql Script for database:
/****** Object:  Table [dbo].[tb_employee_with_code]    Script Date: 07/05/2011 14:02:35 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tb_employee_with_code]') AND type in (N'U'))
DROP TABLE [dbo].[tb_employee_with_code]
GO
/****** Object:  Table [dbo].[tb_employee_with_code]    Script Date: 07/05/2011 14:02:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[tb_employee_with_code]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[tb_employee_with_code](
      [id] [bigint] NOT NULL,
      [ename] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      [eadd] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      [code] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      [email] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      [uname] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
      [pwd] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
 CONSTRAINT [PK_tb_employee_with_code] PRIMARY KEY CLUSTERED
(
      [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON)
)
END
GO
INSERT [dbo].[tb_employee_with_code] ([id], [ename], [eadd], [code], [email], [uname], [pwd]) VALUES (1, N'bharat', N'#123`', N'', N'bharti222000@yahoo.com', N'1234', N'espranza')

 Conclusion
Through this article, you have learned how to create and send create and send reset password link that will use onle one time in asp.net

22 comments:

  1. i work with asp.net + c# + access
    and want to write code for forgeting password/username, and mail them to users.
    pls help.
    tnx

    ReplyDelete
    Replies
    1. If you are looking for this code..i have ready code which i was implemented in one of my project..mail me ur requirements and details to sathish.siri.1985@gmail.com

      Delete
    2. Hey Send me the code.........

      Delete
  2. Can u please send me the code ... I implemented forget and reset password according to your article but i am getting error - "The specified string is not in the form required for an e-mail address."

    ReplyDelete
    Replies
    1. please check your email address,that is not correct or if u are using email account than stop the step2 verification than and than you only access this program...!

      Delete
    2. what do you mean by step2 verification?

      Delete
  3. Hi!! Sindhu Krothapalli. Have any value available in the main table from where you are sending the email for the forget password?

    ReplyDelete
  4. hi.. can i check this code in localhost....!When i ma trying in localhost it's provide error,

    ReplyDelete
  5. Hi I am an amateur and I have cpanel user accounts. I have the mail working with afterlogic lite. I have given users random passwords and I want to send a one time password change link to all the email acounts. Please help. ohm.patel1@gmail.com

    ReplyDelete
  6. HIE THIS IS TANMAY I WAN TO GENERATE OTP AT FIRST TIME LOGING PLEASE HELP ME FOR THAT
    my id is nehete.tanmay@gmail.com

    ReplyDelete
    Replies
    1. Hello Nehete,

      How are you? i an giving you an idea to create the logic for the creation of the otp. create two columns named status_otp and otp in your table. when user click the button for the creation for the otp then generate a randon password and set the status as enable in your database and then send the otp email or sms to the user at the same time. After this when user type the received created OTP and check the typed otp with the value that is store inside the database, if the user enter correct OTP then redirect the user inside your portal and update or set the status column for the particular user as disable. you can also delete the entry from the database if you want, then you need to delete the particular entry when user enter the correct generated password, for the user.

      You can use the below function to generate the alphanumeric OTP
      string value;
      value = CreateRandomPassword(8);
      public static string CreateRandomPassword(int PasswordLength)
      {
      string _allowedChars = "
      0123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ";
      Random randNum = new Random();
      char[] chars = new char[PasswordLength];
      int allowedCharCount = _allowedChars.Length;
      for (int i = 0; i < PasswordLength; i++)
      {
      chars[i] = _allowedChars[(int)((_allowedChars.Length) * randNum.NextDouble())];
      }
      return new string(chars);
      }
      Thanks
      Using asp.net

      Delete
  7. yes i am also getting the same error The specified string is not in the form required for an e-mail address.
    ...

    ReplyDelete
  8. Hi,

    I want the same code which i need to include in my project.

    My mail Id:naren595@gmail.com

    Thank you,

    Narender Reddy

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  9. This is a great approach, but i think it would be improved. For example I used this code with Membership and i figured that maybe some columns are useless. For those who are seeking a better solution, these are my recomendations:

    1. Use one datetime column to store the date of the password reset request, adding this you can validate the expiration of the link (hours, days, etc) and the frequency of requests.
    2. Do not use messages that contains information about the existence of user data, this way if someone is trying to attack your app, he can easyly get a list of valid usernames and user emails.
    3. Do not use the unique identifier or username inside the reset link, this is a bad practice because you are providing user data as mentioned earlier, instead use the code guid and validate with additional data.

    Thank you for the example and I hope somebody find my advices helpful.

    ReplyDelete
  10. i have the same error The specified string is not in the form required for an e-mail address.

    ReplyDelete
  11. Awesome post& Thank you for giving best information . i like it & I'll help you. please visit this website Gmail Technical Support and Call +1-800-231-4635 USA (Toll Free).

    ReplyDelete
  12. can u send me the code to naresh451989@gmail.com

    ReplyDelete
  13. hello can u provide me the source code for implementing otp for password resetting.please provide me the link for that section.send me the link on my email address "tanaychaudhary9@gmail.com"

    ReplyDelete
  14. Hi can you send me this working project? send me through my email awesomejcjx@gmail.com. Thanks in advance :)

    ReplyDelete