Adding security question/answer check to ASP.NET *ChangePassword* control

Discussion in 'ASP .Net' started by Ken Fine, Aug 15, 2008.

  1. Ken Fine

    Ken Fine Guest

    I want to add the security question and answer security feature to the
    ChangePassword control. I am aware that this functionality is built into the
    PasswordRecovery tool. I have implemented the PasswordRecovery with a
    Password reset required; a temporary password is sent to the account on
    file. I want an extra layer of security to accommodate the very unlikely
    contingency that someone's e-mail account is compromised. Challenging with
    the user's security question and answer will address this contingency.

    Put another way, this is the setup I want:
    1) User requests password reset
    2) email is sent with temp password
    3) user's/username's Membership info is evaluated, if comment ==
    "UserResetPasswordMustChange" user is sent to password change form
    4) User changes password using an augmented ChangePassword control that
    evaluates an answer against the user's security question on file.

    I have completed items 1-3.

    I have extended other login controls by exposing the templates, playing
    around with FindControl, and writing functions on the OnWhatever events, so
    I am familiar with the basic concepts involved in extending the
    functionality of these things.

    In the case of a ChangePassword control I imagine I will want to inspect the
    answer to the security question on file during the
    ChangePassword1_ChangingPassword event and e.Cancel it in the event that the
    answer is incorrect.

    I don't know how exactly to do this comparison, especially since the answers
    to the security questions are hashed. Somehow in code I would need to do a
    comparison of the cryptographic "fingerprints" of the user's input vs. the
    hashed answer on file.

    Any help out there? Somewhere someone has written a tutorial on how to do
    all of the above, I'm sure, but even a few snips of code would probably set
    me on my way.

    Thanks!
     
    Ken Fine, Aug 15, 2008
    #1
    1. Advertisements

  2. Hi Ken,

    From your description you want to get the security answer in the
    ChangingPassword event handler of ChangePassword control. You're using
    ASP.NET membership, the provider is
    System.Web.Security.SqlMembershipProvider and the passwordFormat is Hashed,
    which is the default setting. If my understanding is wrong please correct
    me.

    If so it's not that easy to retrieve the password answer. If you want to do
    so I suggest you to write a custom provider. You can refer to the source
    code of System.Web.Security.SqlMembershipProvider. In its ResetPassword
    method it calls base.EncodePassword to encode the password answer and then
    call a stored procedure aspnet_Membership_ResetPassword to reset the
    password. You can encode the password answer in the same way and compare it
    with the password answer stored in the database.

    The above workaround is a bit complex. Here I would suggest you to use a
    tricky one:

    <asp:ChangePassword DisplayUserName="true" ID="ChangePassword1"
    runat="server"
    onchangingpassword="ChangePassword1_ChangingPassword">
    <ChangePasswordTemplate>
    <table border="0" cellpadding="4">
    <tr>
    <td>
    <table border="0" cellpadding="0"
    style="font-family: Verdana;">
    <tr>
    <td align="center" colspan="2"
    style="color: White;
    background-color: #1C5E55;

    font-weight: bold;">
    Change Your Password</td>
    </tr>
    <tr>
    <td align="center" colspan="2"
    style="color: Black;
    font-style: italic;">
    Enter your username and old
    password.
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label
    AssociatedControlID="UserName"
    ID="UserNameLabel" runat="server">
    User Name:</asp:Label>
    </td>
    <td>
    <asp:TextBox ID="UserName"
    runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator
    ControlToValidate="UserName"
    ErrorMessage="User Name is
    required."
    ID="UserNameRequired"
    runat="server"
    ToolTip="User Name is
    required."

    ValidationGroup="ChangePassword1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label

    AssociatedControlID="CurrentPassword"
    ID="CurrentPasswordLabel"

    runat="server">Password:</asp:Label>
    </td>
    <td>
    <asp:TextBox ID="CurrentPassword"
    runat="server"
    TextMode="Password">
    </asp:TextBox>
    <asp:RequiredFieldValidator

    ControlToValidate="CurrentPassword"
    ErrorMessage="Password is
    required."
    ID="CurrentPasswordRequired"
    runat="server"
    ToolTip="Password is required."

    ValidationGroup="ChangePassword1">*</asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label
    AssociatedControlID="NewPassword"
    ID="NewPasswordLabel"
    runat="server">New Password:
    </asp:Label></td>
    <td>
    <asp:TextBox ID="NewPassword"
    runat="server"
    TextMode="Password">
    </asp:TextBox>
    <asp:RequiredFieldValidator
    ControlToValidate="NewPassword"
    ErrorMessage="New Password is
    required."
    ID="NewPasswordRequired"
    runat="server"
    ToolTip="New Password is
    required."

    ValidationGroup="ChangePassword1">*
    </asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="right">
    <asp:Label

    AssociatedControlID="ConfirmNewPassword"
    ID="ConfirmNewPasswordLabel"
    runat="server">Confirm New
    Password:
    </asp:Label>
    </td>
    <td>
    <asp:TextBox
    ID="ConfirmNewPassword"
    runat="server"
    TextMode="Password">
    </asp:TextBox>
    <asp:RequiredFieldValidator

    ControlToValidate="ConfirmNewPassword"
    ErrorMessage="Confirm New
    Password is required."
    ID="ConfirmNewPasswordRequired"
    runat="server"
    ToolTip="Confirm New Password is
    required."

    ValidationGroup="ChangePassword1">*
    </asp:RequiredFieldValidator>
    </td>
    </tr>
    <tr>
    <td align="center" colspan="2">
    <asp:CompareValidator
    ControlToCompare="NewPassword"

    ControlToValidate="ConfirmNewPassword"
    Display="Dynamic"
    ErrorMessage="The confirm New
    Password must match the New Password entry."
    ID="NewPasswordCompare"
    runat="server"

    ValidationGroup="ChangePassword1">
    </asp:CompareValidator>
    </td>
    </tr>
    <tr>
    <td align="center" colspan="2"
    style="color: Red;">
    <asp:Literal
    EnableViewState="False"
    ID="FailureText" runat="server">
    </asp:Literal>
    </td>
    </tr>
    <tr>
    <td>
    Question:<asp:Label ID="Label1"
    runat="server" Text="question"
    onload="Label1_Load"></asp:Label>
    <br />
    Answer: <asp:TextBox ID="PasswordAnswer"
    runat="server"></asp:TextBox>
    <asp:CompareValidator
    ID="CompareValidator1" runat="server"
    ControlToValidate="PasswordAnswer"
    ErrorMessage="Please input the answer!"></asp:CompareValidator>
    <br />
    </td></tr>
    <tr>
    <td align="right">
    <asp:Button BackColor="White"
    BorderColor="#C5BBAF"
    BorderStyle="Solid"
    BorderWidth="1px"
    CommandName="ChangePassword"
    Font-Names="Verdana"
    ForeColor="#1C5E55"
    ID="ChangePasswordPushButton"
    runat="server"
    Text="Change Password"

    ValidationGroup="ChangePassword1" />
    </td>
    <td>
    <asp:Button BackColor="White"
    BorderColor="#C5BBAF"
    BorderStyle="Solid"
    BorderWidth="1px"
    CausesValidation="False"
    CommandName="Cancel"
    Font-Names="Verdana"
    ForeColor="#1C5E55"
    ID="CancelPushButton"
    runat="server"
    Text="Cancel" />
    </td>
    </tr>

    </table>
    </td>
    </tr>
    </table>



    </ChangePasswordTemplate>
    </asp:ChangePassword>

    protected void ChangePassword1_ChangingPassword(object sender,
    LoginCancelEventArgs e)
    {

    ChangePassword cp=sender as ChangePassword;
    TextBox newpassword= cp.Controls[0].FindControl("NewPassword") as
    TextBox;
    TextBox passwordanswer=cp.Controls[0].FindControl("PasswordAnswer")
    as TextBox;

    try
    { //test is my username. You need to use the correct one in your
    case
    MembershipUser user = Membership.GetUser("test");
    string autogeneratedpassword
    =user.ResetPassword(passwordanswer.Text);
    //now a new auto-generated password is got, we have to change it
    to a new one
    user.ChangePassword(autogeneratedpassword, newpassword.Text);
    //Password successfully changed. You can show a message here
    Response.Write("Done!");
    }
    catch (MembershipPasswordException ex)
    {
    //the password answer is incorrect
    Response.Write("Incorrect!");
    }
    //cancel the subsequent process since we've changed the password.
    e.Cancel = true;

    }

    From above code you can see I called MembershipUser. ResetPassword method
    again. This is used to validate the password answer that is input by the
    user. If the exception is thrown we can know the password answer is
    incorrect.

    Please let me know if it works. Looking forward to your test result.

    Regards
    Allen Chen
    Microsoft Online Support

    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can improve the support we provide to you. Please
    feel free to let my manager know what you think of the level of service
    provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications.

    Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
    where an initial response from the community or a Microsoft Support
    Engineer within 1 business day is acceptable. Please note that each follow
    up response may take approximately 2 business days as the support
    professional working with you may need further investigation to reach the
    most efficient resolution. The offering is not appropriate for situations
    that require urgent, real-time or phone-based interactions or complex
    project analysis and dump analysis issues. Issues of this nature are best
    handled working with a dedicated Microsoft Support Engineer by contacting
    Microsoft Customer Support Services (CSS) at
    http://msdn.microsoft.com/subscriptions/support/default.aspx.
    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.


    --------------------
    | From: "Ken Fine" <>
    | Subject: Adding security question/answer check to ASP.NET
    *ChangePassword* control
    | Date: Thu, 14 Aug 2008 21:55:21 -0700
    | Lines: 1
    | Message-ID: <>
    | MIME-Version: 1.0
    | Content-Type: text/plain;
    | format=flowed;
    | charset="iso-8859-1";
    | reply-type=original
    | Content-Transfer-Encoding: 7bit
    | X-Priority: 3
    | X-MSMail-Priority: Normal
    | Importance: Normal
    | X-Newsreader: Microsoft Windows Live Mail 12.0.1606
    | X-MimeOLE: Produced By Microsoft MimeOLE V12.0.1606
    | X-MS-CommunityGroup-MessageCategory:
    {E4FCE0A9-75B4-4168-BFF9-16C22D8747EC}
    | X-MS-CommunityGroup-PostID: {E6AE7961-017F-4633-8287-9041A12ED72B}
    | Newsgroups: microsoft.public.dotnet.framework.aspnet
    | NNTP-Posting-Host: meta.urel.washington.edu 128.95.9.50
    | Path: TK2MSFTNGHUB02.phx.gbl!TK2MSFTNGP01.phx.gbl!TK2MSFTNGP05.phx.gbl
    | Xref: TK2MSFTNGHUB02.phx.gbl
    microsoft.public.dotnet.framework.aspnet:73903
    | X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet
    |
    | I want to add the security question and answer security feature to the
    | ChangePassword control. I am aware that this functionality is built into
    the
    | PasswordRecovery tool. I have implemented the PasswordRecovery with a
    | Password reset required; a temporary password is sent to the account on
    | file. I want an extra layer of security to accommodate the very unlikely
    | contingency that someone's e-mail account is compromised. Challenging
    with
    | the user's security question and answer will address this contingency.
    |
    | Put another way, this is the setup I want:
    | 1) User requests password reset
    | 2) email is sent with temp password
    | 3) user's/username's Membership info is evaluated, if comment ==
    | "UserResetPasswordMustChange" user is sent to password change form
    | 4) User changes password using an augmented ChangePassword control that
    | evaluates an answer against the user's security question on file.
    |
    | I have completed items 1-3.
    |
    | I have extended other login controls by exposing the templates, playing
    | around with FindControl, and writing functions on the OnWhatever events,
    so
    | I am familiar with the basic concepts involved in extending the
    | functionality of these things.
    |
    | In the case of a ChangePassword control I imagine I will want to inspect
    the
    | answer to the security question on file during the
    | ChangePassword1_ChangingPassword event and e.Cancel it in the event that
    the
    | answer is incorrect.
    |
    | I don't know how exactly to do this comparison, especially since the
    answers
    | to the security questions are hashed. Somehow in code I would need to do
    a
    | comparison of the cryptographic "fingerprints" of the user's input vs.
    the
    | hashed answer on file.
    |
    | Any help out there? Somewhere someone has written a tutorial on how to do
    | all of the above, I'm sure, but even a few snips of code would probably
    set
    | me on my way.
    |
    | Thanks!
    |
    |
     
    Allen Chen [MSFT], Aug 15, 2008
    #2
    1. Advertisements

  3. Hi Ken,

    Is this problem solved? Please feel free to let me know if you need further
    assistance.

    Regards,
    Allen Chen
    Microsoft Online Support
    --------------------
    | From: "Ken Fine" <>
    | Subject: Adding security question/answer check to ASP.NET
    *ChangePassword* control
    | Date: Thu, 14 Aug 2008 21:55:21 -0700
    | Lines: 1
    | Message-ID: <>
    | MIME-Version: 1.0
    | Content-Type: text/plain;
    | format=flowed;
    | charset="iso-8859-1";
    | reply-type=original
    | Content-Transfer-Encoding: 7bit
    | X-Priority: 3
    | X-MSMail-Priority: Normal
    | Importance: Normal
    | X-Newsreader: Microsoft Windows Live Mail 12.0.1606
    | X-MimeOLE: Produced By Microsoft MimeOLE V12.0.1606
    | X-MS-CommunityGroup-MessageCategory:
    {E4FCE0A9-75B4-4168-BFF9-16C22D8747EC}
    | X-MS-CommunityGroup-PostID: {E6AE7961-017F-4633-8287-9041A12ED72B}
    | Newsgroups: microsoft.public.dotnet.framework.aspnet
    | NNTP-Posting-Host: meta.urel.washington.edu 128.95.9.50
    | Path: TK2MSFTNGHUB02.phx.gbl!TK2MSFTNGP01.phx.gbl!TK2MSFTNGP05.phx.gbl
    | Xref: TK2MSFTNGHUB02.phx.gbl
    microsoft.public.dotnet.framework.aspnet:73903
    | X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet
    |
    | I want to add the security question and answer security feature to the
    | ChangePassword control. I am aware that this functionality is built into
    the
    | PasswordRecovery tool. I have implemented the PasswordRecovery with a
    | Password reset required; a temporary password is sent to the account on
    | file. I want an extra layer of security to accommodate the very unlikely
    | contingency that someone's e-mail account is compromised. Challenging
    with
    | the user's security question and answer will address this contingency.
    |
    | Put another way, this is the setup I want:
    | 1) User requests password reset
    | 2) email is sent with temp password
    | 3) user's/username's Membership info is evaluated, if comment ==
    | "UserResetPasswordMustChange" user is sent to password change form
    | 4) User changes password using an augmented ChangePassword control that
    | evaluates an answer against the user's security question on file.
    |
    | I have completed items 1-3.
    |
    | I have extended other login controls by exposing the templates, playing
    | around with FindControl, and writing functions on the OnWhatever events,
    so
    | I am familiar with the basic concepts involved in extending the
    | functionality of these things.
    |
    | In the case of a ChangePassword control I imagine I will want to inspect
    the
    | answer to the security question on file during the
    | ChangePassword1_ChangingPassword event and e.Cancel it in the event that
    the
    | answer is incorrect.
    |
    | I don't know how exactly to do this comparison, especially since the
    answers
    | to the security questions are hashed. Somehow in code I would need to do
    a
    | comparison of the cryptographic "fingerprints" of the user's input vs.
    the
    | hashed answer on file.
    |
    | Any help out there? Somewhere someone has written a tutorial on how to do
    | all of the above, I'm sure, but even a few snips of code would probably
    set
    | me on my way.
    |
    | Thanks!
    |
    |
     
    Allen Chen [MSFT], Aug 25, 2008
    #3
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.