Added more validation to the various AuthController functions.

This commit is contained in:
2021-01-15 09:41:35 -06:00
parent 8e9824f497
commit 5a9d3621fe
4 changed files with 68 additions and 15 deletions
@@ -47,7 +47,6 @@ namespace SecureCore.Authentication
public static void InsertPasswordResetRequest(string email, string sessionToken, DateTime expirationDate, string userAgent, string ipAddress, string connectionString)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("LogPasswordResetRequest", connection) { CommandType = CommandType.StoredProcedure };
command.Parameters.AddWithValue("SessionToken", sessionToken);
@@ -78,7 +77,6 @@ namespace SecureCore.Authentication
public static (string PasswordHash, string Salt) GetPasswordHashAndSalt(string username, string connectionString)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("SELECT [Password Hash], [Salt] FROM dbo.GetUserPasswordHashAndSalt(@Username)", connection);
command.Parameters.AddWithValue("Username", username);
@@ -20,7 +20,6 @@ namespace SecureCore.Authentication
public static bool IsSessionTokenValid(string sessionToken, string connectionString, bool isResetToken = false)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("ValidateSessionToken", connection) { CommandType = CommandType.StoredProcedure };
command.Parameters.AddWithValue("SessionToken", sessionToken);
@@ -36,7 +35,6 @@ namespace SecureCore.Authentication
public static void Logout(string sessionToken, string connectionString)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("LogoutUser", connection) { CommandType = CommandType.StoredProcedure };
command.Parameters.AddWithValue("SessionToken", sessionToken);
@@ -49,7 +47,6 @@ namespace SecureCore.Authentication
public static void Login(string userName, string sessionToken, DateTime expirationDate, string userAgent, string ipAddress, string connectionString)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("LoginUser", connection) { CommandType = CommandType.StoredProcedure };
command.Parameters.AddWithValue("SessionToken", sessionToken);
+35 -8
View File
@@ -17,7 +17,7 @@ namespace SecureCore.Controllers
public IActionResult Login([FromBody] UserInformation.LoginData info)
{
AppSettingsManager.TryGetConnectionStringByName("MainDataConnectionString", out string connectionString);
//TODO: see if the request has an active session key so we don't spam out new keys like mad
try
{
if (HttpContext.Request.Cookies.ContainsKey("Session"))
@@ -27,6 +27,10 @@ namespace SecureCore.Controllers
//Verify that the username provided is valid, i.e. no whitespace, special characters, etc.
var result = UserDataService.IsUsernameValid(info.Username);
//If the name isn't valid, return the error message to the user.
if (!result.IsValid) return Unauthorized(result.Message);
//Now make sure the password is valid.
result = PasswordManager.IsPasswordValid(info.Password);
if (!result.IsValid) return Unauthorized(result.Message);
//Next try to get the user's login data, if the fuction returns empty strings, then the user isn't a registered name.
@@ -34,10 +38,6 @@ namespace SecureCore.Controllers
//If the user name isn't in the system, then simply return a generic error message about something not being right.
if (password == string.Empty) return Unauthorized("User name or password is not correct.");
result = PasswordManager.IsPasswordValid(info.Password);
if (!result.IsValid) return Unauthorized(result.Message);
if(!PasswordManager.IsPasswordAMatch(info.Password, salt, password)) return Unauthorized("User name or password is not correct.");
var sessionToken = SessionManager.CreateSessionToken();
@@ -62,6 +62,7 @@ namespace SecureCore.Controllers
[AcceptVerbs("POST")]
public IActionResult Register([FromBody] UserInformation.RegistrationData info)
{
AppSettingsManager.TryGetConnectionStringByName("MainDataConnectionString", out string connectionString);
//Verify that the username provided is valid, i.e. no whitespace, special characters, etc.
var result = UserDataService.IsUsernameValid(info.Username);
//If the name isn't valid, return the error message to the user.
@@ -71,7 +72,12 @@ namespace SecureCore.Controllers
if (!result.IsValid) return Unauthorized(result.Message);
AppSettingsManager.TryGetConnectionStringByName("MainDataConnectionString", out string connectionString);
result = UserDataService.IsEmailValid(info.Email);
if (!result.IsValid) return Unauthorized(result.Message);
if (UserDataService.IsEmailInUse(info.Email, connectionString)) return Unauthorized("This email is already in use.");
var (hash, salt) = PasswordManager.HashPassword(info.Password);
var sessionToken = SessionManager.CreateSessionToken();
var agent = HttpContext.Request.Headers[Microsoft.Net.Http.Headers.HeaderNames.UserAgent];
@@ -97,9 +103,18 @@ namespace SecureCore.Controllers
[AcceptVerbs("POST")]
public IActionResult Logout()
{
if (!HttpContext.Request.Cookies.ContainsKey("Session")) return Ok();
AppSettingsManager.TryGetConnectionStringByName("MainDataConnectionString", out string connectionString);
SessionManager.Logout(HttpContext.Request.Cookies["Session"], connectionString);
try
{
SessionManager.Logout(HttpContext.Request.Cookies["Session"], connectionString);
}
catch(Exception e)
{
//TODO: decide what to do here. If the SQL fails to clear the token from the database, do we want to clear the token cookie?
}
HttpContext.Response.Cookies.Delete("Session");
@@ -114,7 +129,11 @@ namespace SecureCore.Controllers
try
{
if (!SessionManager.IsSessionTokenValid(token, connectionString, true)) return Unauthorized("Token invalid");
if (!SessionManager.IsSessionTokenValid(token, connectionString, true)) return Unauthorized("This link has expired, please request a new email reset link.");
var (IsValid, Message) = PasswordManager.IsPasswordValid(password);
if (!IsValid) return Unauthorized(Message);
var (Hash, Salt) = PasswordManager.HashPassword(password);
@@ -133,6 +152,14 @@ namespace SecureCore.Controllers
public IActionResult CreatePasswordResetLink([FromBody] string email)
{
AppSettingsManager.TryGetConnectionStringByName("MainDataConnectionString", out string connectionString);
//Validate the email input.
var (IsValid, Message) = UserDataService.IsEmailValid(email);
if (!IsValid) return Unauthorized(Message);
//If its a properly formatted email, then check to see if its in use by anyone.
if (!UserDataService.IsEmailInUse(email, connectionString)) return Unauthorized("Email is not valid.");
var token = SessionManager.CreateSessionToken();
var agent = HttpContext.Request.Headers[Microsoft.Net.Http.Headers.HeaderNames.UserAgent];
var ip = PasswordManager.HashStringData(Request.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString());
+32 -1
View File
@@ -11,6 +11,7 @@ namespace SecureCore.Services
{
//
public static int UserNameMaxLength { get; } = 64;
public static int EmailMaxLength { get; } = 512;
public static (bool IsValid, string Message) IsUsernameValid(string userName)
{
@@ -29,7 +30,6 @@ namespace SecureCore.Services
public static int RegisterNewUser(string userName, string email, string passwordHash, string saltHash, string sessionToken, DateTime expirationDate, string userAgent, string ipAddress, string connectionString)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("RegisterNewUser", connection) { CommandType = CommandType.StoredProcedure };
command.Parameters.AddWithValue("UserName", userName);
@@ -47,5 +47,36 @@ namespace SecureCore.Services
return Convert.ToInt32(result);
}
public static bool IsEmailInUse(string email, string connectionString)
{
using var connection = new SqlConnection(connectionString);
using var command = new SqlCommand("SELECT dbo.EmailInUse(@Email) AS InUse", connection);
command.Parameters.AddWithValue("Email", email);
connection.Open();
return Convert.ToBoolean(command.ExecuteScalar());
}
public static (bool IsValid, string Message) IsEmailValid(string email)
{
if (email.Length > EmailMaxLength) return (false, $"Email exceeds the maximum length of {EmailMaxLength} characters.");
//Code taken from user "Cogwheel" on StackOverflow: https://stackoverflow.com/questions/1365407/c-sharp-code-to-validate-email-address
try
{
var addr = new System.Net.Mail.MailAddress(email);
if (addr.Address != email) return (false, $"The provided email is not in the correct format.");
return (true, string.Empty);
}
catch
{
return (false, $"The provided email is not in the correct format.");
}
}
}
}