Send email to user for password reset - c#

The flow is:
user enters email address
after submit, an email is sent to the user
The email will include a link that will take the user to a reset password page.
Now, how do I fetch user's ID based on the email address and encrypt it? Then what should link be? Like, what I want is fetch the User ID then encrypt it somehow so that the link doesn't contain the actual ID and that link will take the user to a page that will have textboxes to reset the password. I am just confused how to go about it.
Also is this the secure way? To reset a password like this?

I usually create a new table in the database:
PasswordresetRequest with the following fields:
Id: Guid - Id of password reset request.
Accountid: string - username of user
Created: DataTime - timestamp of when password reset were created
Flow is as follows:
User request password reset at web site.
A new record is created in the PasswordresetRequest table.
An email with a link to the password reset page with the password request id as request parameter is sent to the user.
User click on link in email which send him to password reset page.
Password request if fetched from database from request parameter. If request could be found or and request is not older than e.g. 12 hours a form is presented to user where he can enter a new password.
This is pretty simple to implement and is secure enough for most sites.

There is any number of ways to go about doing this. If your major concern is security, one way could be to send a link that contains a guid parameter which you create and store on your end (in a db table, file or whatever suits you) together with the user id associated with it. When the request for password reset comes in, you check for the guid and look if there is one matching value in your db/file/whatever and proceed with the password reset. Don't forget to delete the guid from your storage to prevent multiple use of the same link.

There is a railscast on exactly this subject: http://railscasts.com/episodes/274-remember-me-reset-password?view=asciicast

Related

Authenticate without username and password

I have a database table with 4 columns (email, token, tokenDate (DateTime), isOnline (bool))
What I am trying to do in ASP.NET MVC is have an application where the user goes to a page like this Home/Index?email=xxxxx#xxxxxxx.com and when they goto the page, they are login, now what I could do it when they goto the page is this:
Find the user in the database table
Mark isOnline to true
Set the tokenDate to DateTime.Now
Create a random token and set that as token
Create a web cookie with the same value as token
And when someone else (or the same person) with the same email tries to goto the page
Find the user in the database table
If isOnline is marked as true and the cookie does not exist and if it does check against the one in the database, if fails boot them out, if success, they can enter.
My question is what token would I want to create so they original user is still authenticated so if they close their browser or goto another page they can still goto the main page where they authenticated?
User goes to a page like this Home/Index?email=xxxxx#xxxxxxx.com or User Types email in a text box
STEP 1:
Find the user in the database table if doesn't exist take to access
denied page.
If exist Mark isOnline to true.
Set the tokenDate to.
DateTime.UtcNow so that you can display later into local time of
user.
Create a random token using
GUID
and set that as token in database.
Create a
cookie
to store
multiple
values one with the GUID value as token and another would be user
email then set cookie expiry to years so doesn't expire even if user
closes the browser.
Step 2:
Now when user goes to Home/SomeOtherPage or the authentication page Home/Index?email=xxxxx#xxxxxxx.com
Check if cookie with the name exist , if exist get the email and token values from cookie and check against the value in database , if token matches for the email then user is authenticated.
Edit cookie and Set another value in cookie saying if user is authenticated, So next time when user visits check the value of authenticated as this would eliminate hitting database again if user visit pages again.
Note:
It would be better if you could encrypt the email while setting it in the cookie.

duplicate ID in aspx c# when sending emails

Im creating a tracking system in aspx c# and I want the user to submit a ticket and it'll assign it an ID and send the email.
I got everything to work but the problem is if two or more users are on the same page it'll assign them the same ID when they send the email (#150 and #150). However in Sql, it would be (#150 and #151).
aspx.cs page (Im getting the current ID from SQL)
id.Text = ds.Tables[0].Rows[0]["id"].ToString();
Then I'm incrementing it by 1 (to send the email) Because I dont want the current users that's sending the request to have an old ID.
id = id + 1;
Note that this works perfectly if only one users is on the page submitting the request.
Can someone get a work around this? Thanks!
In case you are using the logged-in user's id on the url to handle a user's session and also set the email ID (check example below):
.aspx?user_id=150&email_id=150
Then you need to use the appropriate user's session that opens your webpage as shown below to get the appropriate ID as an email ID.
id.Text = Session[user_id].ToString();
For that reason when both users are logged in simultaneously you only get the same id for both. You probably have a static site that handles only one session per user.

Reset Password e- mail... recent email should work , not previous

Reset Password Email - If two reset Password email has been sent , then the recent one should only work. Previous one should n't redirect to a reset password page.. Provide me a hint what can i do to make it work as required
Add a VerificationCode-column to the database where the passwords are saved
Username Password VerificationCode
user1 Pass1 dfsdb-dfb-anda
Password reset link will consist of a randomly generated verificationCode (as a query parameter).
/account/ResetPassword?user=user1&VerificationCode=dfsdb-dfb-anda
On receiving a request from reset form, to change password, verify the username and verificationCode combination. Once the user has changed the password, delete the verification code from the database.

How to allow Unauthenticated users to reset password?

