MVC 3 where to encrypt the user's password? - asp.net-mvc-3

I have my own password encryption dll that I am using to check the user's password when they login, this is referenced in my User entity.
Now I have created the ability for a user to register which is working fine, apart from the passwords are yet to be encrypted.
My question is quite simple, where should I put the encryption of the new user's password? I'm not sure as I am aware that the user's password shouldn't be transmitted in plain text, therefore I don't know where the best place to call the encryption function:
User Entity (where the encryption dll is already used for validation).
The User repository where the save user method is.
The User controller where the user creation views are controlled.
Somewhere else that I haven't considered!
Thanks very much

First of all, for client - server communication, I would suggest you to use SSL for the sensitive information (like passwords) not to be transferred in plain text format.
Afterwards, it's the common practice not to save passwords anywhere (even with encryption, but the hashed values of them.
You can put the hash function to the set method of password property. Here is an example:
public class Member
{
private string _username;
public string Username
{
get { return _username; }
set { _username = value.ToLowerInvariant(); }
}
public string Passhash {get;set;}
public void SetPassword(string password)
{
Passhash = Crypto.Hash(password);
}
public bool CheckPassword(string password)
{
return string.Equals(Passhash, Crypto.Hash(password));
}
}
public static class Crypto
{
public static string Hash(string value)
{
return Convert.ToBase64String(
System.Security.Cryptography.SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes(value)));
}
}
Edit:
As Craig Stuntz pointed out, the Hash code in this example is very simple. See the following post for a more secure way to hash your password: Hashing passwords with MD5 or sha-256 C#

In a service layer method that will be responsible for doing 2 things:
call your encryption layer to hash the password (not to encrypt it)
call your user repository to persist the user entity to the database with the hashed password
The controller action will of course talk to the service layer.

Don't do your own password hashing and don't even think about encrypting passwords.
The effort of making this secure are tremendous. Use an existing method based on publicly available specs and algorithms.

//ENCODE
public string base64Encode(string sData)
{
try
{
byte[] encData_byte = new byte[sData.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(sData);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
catch(Exception ex)
{
throw new Exception("Error in base64Encode" + ex.Message);
}
}
//DECODE
public string base64Decode(string sData)
{
try
{
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(sData);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
catch (Exception ex)
{
throw new Exception("Error in base64Decode" + ex.Message);
}
}
How to call
string encode= base64Encode(val);
string decode= base64Decode(val);
This is very helpful to decode and encode your string(password)

Related

BCrypt PasswordHasher:- FormatException: The input is not a valid Base-64 string

I went through almost all the related questions regarding this issue and could not found a similar situation or a reliable answer for my problem below.
Problem:
I am doing an ASP.NET Core MVC project. I employ Identity UI for user authentication and authorization. I have override the Idetity User default password hasher: 'PasswordHasher' which is also implemented from 'IPasswordHasher' interface (ASP.NET Identity Version 2: PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations), and implemented my own class as follows:
BCryptPasswordHasher.cs
using Microsoft.AspNetCore.Identity;
using System;
using System.Text;
namespace WATERrhythmWeb
{
public class BCryptPasswordHasher<TUser> : PasswordHasher<TUser> where TUser : class
{
readonly BCryptPasswordSettings _settings;
public BCryptPasswordHasher()
{
}
public BCryptPasswordHasher(BCryptPasswordSettings settings)
{
_settings = settings;
}
public override PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword)
{
if (hashedPassword == null) { throw new ArgumentNullException(nameof(hashedPassword)); }
if (providedPassword == null) { throw new ArgumentNullException(nameof(providedPassword)); }
byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword);
// read the format marker from the hashed password
if (decodedHashedPassword.Length == 0)
{
return PasswordVerificationResult.Failed;
}
// ASP.NET Core uses 0x00 and 0x01, so we start at the other end
if (decodedHashedPassword[0] == 0xFF)
{
if (VerifyHashedPasswordBcrypt(decodedHashedPassword, providedPassword))
{
// This is an old password hash format - the caller needs to rehash if we're not running in an older compat mode.
return _settings.RehashPasswords
? PasswordVerificationResult.SuccessRehashNeeded
: PasswordVerificationResult.Success;
}
else
{
return PasswordVerificationResult.Failed;
}
}
return base.VerifyHashedPassword(user, hashedPassword, providedPassword);
}
private static bool VerifyHashedPasswordBcrypt(byte[] hashedPassword, string password)
{
if (hashedPassword.Length < 2)
{
return false; // bad size
}
//convert back to string for BCrypt, ignoring first byte
var storedHash = Encoding.UTF8.GetString(hashedPassword, 1, hashedPassword.Length - 1);
return BCrypt.Net.BCrypt.Verify(password, storedHash);
}
public override string HashPassword(TUser user, string password)
{
//throw new NotImplementedException();
return BCrypt.Net.BCrypt.HashPassword(password);
}
}
}
The user registration occurs successfully and I get following
hashed string for the password 'D4%%6gf45'
$2a$10$vUHdbnKLplTz4d4VgG.cHOx3O2jMAaeH5mFvNTVuf4wqoEtvRx442
Nevertheless, when the same user tries to log in, I am getting the
following error. (It is obvious this happen when the hashed password
in the database is verified with the user input password):
FormatException: The input is not a valid Base-64 string as it
contains a non-base 64 character, more than two padding characters, or
an illegal character among the padding characters.
The error is from the following line of code in
PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword) method of PasswordHasher
class, where hashedPassword is being converted to a base64 string.
byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword);
Can somebody please explain to me how to resolve this issue?
Thank you.

