ResetPassword method in ASP.NET 4.0 - asp.net

The ResetPassword method is able to reset the old password, but user is unable to login with the new password generated by ResetPassword method. Code:
String user =(((TextBox)PasswordRecovery2.Controls[0].FindControl("UserName")).Text).ToString();
String newPassword = clsStatic.RandomString(10, false);
MembershipUser username = Membership.GetUser(user);
String resetPassword = username.ResetPassword();
username.ChangePassword(resetPassword, newPassword);

Does ChangePassword return true or false?
I bet your random function returns a password that doesn't meet the criteria specified in your web.config membership section.
Since ResetPassword already gives you a new valid password why do you have to generate another one?

Your new random password generation should be ideally one of these
// this will automatically take care of all password criteria
string newPassword = Membership.GeneratePassword(10, 0);
Or
//for generating alpha numeric password only
string newPwd = Guid.NewGuid().ToString().Substring(0, 11).Replace("-", "");
Your code is fine otherwise.

Related

Web app protected by single password for all clients

I was wondering if there is a standard way of protecting a ASP.Net web application with just a single password? In other words no username needed and all clients use the same password for authentication.
Or does anyone have their own solution?
You simply could use Identity framework to aim this propose. Actually you don't need any user or password to authenticate.
[HttpPost]
public ActionResult Login(string password)
{
if (password=="MyVerySecretPassword")
{
var ident = new ClaimsIdentity(
new[] {
// adding following 2 claim just for supporting default antiforgery provider
new Claim(ClaimTypes.NameIdentifier, "JustAnuniqueName"),
new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider", "ASP.NET Identity", "http://www.w3.org/2001/XMLSchema#string"),
new Claim(ClaimTypes.Name,"JustAnuniqueName"),
},
DefaultAuthenticationTypes.ApplicationCookie);
HttpContext.GetOwinContext().Authentication.SignIn(
new AuthenticationProperties { IsPersistent = false }, ident);
return RedirectToAction("MyAction"); // auth succeed
}
// invalid password
ModelState.AddModelError("", "invalid username or password");
return View();
}
But it would be much better if you hash the password and check the hashed password instead of above simple if statement. To aim this you could use PasswordHasher class to hash and verify the password.
First hash your desired password and save it in preferred storage (DB, file, hard coded in code or everywhere else):
string hashedPassword = new PasswordHasher().HashPassword("MyVerySecretPassword");
Now since you have the hashed one. You could use VerifyHashedPassword() method to verify it.
if(new PasswordHasher()
.VerifyHashedPassword("myHashedPassword",password)==PasswordVerificationResult.Success)
{
// the password is correct do whatever you want
}
Also you could see my simple working example which I made to demonstrate it.

How to configure member ship with a database other than aspnetdb

I created one database and tables to store the user login values and credentials.
asp.net is providing aspnet_regsql tool to create a database for the membership related activities. But I dont want to use it. Thats why I created another database. Now I want to connect this database to my project. I changed in web.config file for the connectionstring parameter to my newly created database. But I am unable to login. It is giving following error message.
Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'
How to work with this. Is there any step by step procedures are there!! If so please provide.
Is there any thing to change rather than the connection string in the web.config file?
You need to create a membership provider to connect to your custom tables for authentication. MSDN has some documentation on the subject. You can also view a video on the subject at ASP.NET. Here are the links.
http://msdn.microsoft.com/en-us/library/f1kyba5e(v=vs.100).aspx
http://www.asp.net/web-forms/videos/how-do-i/how-do-i-create-a-custom-membership-provider
The main method for validation is going to be the ValidateUser method, you will override this method to provide authentication.
public sealed class CustomMembershipProvider : MembershipProvider
{
// implement other methods
public override bool ValidateUser(string username, string password)
{
try
{
var user = // GET USER OBJECT HERE
if (user != null)
{
string name = // set username
// Set your forms authentication ticket
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.ID.ToString(), DateTime.Now, DateTime.Now.AddMinutes(30), false, name, FormsAuthentication.FormsCookiePath);
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
HttpContext.Current.Response.Cookies.Add(authCookie);
return true;
}
}
catch
{
}
return false;
}
// Other implementations
}
If you have roles in your application you may also want to implement a custom role provider:
http://msdn.microsoft.com/en-us/library/8fw7xh74(v=vs.100).aspx

I implemented custom authentication but how to get UserID through application

