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

  • Thread starter Thread starter Ken Fine
  • Start date Start date
K

Ken Fine

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!
 
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:
(e-mail address removed).

==================================================
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" <[email protected]>
| Subject: Adding security question/answer check to ASP.NET
*ChangePassword* control
| Date: Thu, 14 Aug 2008 21:55:21 -0700
| Lines: 1
| Message-ID: <[email protected]>
| 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!
|
|
 
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" <[email protected]>
| Subject: Adding security question/answer check to ASP.NET
*ChangePassword* control
| Date: Thu, 14 Aug 2008 21:55:21 -0700
| Lines: 1
| Message-ID: <[email protected]>
| 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!
|
|
 
Back
Top