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:
Binary file not shown.
@@ -6,6 +6,10 @@ namespace SecureCore.Authentication
|
||||
{
|
||||
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;";
|
||||
|
||||
public PasswordManager()
|
||||
@@ -18,14 +22,14 @@ namespace SecureCore.Authentication
|
||||
|
||||
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)
|
||||
{
|
||||
var saltBytes = Convert.FromBase64String(salt);
|
||||
|
||||
return passwordHash == GetPasswordHash(password, saltBytes);
|
||||
return passwordHash == GetHash(password, saltBytes);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@ namespace SecureCore.Controllers
|
||||
//Very the user has login data.
|
||||
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"))
|
||||
{
|
||||
@@ -33,7 +35,7 @@ namespace SecureCore.Controllers
|
||||
|
||||
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());
|
||||
|
||||
@@ -51,10 +53,12 @@ namespace SecureCore.Controllers
|
||||
{
|
||||
var (hash, salt) = PasswordManager.HashPassword(info.Password);
|
||||
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
|
||||
{
|
||||
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());
|
||||
|
||||
|
||||
@@ -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 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("ExpirationDate", expirationDate);
|
||||
command.Parameters.AddWithValue("UserKey", userId);
|
||||
command.Parameters.AddWithValue("UserAgent", userAgent);
|
||||
command.Parameters.AddWithValue("IpAddress", ipAddress);
|
||||
|
||||
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))
|
||||
{
|
||||
@@ -113,6 +115,8 @@ namespace SecureCore.Services
|
||||
command.Parameters.AddWithValue("Salt", saltHash);
|
||||
command.Parameters.AddWithValue("SessionToken", sessionToken);
|
||||
command.Parameters.AddWithValue("ExpirationDate", expirationDate);
|
||||
command.Parameters.AddWithValue("UserAgent", userAgent);
|
||||
command.Parameters.AddWithValue("IpAddress", ipAddress);
|
||||
|
||||
connection.Open();
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user