I implemented custom authentication/authorization based on this tutorial http://www.mattwrock.com/post/2009/10/14/Implementing-custom-Membership-Provider-and-Role-Provider-for-Authinticating-ASPNET-MVC-Applications.aspx
It works fine. I implemented it because I don't want to have stored procedures in my database and possibility to use different RDBMS.
But I have one issue here. I authenticate user but I don't know how to store UserId somewhere so when I need to get something from database based on UserID to get it. Something like:
List<Product> products = productsRepository.GetProductsByUserId(User.UserID);
How to make this?
BTW Is there any better way to make custom authentication/authorization than this from this tutorial?
Thanks
If you've actually implemented all the methods, and you're populating the built-in MembershipUser, then simply Membership.GetUser().ProviderUserKey will return ther UserId.
in my solution I use
Docent docent = DocentRepo.GetByID(User.Identity.Name);
maybe this can be of use to you
If you're using FormsAuthentification you can encode some custom user data in your cookie / ticket besides UserName. But you have to manually create a FormsAuthenticationTicket and set UserData property to the user's id during login. This way you can have both UserName & UserId.
// during login
var authCookie = FormsAuthentication.GetAuthCookie(userName, createPersistentCookie);
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
// preserve data in your configuration
var ticketWithId = new FormsAuthenticationTicket(
version: ticket.Version,
name: ticket.Name,
issueDate: ticket.IssueDate,
expiration: ticket.Expiration,
isPersistent: ticket.IsPersistent,
userData: userId);
authCookie.Value = FormsAuthentication.Encrypt(ticketWithId);
_context.Response.Cookies.Add(authCookie);
Then you can have an extension method for Controller or HttpContext classes:
public int? GetUserId(this Controller controller) {
var identity = (FormsIdentity)controller.User.Identity;
int id;
if (int.TryParse(identity.Ticket.UserData, out id))
return id;
return null;
}
But if you don't need both UserId & UserName data for your user, than HttpContext.User.Identity.Name or Controller.User.Identity.Name will have the username for your current user

asp.net membership change password without knowing old one

Evaluting the method signature, it is required to know old password while changing it.
membershipUser.ChangePassword(userWrapper.OldPassword, userWrapper.Password)
Is there any way to change password without knowing old one.
string username = "username";
string password = "newpassword";
MembershipUser mu = Membership.GetUser(username);
mu.ChangePassword(mu.ResetPassword(), password);
The other answers here are correct, but can leave the password in an unknown state.
ChangePassword will throw exceptions if the password doesn't meet the requirements laid out in Web.Config (minimum length, etc.). But it only fails after ResetPassword has been called, so the password will not be known to the original user or to the person who's tried to change it. Check for complexity requirements before changing the password to avoid this:
var user = Membership.GetUser(userName, false);
if ((newPassword.Length >= Membership.MinRequiredPasswordLength) &&
(newPassword.ToCharArray().Count(c => !Char.IsLetterOrDigit(c)) >=
Membership.MinRequiredNonAlphanumericCharacters) &&
((Membership.PasswordStrengthRegularExpression.Length == 0) ||
Regex.IsMatch(newPassword, Membership.PasswordStrengthRegularExpression))) {
user.ChangePassword(user.ResetPassword(), newPassword);
} else {
// Tell user new password isn't strong enough
}
You need to reset the user's password before changing it, and pass in the generated password to ChangePassword.
string randompassword = membershipUser.ResetPassword();
membershipUser.ChangePassword(randompassword , userWrapper.Password)
or inline:
membershipUser.ChangePassword(membershipUser.ResetPassword(), userWrapper.Password)
Try to use SimpleMembershipProvider it's easier:
var token = WebSecurity.GeneratePasswordResetToken("LoginOfUserToChange");
WebSecurity.ResetPassword(token, "YourNewPassword");
Please note, all these mentioned solutions will only work if the RequiresQuestionAndAnswer property is set to false in Membership system configuration. If RequiresQuestionAndAnswer is true then the ResetPassword method needs to be passed the security answer, otherwise it will throw an exception.
In case you need RequiresQuestionAndAnswer set to true, you can use this workaround
This code mentioned on posts above is working:
string username = "username";
string password = "newpassword";
MembershipUser mu = Membership.GetUser(username);
mu.ChangePassword(mu.ResetPassword(), password);
But you have to set requiresQuestionAndAnswer="false" in web.config in membership provider tag. If it is true, resetpassword method generate an error "Value can not be null".
In this case you must supply question answer as parameter to ResetPassword.
Use the password you want to set from textbox in place of 123456.
MembershipUser user;
user = Membership.GetUser(userName,false);
user.ChangePassword(user.ResetPassword(),"123456");
#Rob Church is right:
The other answers here are correct but can leave the password in an
unknown state.
However, instead of his solution to do the validation by hand, I would try to change the password using the ResetPassword from token method and catch and show the error:
var user = UserManager.FindByName(User.Identity.Name);
string token = UserManager.GeneratePasswordResetToken(user.Id);
var result = UserManager.ResetPassword(user.Id, token, model.Password);
if (!result.Succeeded){
// show error
}
string username = "UserName";
string userpassword = "NewPassword";
string resetpassword;
MembershipUser mu = Membership.GetUser(username, false);
if (mu == null){
Response.Write("<script>alert('Invalid Username!')</script>");
}
else{
resetpassword = mu.ResetPassword(username);
if (resetpassword != null){
if (mu.ChangePassword(resetpassword, userpassword)){
Response.Write("<script>alert('Password changed successfully!')</script>");
}
}
else{
Response.Write("<script>alert('Oh some error occurred!')</script>");
}
}
string username = "UserName";
string userpassword = "NewPassword";
MembershipUser mu = Membership.GetUser(username, false);
mu.ChangePassword(mu.ResetPassword(username), userpassword);

