ASP.NET MVC password validation with hash - asp.net

So I want to add my Custom Hash into my password, but it got stuck because my own validation
My Model:
public class ms_user
{
[Required(ErrorMessage = "Please Input your Login Email")]
[DataType(DataType.EmailAddress)]
public object user_id { get; set; }
[Required(ErrorMessage = "Please Input your Password")]
// Validation at least 1 uppercase & 1 number, password lenght must be greater then 6 and lower then 12, with no Special Character
[RegularExpression(#"^(?=.*\d)(?=.*[A-Z])[a-zA-Z0-9](.{6,12})$", ErrorMessage = "Error, Wrong Password Format")]
public object password { get; set; }
}
Sample:
Password Inputed : Admin123 // Pass Validation
HashedPassword Output: l92Vi3c2Af7Oftgy7JqYJKR8isYXef8pIOqvMzjrN6rnRct6W6UuDzv0YRCOudPPXnC69Gj2J4igXZWH1WRz9C19abN4UWKSqX8d0TxA+0IvXJAvzoksaEWPQm56gy/l:9KZQeh3nB9apjy81V/FvfU // After i hashed my password,
My Project pass the Password Validation, but on the db.SaveChanges(); it return error, because the Password validation
is there any solution?? i prefer not to add javascript validation...
Thx

Change the Datatype of Password column to nvarchar(MAX) in your User table to accomodate the Hashed Password.

I faced this exact same problem, because I updated the password length in database to nvarchar(max) but didn't update the model in visual studio after that. So Update the Model and it should fix that.

Related

Remove User from Directory Role using Graph API

I am trying to add and remove users from a directory role (Guest Inviter) based on a user's ID. My client ID has Directory.AccessAsUserAll for the Microsoft Graph application. I am using the ID for the directory role and the ID for the user. Using an HTTP Client call (verb is DELETE) I use the format suggested by Microsoft and get an "Insufficient privileges to complete the operation." error. I can perform other functions successfully
It seems clear to me that I am missing something. I would think that you still log in with the Client ID and Client Secret then do something with an admin type id and password rather than just create a new token based these credentials (because then why would you link them) similar to impersonation code but I don't know how and cannot seem to find an example of how.
Using HTTPClient
Verb DELETE
following this pattern
DELETE /directoryRoles/{id}/members/{id}/$ref
https://learn.microsoft.com/en-us/graph/api/directoryrole-delete-member?view=graph-rest-1.0&tabs=cs
Using C# creating bearer token (with client id and client secret) then using an HTTPCLient I call DeleteAsync using a url string based on the recommended pattern.
I see references to needing to pass user credential for a user in an admin role.
I think the issue is the absence of something important. This is called once the bearer token is obtained using client id and client secret for out tenant.
string delURL = $"{settings.RestUrl.value}{settings.RestVersion.value}/directoryRoles/{settings.GuestInviterRoleObjectID.value}/members/{user.id}/$ref";
HttpResponseMessage payload = await client.DeleteAsync(delURL);
Task<string> json = payload.Content.ReadAsStringAsync();
JObject o = new JObject();
if (json.Result.Length > 0)
{
o = JObject.Parse(json.Result);
}
I would like to remove the user from the Guest Inviter directory role. I get however
error: code:"authorization_requestDenied",
messsage: "Insufficient privileges to complete the operation" ....
Update: I was following this example https://dzone.com/articles/getting-access-token-for-microsoft-graph-using-oau-2
I built a class to contain the properties so after getting my original token using Client ID and Client secret then feeding in what I was told was a global admin credentials and now I get a 401 unauthorized error.
string tURL = $"https://login.microsoftonline.com/{settings.TenantID.value}/oauth2/token";
using (System.Net.WebClient c = new System.Net.WebClient())
{
c.Headers["Authorization"] = $"Bearer {token}";
c.Headers["Content-Type"] = "application/x-www-form-urlencoded";
System.Collections.Specialized.NameValueCollection data = new System.Collections.Specialized.NameValueCollection();
body.GetType().GetProperties().ToList().ForEach(delegate (System.Reflection.PropertyInfo item)
{
data.Add(item.Name, item.GetValue(body) == null ? string.Empty : item.GetValue(body).ToString());
});
var res = await Task.Run(() => c.UploadValues(tURL, data));
Task.WaitAll();
if(res != null)
{
string response = System.Text.Encoding.UTF8.GetString(res);
}
}
Data object
public class JSONBody
{
public string grant_type { get; set; }
public string client_id { get; set; }
public string client_secret { get; set; }
public string resource { get; set; }
public string username { get; set; }
public string password { get; set; }
public JSONBody()
{
this.grant_type = "password";
this.resource = "https://graph.microsoft.com";
}
}
I cannot prove or disprove the 401 error because I cannot prove my code works (or doesn't).
According to the documentation https://learn.microsoft.com/en-us/graph/api/directoryrole-delete-member
You’ll need an application with the delegated Directory.AccessAsUser.All permission. The you’ll need an admin to login to that application (with the correct permissions).
The application credentials (or client credentials flow) is unsupported, by design.
This could result in privilege elevation, if some admin would create an application with these permissions. If that admin would then be removed from the admin role he would be able to use his application to make himself admin again

Plain password in .net core SignInManager Identity

I have user table with plain passwords. I need connect the table into .net core web's AspNetUsers table.How to hash my user table's plain passwords like AspNetUsers's PasswordHash.
How can login with SignInManger plain-text password?
I recently did something like this. Our legacy system had its own password hashing method. I needed to covert everything over to asp.net users.
First thing I did was add two new columns to the Application user. These contain my legacy user password and that hash that was used to create it.
public string LegacyPasswordHash { get; set; }
public string LegacyPasswordSalt { get; set; }
Then i ran my sql script that copied all of the users in including their legacy password hash and salt.
Then i created a custom SignInManager.
public class ApplicationSignInManager : SignInManager<ApplicationUser> {}
In the password check method I test if its a legacy password user and if it is i covert the password that they just sent me over to a asp.net users password and delete their legacy password. Tip: is to remember to set the user security token on the user table as well this can not be null. You will have major issues with resting password if it is. As there is a bug in the token validation 2022
This is the section of the code i use for testing and resetting the password.
if (_password.EncodePassword(_user.LegacyPasswordSalt) == _user.LegacyPasswordHash)
{
_logger.LogInformation(LoggingEvents.LegacyUserCommand, "Legacy User {_user.Id} migrating password.", _user.Id);
await _userManager.AddPasswordAsync(_user, _password);
_user.SecurityStamp = Guid.NewGuid().ToString();
_user.LegacyPasswordHash = null;
_user.LegacyPasswordSalt = null;
await _userManager.UpdateAsync(_user);
return await new CheckTwoFactorCommand(_logger, _userManager, _user).Execute();
}
if (_shouldLockout)
{
_user.SecurityStamp = Guid.NewGuid().ToString();
await _userManager.UpdateAsync(_user);
_logger.LogInformation(LoggingEvents.LegacyUserCommand, "Login failed for Legacy user {_user.Id} invalid password. (LockoutEnabled)", _user.Id);
await _userManager.AccessFailedAsync(_user);
if (await _userManager.IsLockedOutAsync(_user))
return SignInResult.LockedOut;
}
_logger.LogInformation(LoggingEvents.LegacyUserCommand, "Login failed for Legacy user {_user.Id} invalid password", _user.Id);
return SignInResult.Failed;

How to implement Asp.net membership in my developed web application

I am working on a web application. I already completed it. But when I gone through security audit, I came to know that I should use asp.net membership for, login, password change, creating user, reset password etc.
So I stared using asp.net membership. I created a login page and it's working fine. I also got a database in my App_Data folder.
The problem is that I already have a database for my application where I have a user table which is having more fields than the table aspnet_Users. see the image below.
So please suggest me how to implement asp.net membership in my web application, as I need more fields in user table,
how to insert data along with my fields with the fields above mentioned in the above image, because I didn't fine any code through using asp.net membership. If I could got, I would surely make changes accordingly.
I mean how to merge this database and mine without any code.
I would also recommend that you use ASP.Net Identity as it is the framework for handling security.
However, if you are going to use simple membership, here is some code to help you "add fields" to your user table.
First, create your user model with all needed properties like so:
[Table("User")]
public class User
{
public int UserId { get; set; }
[Display(Name = "User name")]
[Required(ErrorMessage = "Usernname is required.")]
[StringLength(80, ErrorMessage = "Please enter a value no more than 80 characters.")]
public string UserName { get; set; }
[Display(Name = "First Name")]
[Required(ErrorMessage = "First name is required.")]
[StringLength(80, ErrorMessage = "Please enter a value no more than 80 characters.")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
[Required(ErrorMessage = "Last name is required.")]
[StringLength(80, ErrorMessage = "Please enter a value no more than 80 characters.")]
public string LastName { get; set; }
[Required]
[Display(Name = "Email")]
[DataType(DataType.EmailAddress)]
[StringLength(254, ErrorMessage = "Please enter a value no more than 254 characters.")]
public string Email { get; set; }
//Add other properties... etc
}
Next, write the code to initialize your database. You probably have this code somewhere in the InitializeSimpleMembershipAttribute.cs file. Or, you can take it out from there and put in on your Application Start method. Here is the piece you need to modify:
WebSecurity.InitializeDatabaseConnection("YourDBConnectionName", "User", "UserId", "UserName", autoCreateTables: true);
//Modify the above properties if you change your user model to be a different table name
See reference to InitializeDatabaseConnection.
Now, when you want to create a user, call the following method:
WebSecurity.CreateUserAndAccount(user.UserName, user.Password, new { user.Email, user.FirstName, user.LastName });
//user is the User object that has all your data populated from some type of input
Reference to create user account: CreateUserAndAccount
The one you are trying to implement is legacy ASP.Net Membership Provider created using aspnet_regsql.exe. Do not use it, because it has been deprecated long time ago.
Currently, Microsoft offers 3 types of Memberships -
ASP.NET Universal Providers
Simple Membership Provider
ASP.NET Identity
Since your application is new and doesn't have existing users, you want to use -
ASP.NET Identity 2
The problem is that I already have a database for my application where
I have a user table which is having more fields than the table
aspnet_Users.
ASP.Net Identity lets you create custom fields in User table.
FYI: Make sure you use Version 2.

How to securely store service passwords with ASP.NET Membership?

I am using ASP.NET MVC 3 membership for my site with defaults. Thus the membership password for the user is stored securely.
My service requires the user to enter username/passwords for other web services they use. I access those services from my service. If I save the users' service passwords I need to ensure that those usernames/passwords are stored securely as well so that if someone hacks my server they will not be exposed.
I understand the general concepts of how this might be done (encrypt the username/pw using the hash of the ASP.NET membership pw they've provided as the key). But I don't know the specific APIs or correct patterns.
I also think it's basically impossible to really do this because if someone hacks my service they could simply use the hash themselves to decrypt the passwords. Am I right about that.
Assuming i'm wrong, and it is possible to do what I want, assume my model contains something like this:
public class MSExchangeSettings
{
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address for your Exchange account")]
public string EmailAddress { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "Password for your Exchange account")]
public string Password { get; set; }
...
}
Can someone please provide an example of how to do this correctly?
If, this is not possible I'll have to resort to asking the user for the PW every every time which I want to avoid. Of course, for the services I use that support OpenID or OAuth I have other alternatives, but for this specific example (Exchange) I need a username/pw.
Take a look at this
private static string GetPasswordHashed(string password) {
var saltBytes = new byte[0x10];
using (var random = new RNGCryptoServiceProvider()) {
random.GetBytes(saltBytes);
}
var passwordBytes = Encoding.Unicode.GetBytes(password);
var combinedBytes = saltBytes.Concat(passwordBytes).ToArray();
byte[] hashBytes;
using (var hashAlgorithm = HashAlgorithm.Create("HashAlgorithm")) {
hashBytes = hashAlgorithm.ComputeHash(combinedBytes);
}
var PasswordHashed = Convert.ToBase64String(hashBytes);
return PasswordHashed;
}

asp.net membership IsApproved false but still allowing login

i have change the default Account Membership provider to set IsApproved to false.
public MembershipCreateStatus CreateUser(string userName, string password, string email)
{
MembershipCreateStatus status;
_provider.CreateUser(userName, password, email, null, null, false, null, out status);
return status;
}
But i then go back to the login page and it allows me to login. Shouldn't it fail login and say that i am not approved ??
EDIT:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(string userName, string email, string password, string confirmPassword, string address, string address2, string city, string state, string homePhone, string cellPhone, string company)
{
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
if (ValidateRegistration(userName, email, password, confirmPassword))
{
// Attempt to register the user
MembershipCreateStatus createStatus = MembershipService.CreateUser(userName, password, email);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuth.SignIn(userName, false /* createPersistentCookie */);
TempData["form"] = Request.Form;
TempData["isActive"] = false;
return RedirectToAction("Create", "Users");
}
else
{
ModelState.AddModelError("_FORM", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View();
}
(it looks like the other copy of this question is going to be closed, so I've copied my answer here)
HttpRequest.IsAuthenticated returns true if HttpContext.User.Identity is not null and it's IsAuthenticated property returns true.
The current identity is set in the FormsAuthenticationModule, but it has nothing to do with your MembershipProvider. In fact, it doesn't even reference it. All it does is check to see if the authentication cookie is still set and is still valid (as is, has not expired).
I think the problem is that you are calling one of the FormsAuthentication methods like RedirectFromLoginPage, which is settings the authentication cookie. If you need to wait until the user is approved, then you need to make sure you are not setting the cookie.
Update
There are no values of MembershipCreateStatus that specify that the user has been created but not approved, so your code is calling FormsAuth.SignIn without actually checking if the user has been approved.
FormsAuth.SignIn just sets the cookie, that's it. It doesn't validate the user or otherwise have any relation to your MembershipProvider. If approval is asynchronous (ie. waiting for a human), then don't automatically log the user in by calling FormsAuth.SignIn.

Resources