getCurrentUser not going null even i logged out using Parse sdk

How to manage session with Parse SDK?
I have used SharedPrefences to locally store the session user info, and checked on the start whether move the user to Home Screen or Login screen. Is this the right process or there is an option to maintain session automatically without using SharedPrefecences.
Just use SharedPrefences according to your Login and SignUp Activity besides you can also use Parse Session Management..
I don't know the solution to the first problem as even I failed to get it working. One of the workaround is to store the user information in shared preferences temporarily when he/she logs in and clear them when user logs out of the app.
private void setUserPreferences(String username){
SharedPreferences sharedPreferences=getSharedPreferences("DEFAULT_SP", Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit();
editor.putString("username", username);
editor.commit();
}
private String getUserPreferences(){
SharedPreferences sharedPreferences=getSharedPreferences("DEFAULT_SP", Context.MODE_PRIVATE);
return sharedPreferences.getString("username", null);
}
private void clearUserPreferences(){
SharedPreferences sharedPreferences=getSharedPreferences("DEFAULT_SP", Context.MODE_PRIVATE);
SharedPreferences.Editor editor=sharedPreferences.edit();
editor.clear();
editor.commit();
}
Now you can call these functions when you log into the app and log out of the app. Not a viable solution but its all what I've got for the time being.
Also, you cannot login using email-id in parse, you will need username for that. So what you can do is to find the username associated with that email and then log into parse using that username.
private String mUsername=null;
private void getParseUsername(String email){
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
query.whereEqualTo("email", email);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> parseList, ParseException e) {
if (e == null) {
//assuming you don't have same email id's in the parse database
//, I don't think that's even allowed.
mUsername = parseList.get(0).getString("");
} else {
Log.d("parseList", "Error: " + e.getMessage());
}
}
});
}
For retrieving user info, you can simply type this code:
ParseUser.getCurrentUser().getUsername()
For your fourth question, if I understand it correctly, you don't want user to register with a mobile number which is already registered.
private boolean mDuplicatePhoneNo=false;
private void isPhoneNumberDuplicate(String phoneNo)
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
//Here phone_no is the field name in which you have stored your phone numbers
//Make sure they are in string format.
query.whereEqualTo("phone_no", phone);
query.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> parseList, ParseException e) {
if (e == null) {
if(phoneNo.equals(parseList.get(0).getString("phone_no"))){
mDuplicatePhoneNo=true;
}
} else {
Log.d("parseList", "Error: " + e.getMessage());
}
}
});
Also make sure to visit https://parse.com/docs/android/guide#getting-started
for a better guide.

Passing a variables in C#