Please see Update Below:
I am using ASP.NET SQL Membership Provider.
So far I am able to allow users to change their password but only if they are authenticated or logged into the application.
What I really need is for users to be able to get a link in an email. They can click this link and reset their password.
Example: Lets say a user forgets his or her password, they can visit a page which they can either enter security question and answer; or their email address on file. They will then get an email with a link to reset their password.
All I have so far is this: Which allows only authenticated users to reset their passwords:
I do not want to use the Recovery Control which generates a password.
public void ChangePassword_OnClick(object sender, EventArgs args)
{
MembershipUser user = Membership.GetUser(User.Identity.IsAuthenticated);
try
{
if (user.ChangePassword(OldPasswordTextbox.Text, PasswordTextbox.Text))
{
Msg.Text = "Password changed.";
}
else
{
Msg.Text = "Password change failed. Please re-enter your values and try again.";
}
}
catch (Exception e)
{
Msg.Text = "An exception occurred: " + Server.HtmlEncode(e.Message) + ".
try again.";
}
}
I can create the store procedure and the email using a String Builder but I do not know how to get the un-authenticated user to change password. Is there a way for the user to be Authenticated when they click the link. I am not sure how to even ask this.
Thanks for reading:
Update:
Okay I managed to get the password to Reset using this code:
protected void btnResetPassword_Click(object sender, EventArgs e)
{
string username = "ApplePie12";
MembershipUser currentUser = Membership.GetUser(username);
currentUser.ChangePassword(currentUser.ResetPassword(), txtResetPassword.Text);
}
Here is my plan:
Make this page public so that it is access by Un-Authenticated Users but only via email link.
Create a Stored Procedure that verifies a user Exists either by the UserName they enter or by the Security Question/Answer.
If they exists, they are sent a link containing a token/GUID
Lastly when they click the link they will land on this page asking them to change password. *The Link Expires as soon as it is used.
My only question is: Doing all of the above requires turning off using security Question/Answer in the Web Config file.
I really would love to have the Security question as an option for the user to either verify by email or security question. If this is not possible, I'll have to create some kind of account number or userid (not membership user id) as an alternative.
My answer is not specific to Membership Provider, but hopefully will point you in the right direction. Typically the way to approach this is to generate a very long random string, called a token. You send them a link that includes this token as a parameter, something like:
http://foo.bar/reset?token=asldkfj209jfpkjsaofiu029j3rjs-09djf09j1pjkfjsodifu091jkjslkhfao
Inside your application you keep track of tokens you have generated. If you receive a request containing that token, you authenticate it as if it was that user.
A couple notes:
The token generated should be random and effectively unguessable in a short period of time.
The token should only work for a short period of time after being generated, ideally shorter than the time required to guess it.
The token should only be usable once. Once a user has changed their password using it, remove it from the system.
Chris has given definitely the correct solution.
You can use the sql table for token management. the token may be UserId or Email that are unique. the link used for reset email like http://test.com/reset?id=sfksdfh-24204_23h7823.
The id in the url is encrypted Userid or Email as you like.
Fetch the detail from table on the basis of id in Url. if id contain in database. then reset the password for user. and remove that token from DB.

WebMatrix.WebData.WebSecurity - How can I get UserName by only having PasswordResetToken

I just wanted to ask for help to get my scenario work? I want to get the UserName using a PasswordResetToken.
This is my scenario.
I have a forgot password feature in my website that would send a passwordresettoken email a change password to the user.
I wanted to send just the passwordresettoken string only.
When the user clicks the link. I will just query the request["token"] to get the username and and then will allow the user to change password and autologin.
this is my code below:
public ActionResult ChangePassword()
{
ChangePasswordModel model = new ChangePasswordModel();
string token=string.Empty;
try
{
token = Request["token"].ToString();
int userId = WebSecurity.GetUserIdFromPasswordResetToken(token);
if (userId > 0)
{
//Get the user object by (userid)
//???????????????????
//???????????????????
}
else
{
throw new Exception("The change password token has expired. Please go to login page and click forgot password again.");
}
}
catch
{
model.HasError = true;
ModelState.AddModelError("", "The change password token has expired. Please go to login page and click forgot password again.");
}
return View(model);
}
Thank you in advance.
Look at the remark at the end of this article: WebSecurity.GeneratePasswordResetToken Method.
I'll copy the relevant part for your convenience:
If users have forgotten their password, they can request a new one. To
provide a new password, do the following:
Create a password-reset page that has a field where users can enter their email address.
When a user has entered his or her email address in the password-reset page, verify that the email address represents a valid
user. If it does, generate a password reset token by calling the
GeneratePasswordResetToken(String, Int32) method.
Create a hyperlink that points to a confirmation page in your site and that includes the token as a query-string parameter in the link's
URL.
Send the link to a user in an email message. When the user receives the email message, he or she can click the link to invoke the
confirmation page.
Create a confirmation page that extracts the token from the URL parameter and that lets the user enter a new password.
When the user submits the new password, call the ResetPassword(String, String) method and pass the password reset token
and the new password. If the token is valid, the password will be
reset. If the token is not valid (for example, it has expired),
display an error message.
Highlighting is mine. Basically you do not need the user name. The framework does all the heavy lifting for you.
Addressing your comment, I would not recommend automatically logging the user in. It's a good practice for them to log manually to check that this password changing thingie has actually worked, and not to discover that it did not only next time around.
Anyway, you can do this:
SimpleMembershipProvider provider = (SimpleMembershipProvider)Membership.Provider;
string username = provider.GetUserNameFromId(userId);
Reference: GetUserNameFromId.
I think the WebSecurity.GetUserIdFromPasswordResetToken(string token) method do what you want.
More info here.
Update:
Sorry but I didn't saw that you were already using that method... So if you want get the username and you are using code first migrations of Entity Framework, you can get the username with the following LINQ expression:
string username = yourDbContext.UserProfiles.FirstOrDefault(up=>up.UserId == userId).Username;

Categories