asp.net "Remember Me" cookie

I have implemented remember me option in my asp.net webform by using this,
protected void LBtnSubmit_Click(object sender, EventArgs e)
{
if (this.ChkRememberme != null && this.ChkRememberme.Checked == true)
{
HttpCookie cookie = new HttpCookie(TxtUserName.Text, TxtPassword.Text);
cookie.Expires.AddYears(1);
Response.Cookies.Add(cookie);
}
}
Am i doing it the right way? Any suggestion.. I am using windows authentication and i am not using asp.net membership..
Rather than directly storing the username and password in the cookie, store the username and a hash of the password and a salt in the cookie, then when you authenticate the cookie, retrieve the password for the given username, re-create the hash with the password and the same salt and compare them.
Creating the hash is as simple as storing the password and salt values together in a string, converting the string to a byte array, computing the hash of the byte array (using MD5 or whatever you prefer) and converting the resulting hash to a string (probably via base64 encoding).
Here's some example code:
// Create a hash of the given password and salt.
public string CreateHash(string password, string salt)
{
// Get a byte array containing the combined password + salt.
string authDetails = password + salt;
byte[] authBytes = System.Text.Encoding.ASCII.GetBytes(authDetails);
// Use MD5 to compute the hash of the byte array, and return the hash as
// a Base64-encoded string.
var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] hashedBytes = md5.ComputeHash(authBytes);
string hash = Convert.ToBase64String(hashedBytes);
return hash;
}
// Check to see if the given password and salt hash to the same value
// as the given hash.
public bool IsMatchingHash(string password, string salt, string hash)
{
// Recompute the hash from the given auth details, and compare it to
// the hash provided by the cookie.
return CreateHash(password, salt) == hash;
}
// Create an authentication cookie that stores the username and a hash of
// the password and salt.
public HttpCookie CreateAuthCookie(string username, string password, string salt)
{
// Create the cookie and set its value to the username and a hash of the
// password and salt. Use a pipe character as a delimiter so we can
// separate these two elements later.
HttpCookie cookie = new HttpCookie("YourSiteCookieNameHere");
cookie.Value = username + "|" + CreateHash(password, salt);
return cookie;
}
// Determine whether the given authentication cookie is valid by
// extracting the username, retrieving the saved password, recomputing its
// hash, and comparing the hashes to see if they match. If they match,
// then this authentication cookie is valid.
public bool IsValidAuthCookie(HttpCookie cookie, string salt)
{
// Split the cookie value by the pipe delimiter.
string[] values = cookie.Value.Split('|');
if (values.Length != 2) return false;
// Retrieve the username and hash from the split values.
string username = values[0];
string hash = values[1];
// You'll have to provide your GetPasswordForUser function.
string password = GetPasswordForUser(username);
// Check the password and salt against the hash.
return IsMatchingHash(password, salt, hash);
}
I would not store the users password in a cookie... Rather store the user id and the ip address in the cookie.
I would not store the ip / user id in the cookie. Session highjacking would then be really easy, I mean I know the username / ip of my collegues, I could add that cookie to my message and then I can work on the session of my collegue.

Resources