I am trying to pass a variable that identifies a staff member from their login details to the next screen to populate the Tester ID box.
Would I be better using a global variable that is then read when the next screen is set up or would I be better to put it into a variable and send it to the next screen?
The login code sits as follows:
public Login()
{
InitializeComponent();
}
private void LoginButton_Click(object sender, EventArgs e)
{
String Username1 = StaffUsername.Text;
String Password1 = StaffPassword.Text;
String HardUser = "Test";
String HardPass = "Merlin123";
if (Username1 == "" && Password1 == "")
{
MessageBox.Show("Please Enter Login Id and Password");
}
else
{
if (Username1.Equals(HardUser) && Password1.Equals(HardPass))
{
this.Hide();
AddingClients M1 = new AddingClients();
M1.Show();
}
else{
this.Hide();
Login Lg = new Login();
Lg.Show();
MessageBox.Show("Incorrect Username or Password Entered");
}
}
}
}
}
I am using a hardcoded username and password for now, but in the actual program, I would have this call on a database and compare the username and the password and then go through to the next screen.
Would lit be better to have a global variable that the login action throws over to the next screen or would it be easier having a variable that the next screen reads and then populates the text box required? How would I go about this?
Thanks
The way you do this is to use the Thread.CurrentPrincipal.
Once the user is confirmed to be who they say they are, you can do:
private static void SignUserIn(string userName)
{
GenericIdentity identity = new GenericIdentity(userName, null);
Thread.CurrentPrincipal = new GenericPrincipal(identity);
}
Then whenever you need the userName, you use Thread.CurrentPrincipal.Identity.Name.
To extend this a little further, its probably best to abstract this a little bit, so you can swap in and out providers e.g. you might want to use Windows Authentication.
So you could do it like this:
public interface IAuthenticator
{
bool IsValidUser ( string username, string password );
IPrincipal SignInUser ( string username );
void SignOutCurrentUser();
}
public class DbAuthenticator : IAuthenticator
{
public bool IsValidUser ( string username, string password )
{
// Check user here and return bool if valid
}
public void SignInUser(string userName, string[] roles = null)
{
GenericIdentity identity = new GenericIdentity(userName, roles);
Thread.CurrentPrincipal = new GenericPrincipal(identity);
return Thread.CurrentPrincipal;
}
public void SignOutUser()
{
Thread.CurrentPrincipal = WindowsPrincipal.GetCurrent();
}
}
Then in your code, inject the authenticator using some sort of DI pattern. So MEF would be like this:
[Export(typeof(IAuthenticator))]
public interface IAuthenticator { }
And in your form:
[Import]
internal IAuthenticator authenticator;
private static void SignUserIn(string userName)
{
authenticator.SignUserIn(username);
}
You should have a User object and pass it to other pages and functions. That way they become more testable.
But you also need to store the object somewhere globally so you can retrieve the currently logged in user when needed. The problem with that is that piece of code then depends on that user storage existing/working, but if it's only one place it's okay.
PS: your title should be: pass the user on or store globally?

