Forgot password URL

asp.net, c#, url

Solution

Consider a separate page for the changepassword link. Have this page take a unique identifier. This identifier should work one time only, have an expiry date, and be specific to that user. Make this page public:

<location path="changepassword.aspx">
 <system.web>
   <authorization>
     <allow users="*"/>
   </authorization>
 </system.web>
</location>

You need to store the unique identifier somewhere against the user. If you don't want to affect your current schema, you can create a new table:

PK | Identifier | UserID                               | expires
1  | abcd       | ffffffff-ffff-ffff-ffff-ffffffffffff | 16-jul-2012 18:26

When the page is requested, if the identifier is expired don't allow the page to function. Once the password has been changed, invalidate the identifier - either delete it, or set the expiry date to something in the past (e.g. now).

Problem

I have a web application which uses an asp.net login control. In addition, I also uses a password recovery control for users to recover their password. Once user had finished entering their particulars in the recovery control, an email containing a verification URL would be send to the user's email address. Upon clicking the URL, it would direct the user into the UserProfile of my web application, which inside, it allows the user to change their password. Now the problem is, because i set an access rule to UserProfile.aspx to deny anonymous user, when I redirect from the URL into the UserProfile.aspx page, it direct me to the LoginPage instead(the system recognize the me as an anonymous user). Why is it so? Is there anywhere that I could direct into the userprofile page once the URL is clicked(which include all user information) ? The URL look like this: ``` http://localhost:1039/Members/UserProfile.aspx?ID=56f74cc7-7680-4f1b-9207-0ab8dad63cad ``` Where the last part of the URL was actually the userId. Here is the code for userprofile aspx: ``` <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ASPNETDBConnectionString1 %>" SelectCommand="SELECT aspnet_Membership.Email, Details.CustName, Details.CustNum, Details.CustRole, Details.CustStatus, Details.PName, Details.PEmail, Details.PRole, Details.WedDate, aspnet_Users.UserName, Details.UserId FROM Details INNER JOIN aspnet_Membership ON Details.UserId = aspnet_Membership.UserId INNER JOIN aspnet_Users ON aspnet_Membership.UserId = aspnet_Users.UserId WHERE (Details.UserId = @UserId)" UpdateCommand="update Details SET CustName = @CustName, CustNum = @CustNum, CustRole = @CustRole, CustStatus = @CustStatus, PName = @PName, PEmail = @PEmail, PRole = @PRole, WedDate = @WedDate WHERE [UserId] = @UserId Update aspnet_Membership Set Email= @email WHERE [UserId] = @UserId" DeleteCommand= "DELETE FROM Details WHERE UserId = @UserId;"> <DeleteParameters> <asp:ControlParameter ControlID="lblHidden" Name="UserId" PropertyName="Text" Type="String" /> </DeleteParameters> <SelectParameters> <asp:ControlParameter ControlID="lblHidden" Name="UserId" PropertyName="Text" /> </SelectParameters> <UpdateParameters> <asp:Parameter Name="CustName" /> <asp:Parameter Name="CustNum" /> <asp:Parameter Name="CustRole" /> <asp:Parameter Name="CustStatus" /> <asp:Parameter Name="PName" /> <asp:Parameter Name="PEmail" /> <asp:Parameter Name="PRole" /> <asp:Parameter Name="WedDate" /> <asp:Parameter Name="UserId" /> <asp:Parameter Name="email" /> </UpdateParameters> </asp:SqlDataSource> <asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False" DataSourceID="SqlDataSource1" Height="50px" Width="125px"> <Fields> <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" /> <asp:BoundField DataField="CustName" HeaderText="CustName" SortExpression="CustName" /> <asp:BoundField DataField="CustNum" HeaderText="CustNum" SortExpression="CustNum" /> <asp:BoundField DataField="CustRole" HeaderText="CustRole" SortExpression="CustRole" /> <asp:BoundField DataField="CustStatus" HeaderText="CustStatus" SortExpression="CustStatus" /> <asp:BoundField DataField="PName" HeaderText="PName" SortExpression="PName" /> <asp:BoundField DataField="PEmail" HeaderText="PEmail" SortExpression="PEmail" /> <asp:BoundField DataField="PRole" HeaderText="PRole" SortExpression="PRole" /> <asp:BoundField DataField="WedDate" HeaderText="WedDate" SortExpression="WedDate" /> <asp:BoundField DataField="UserName" HeaderText="UserName" SortExpression="UserName" /> <asp:BoundField DataField="UserId" HeaderText="UserId" SortExpression="UserId" /> <asp:CommandField ShowEditButton="True" /> </Fields> </asp:DetailsView> <asp:Label ID="lblHidden" runat="server" Text="Label" Visible="False"></asp:Label> <asp:Button ID="btnDelete" runat="server" onclick="btnDelete_Click" Text="Delete" /> ``` Here is the code behind: ``` protected void Page_Load(object sender, EventArgs e) { MembershipUser currentUser = Membership.GetUser(); lblHidden.Text = currentUser.ProviderUserKey.ToString(); } protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e) { // Get a reference to the currently logged on user MembershipUser currentUser = Membership.GetUser(); // Determine the currently logged on user's UserId value // Assign the currently logged on user's UserId to the @UserId parameter //access the parameter value using e.Command.Parameters //programmatically set the @UserId: e.Command.Parameters["@UserId"].Value = currentUser.ProviderUserKey.ToString(); } protected void btnDelete_Click(object sender, EventArgs e) { SqlConnection connection = new SqlConnection(); connection.ConnectionString = ConfigurationManager.ConnectionStrings["ASPNETDBConnectionString1"].ConnectionString; SqlCommand cmd = new SqlCommand(); SqlCommand cmd1 = new SqlCommand(); string userId = lblHidden.Text; cmd.Connection = connection; cmd.CommandText = "DELETE FROM Details WHERE UserId ='" + userId + "'"; cmd1.Connection = connection; cmd1.CommandText = "DELETE FROM aspnet_Membership WHERE UserId ='" + userId + "'"; connection.Open(); cmd.ExecuteNonQuery(); cmd1.ExecuteNonQuery(); connection.Close(); Response.Redirect("Home.aspx"); } ``` Secondly, is there any way I could set an expiry to the URL? If the URL is being click the second time, it would not redirect the user to any place. I saw many posts, most of them recommend to add a column into the database. Is there any other way where I could set the expiry without touching the database???

Original source