First attempt at getting a little meta data on the client. Included a value for peppering all password hashing functions.

This commit is contained in:
2021-01-04 00:20:35 -06:00
parent e03610e390
commit 45dceef75e
7 changed files with 40 additions and 11 deletions
Binary file not shown.
+25 -4
View File
@@ -6,6 +6,10 @@ namespace SecureCore.Authentication
{ {
public class PasswordManager public class PasswordManager
{ {
//Add some pepper to the passwords for good measure:
//https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
public static string Pepper { get; } = "rVk/OwQUw01qy76Q+5WimPk+NdqUMMghftMXyJzzckOj/+eFn056PDYzBD61E/ZNjRdgiMK6RhcHEcdfpJdbcw==";
private static string ConnectionString = @"Server=DESKTOP-OEDDVKC\SQLEXPRESS;Database=main;Integrated Security=true;"; private static string ConnectionString = @"Server=DESKTOP-OEDDVKC\SQLEXPRESS;Database=main;Integrated Security=true;";
public PasswordManager() public PasswordManager()
@@ -18,14 +22,14 @@ namespace SecureCore.Authentication
ByteGenerator.GetRandomBytes(ref salt); ByteGenerator.GetRandomBytes(ref salt);
return (GetPasswordHash(password, salt), Convert.ToBase64String(salt)); return (GetHash(password, salt), Convert.ToBase64String(salt));
} }
public static bool PasswordIsValid(string password, string salt, string passwordHash) public static bool PasswordIsValid(string password, string salt, string passwordHash)
{ {
var saltBytes = Convert.FromBase64String(salt); var saltBytes = Convert.FromBase64String(salt);
return passwordHash == GetPasswordHash(password, saltBytes); return passwordHash == GetHash(password, saltBytes);
} }
public static (string PasswordHash, string SaltHash) GetUserPasswordHash(int userId) public static (string PasswordHash, string SaltHash) GetUserPasswordHash(int userId)
@@ -49,9 +53,26 @@ namespace SecureCore.Authentication
} }
} }
private static string GetPasswordHash(string password, byte[] salt) public static string HashStringData(string data, byte[] salt = null)
{ {
return Convert.ToBase64String(KeyDerivation.Pbkdf2(password, salt, Settings.KeyType, Settings.Iterations, Settings.KeySize)); if (salt == null) salt = new byte[0];
return GetHash(data, salt);
}
public static string HashStringData(string data, string salt = "")
{
var saltBytes = new byte[0];
if(!string.IsNullOrEmpty(salt))
saltBytes = Convert.FromBase64String(salt);
return GetHash(data, saltBytes);
}
private static string GetHash(string password, byte[] salt)
{
return Convert.ToBase64String(KeyDerivation.Pbkdf2($"{password}{Pepper}", salt, Settings.KeyType, Settings.Iterations, Settings.KeySize));
} }
} }
} }
+8 -4
View File
@@ -21,9 +21,11 @@ namespace SecureCore.Controllers
//Very the user has login data. //Very the user has login data.
if (!UserDataService.UserHasLoginData(info.UserName)) return Unauthorized("User doesn't have login creds"); if (!UserDataService.UserHasLoginData(info.UserName)) return Unauthorized("User doesn't have login creds");
var (password, saltHash) = UserDataService.GetUserPasswordHash(info.UserName); var (password, salt) = UserDataService.GetUserPasswordHash(info.UserName);
var agent = HttpContext.Request.Headers[Microsoft.Net.Http.Headers.HeaderNames.UserAgent];
var ip = PasswordManager.HashStringData(HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString(), salt);
if (PasswordManager.PasswordIsValid(info.Password, saltHash, password)) if (PasswordManager.PasswordIsValid(info.Password, salt, password))
{ {
if (HttpContext.Request.Cookies.ContainsKey("Session")) if (HttpContext.Request.Cookies.ContainsKey("Session"))
{ {
@@ -33,7 +35,7 @@ namespace SecureCore.Controllers
var sessionToken = SessionManager.CreateSessionToken(); var sessionToken = SessionManager.CreateSessionToken();
UserDataService.SetUserSessionToken(UserDataService.GetUserId(info.UserName), sessionToken, DateTime.Now.AddDays(7)); UserDataService.SetUserSessionToken(UserDataService.GetUserId(info.UserName), sessionToken, DateTime.Now.AddDays(7), agent, ip);
HttpContext.Response.Cookies.Append("Session", sessionToken, GetCookieOptions()); HttpContext.Response.Cookies.Append("Session", sessionToken, GetCookieOptions());
@@ -51,10 +53,12 @@ namespace SecureCore.Controllers
{ {
var (hash, salt) = PasswordManager.HashPassword(info.Password); var (hash, salt) = PasswordManager.HashPassword(info.Password);
var sessionToken = SessionManager.CreateSessionToken(); var sessionToken = SessionManager.CreateSessionToken();
var agent = HttpContext.Request.Headers[Microsoft.Net.Http.Headers.HeaderNames.UserAgent];
var ip = PasswordManager.HashStringData(HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString(), salt);
try try
{ {
var i = UserDataService.RegisterNewUser(info.UserName, info.Email, hash, salt, sessionToken, DateTime.Now.AddDays(7)); var i = UserDataService.RegisterNewUser(info.UserName, info.Email, hash, salt, sessionToken, DateTime.Now.AddDays(7),agent, ip);
HttpContext.Response.Cookies.Append("Session", sessionToken, GetCookieOptions()); HttpContext.Response.Cookies.Append("Session", sessionToken, GetCookieOptions());
+7 -3
View File
@@ -84,15 +84,17 @@ namespace SecureCore.Services
} }
} }
public static void SetUserSessionToken(int userId, string sessionToken, DateTime expirationDate) public static void SetUserSessionToken(int userId, string sessionToken, DateTime expirationDate, string userAgent, string ipAddress)
{ {
using (var connection = new SqlConnection(ConnectionString)) using (var connection = new SqlConnection(ConnectionString))
{ {
using (var command = new SqlCommand("INSERT INTO [Session]([Session Token], [Expiration Date], [User ID]) VALUES (@SessionToken, @ExpirationDate, @UserKey)", connection)) using (var command = new SqlCommand("INSERT INTO [Session]([Session Token], [Expiration Date], [User ID], [User Agent], [IP Address]) VALUES (@SessionToken, @ExpirationDate, @UserKey, @UserAgent, @IpAddress)", connection))
{ {
command.Parameters.AddWithValue("SessionToken", sessionToken); command.Parameters.AddWithValue("SessionToken", sessionToken);
command.Parameters.AddWithValue("ExpirationDate", expirationDate); command.Parameters.AddWithValue("ExpirationDate", expirationDate);
command.Parameters.AddWithValue("UserKey", userId); command.Parameters.AddWithValue("UserKey", userId);
command.Parameters.AddWithValue("UserAgent", userAgent);
command.Parameters.AddWithValue("IpAddress", ipAddress);
connection.Open(); connection.Open();
@@ -101,7 +103,7 @@ namespace SecureCore.Services
} }
} }
public static int RegisterNewUser(string userName, string email, string passwordHash, string saltHash, string sessionToken, DateTime expirationDate) public static int RegisterNewUser(string userName, string email, string passwordHash, string saltHash, string sessionToken, DateTime expirationDate, string userAgent, string ipAddress)
{ {
using (var connection = new SqlConnection(ConnectionString)) using (var connection = new SqlConnection(ConnectionString))
{ {
@@ -113,6 +115,8 @@ namespace SecureCore.Services
command.Parameters.AddWithValue("Salt", saltHash); command.Parameters.AddWithValue("Salt", saltHash);
command.Parameters.AddWithValue("SessionToken", sessionToken); command.Parameters.AddWithValue("SessionToken", sessionToken);
command.Parameters.AddWithValue("ExpirationDate", expirationDate); command.Parameters.AddWithValue("ExpirationDate", expirationDate);
command.Parameters.AddWithValue("UserAgent", userAgent);
command.Parameters.AddWithValue("IpAddress", ipAddress);
connection.Open(); connection.Open();
Binary file not shown.
Binary file not shown.