How to initialize information on authorization [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Ok, so this seems like a common need. A little googling finds a lot of ways to do this. I'm interested in the most "mvc correct" way to do it.
I have, in the upper right hand corner of my app, a greeting that says Hello FirstName LastName. Now, it's quite easy to get at the username of the logged in user, through the IPrincipal (aka User.Identity.Name). However, this won't give me the First and Last name of the user. I have to hit the Membership API to get that.
Hitting the Membership API has its drawbacks. It hits the database every time, which adds an additional db access to every served page. It's easy enough to set some session variables on login, but this only works for that session. If the user clicks the "Remember me", then no login occurs next time and i have to still load these values.
I could create my own membership provider to do some cacheing, but that's a lot of work for a more or less single purpose.
I could use Application_AuthenticateRequest and hit the membership api and store the values in session variables, or something similar. This is ok, but seems a little brute force.
I could register a global filter and handle OnAuthenticate, essentially doing the same thing. This seems a little better, but i'm unusre of the ramifications here.
I could derive a base controller, and simly add properties to provide this information. This seems a bit "old school", and I hate having to make a base class for a single purpose.
I could create a cacheing static method that would get the information on first access. This is basically not much better than a singleton.
I could also create my own IPrincipal, but that means casting it every time to get at the data, and that seems clunky. I could wrap that in another class to simplify it, but still...
I could store the data in the forms authentication cookie, and get it from there. There's some tools available to make that easier.
Are there any methods I haven't thought of? And what is the most "mvc correct" way of doing it?
I think the best way is using Cookies. Here is the solution I used in my project:
Create a class to save data in it
[DataContract]
[Serializable()]
public class AuthData {
[DataMember]
public String UserName { get; set; }
[DataMember]
public String FirstName { get; set; }
[DataMember]
public String LastName { get; set; }
[DataMember]
public String Email { get; set; }
// any other property you need to a light-store for each user
public override string ToString() {
string result = "";
try {
using (MemoryStream stream = new MemoryStream()) {
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
result = Convert.ToBase64String(stream.ToArray());
}
} catch (Exception ex) {
throw new HttpException(ex.Message);
}
return result;
}
static public AuthData FromString(String data) {
AuthData result = null;
try {
byte[] array = Convert.FromBase64String(data);
using (MemoryStream stream = new MemoryStream(array)) {
stream.Seek(0, 0);
BinaryFormatter formatter = new BinaryFormatter();
result = (AuthData)formatter.Deserialize(stream, null);
}
} catch (Exception ex) {
throw new HttpException(ex.Message);
}
return result;
}
}
Signin method:
public static bool SignIn(string userName, string password, bool persistent){
if (Membership.ValidateUser(userName, password)) {
SetAuthCookie(userName, persistent);
return true;
}
return false;
}
Setting AuthCookie:
public static void SetAuthCookie(string userName, bool persistent) {
AuthData data = GetAuthDataFromDB(); // implement this method to retrieve data from database as an AuthData object
var ticket = new FormsAuthenticationTicket(
1,
userName,
DateTime.Now,
DateTime.Now.Add(FormsAuthentication.Timeout),
persistent,
data.ToString(),
FormsAuthentication.FormsCookiePath
);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
cookie.Expires = DateTime.Now.Add(FormsAuthentication.Timeout);
cookie.HttpOnly = false;
cookie.Path = FormsAuthentication.FormsCookiePath;
HttpContext.Current.Response.Cookies.Add(cookie);
}
Getting AuthCookie:
public static AuthData GetAuthCookie() {
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated && HttpContext.Current.User.Identity is FormsIdentity) {
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
var data = AuthData.FromString(ticket.UserData);
HttpContext.Current.Items["AuthDataContext"] = data;
return data;
}
return null;
}
In ControllerBase:
private AuthData _authData;
private bool _authDataIsChecked;
public AuthData AuthData {
get {
_authData = System.Web.HttpContext.Current.Items["AuthDataContext"] as AuthData;
if (!_authDataIsChecked && _authData == null) {
SignService.GetAuthCookie();
_authData = System.Web.HttpContext.Current.Items["AuthDataContext"] as AuthData;
_authDataIsChecked = true;
}
return _authData;
}
}
The FormsAuthenticationExtensions project solves this problem storing the additional information in the auth cookie itself. http://formsauthext.codeplex.com/
This spares the database hit, and lives as long as the auth cookie, hence it works if the users asks for "remember me". It can be used the same way (in MVC too) as the standard forms authentication.
To your question, what is the most MVCisch way: I would first decide where I want to keep the information. This part of the question is rather independent of the MVC framework as the concepts (session, post data, cookies, etc.) are given with or without it.
I will implement and extend the IPrincipal and IIdentity, so when you access User.Identity you will find LastName and FirstName.
This way is better imo.
For my projects I have extended IIdentity and IPrincipal with my classes adding the properties I always need "to be there". To me is not this big work, I mean, there are only a bunch of methods that need to be implemented.
For IIdentity the interface requirement are only AuthenticationType (string), IsAuthenticated (bool) and Name (string).
While in IPrincipal Identity (IIDentity) and IsInRole (boolean)

Login Procedure that does not require a Email Address

I have been asked to create a site where the user isn't required to provide a email to login because of privacy issues. In the past I have simple said this isn't advisable but in this case the client has stringently requested it. My initial thoughts are to potentially create administrators with a email whom could create generic logins (username and a password) and pass them to members of there group on site. Then at least I have a point of contact for login resets and such.
Has anyone had any experience with such situations where they have needed to create logins without the use of a email address? Could you direct me towards any relevant materials or tutorials that may be of use. I'm using MVC3 to develop this project.
I hope I understand your question right and you want to implement a login using username and password instead of email adress and password.
In that case you would have to implement your own custom membership provider and a custom roleprovider if needed.
You want to check the following page for more information:
Custom Membership Provider # Codeproject
EDIT
Fyi you dont need to implement every function - just implement the ones you need.
Custom membership provider from some of my older mvc3 projects. Removed most of the not-implemented functions for shorter code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace Domain.Models
{
public class PlatformMembershipProvider : MembershipProvider
{
public SalesModelContainer ******** = new SalesModelContainer();
public override bool ChangePassword(string username, string oldPassword, string newPassword)
{
var user = ********.UserSet.Single(s => s.Email == username);
if (user.Password == oldPassword)
{
user.Password = newPassword;
return true;
}
else
{
return false;
}
}
public override string GetUserNameByEmail(string email)
{
var user = ********.UserSet.Single(s => s.Email == email);
return user.CompanyName;
}
public override void UpdateUser(System.Web.Security.MembershipUser user)
{
throw new NotImplementedException();
}
//TODO: use MD5 for password encryption
public override bool ValidateUser(string username, string password)
{
bool returnValue;
var user = ********.UserSet.SingleOrDefault(s => (s.Email == username) && (s.Password == password));
if (user != null)
returnValue = true;
else
returnValue = false;
return returnValue;
}
}
}

Resources