125 lines
4.5 KiB
C#
125 lines
4.5 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using MySql.Data.MySqlClient;
|
|
using Newtonsoft.Json;
|
|
using System.Security.Claims;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace Server
|
|
{
|
|
public class Login
|
|
{
|
|
private static string secretKey = "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk";
|
|
|
|
public static string GenerateToken(string user)
|
|
{
|
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
|
|
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
|
|
|
var token = new JwtSecurityToken(
|
|
issuer: "TimeLogServer",
|
|
audience: "TimeLogWebsite",
|
|
claims: new[]
|
|
{
|
|
new Claim(ClaimTypes.Name, user)
|
|
},
|
|
expires: DateTime.Now.AddHours(2),
|
|
signingCredentials: creds
|
|
);
|
|
|
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
|
}
|
|
|
|
public static bool VerifyPassword(string enteredPassword, string storedHash)
|
|
{
|
|
byte[] hashBytes = Convert.FromBase64String(storedHash);
|
|
|
|
// Extract the salt from the stored hash
|
|
byte[] salt = new byte[16];
|
|
Array.Copy(hashBytes, 0, salt, 0, 16);
|
|
|
|
// Hash the entered password with the stored salt
|
|
using (var pbkdf2 = new Rfc2898DeriveBytes(enteredPassword, salt, 10000, HashAlgorithmName.SHA256))
|
|
{
|
|
byte[] newHash = pbkdf2.GetBytes(32);
|
|
|
|
// Compare the computed hash with the stored hash
|
|
for (int i = 0; i < 32; i++)
|
|
{
|
|
if (newHash[i] != hashBytes[i + 16])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public static void run(MySqlConnection conn, HttpListenerRequest request, HttpListenerResponse response)
|
|
{
|
|
try
|
|
{
|
|
conn.Open();
|
|
// prepare SQL query
|
|
MySqlCommand cmd = new MySqlCommand();
|
|
cmd.Connection = conn;
|
|
cmd.CommandText = @"SELECT u.id,password FROM User u
|
|
INNER JOIN Password p ON p.user=u.id
|
|
WHERE mail=@mail";
|
|
var queryString = request.QueryString;
|
|
string? mail = queryString["mail"];
|
|
string? password = queryString["password"];
|
|
cmd.Parameters.AddWithValue("@mail", mail);
|
|
cmd.Parameters.AddWithValue("@password", password);
|
|
// execute query and read results
|
|
MySqlDataReader reader = cmd.ExecuteReader();
|
|
|
|
string? userId = "";
|
|
string? hashedPass = "";
|
|
string? jsonResponse;
|
|
while (reader.Read())
|
|
{
|
|
userId = Convert.ToString(reader["id"]);
|
|
hashedPass = Convert.ToString(reader["password"]);
|
|
}
|
|
|
|
// check username
|
|
if (string.IsNullOrEmpty(userId) && string.IsNullOrEmpty(hashedPass))
|
|
{
|
|
throw new Exception("Error:Invalid Username or Password");
|
|
}
|
|
|
|
//check password
|
|
if (string.IsNullOrEmpty(password)
|
|
|| string.IsNullOrEmpty(hashedPass)
|
|
|| VerifyPassword(password, Convert.ToString(hashedPass)))
|
|
{
|
|
throw new Exception("Error:Invalid Username or Password");
|
|
}
|
|
|
|
jsonResponse = JsonConvert.SerializeObject(GenerateToken(userId));
|
|
|
|
// prepare response
|
|
byte[] buffer = Encoding.UTF8.GetBytes(jsonResponse);
|
|
response.ContentType = "application/json";
|
|
response.ContentLength64 = buffer.Length;
|
|
response.OutputStream.Write(buffer, 0, buffer.Length);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
string errorMessage = $"Error: {ex.Message}";
|
|
byte[] buffer = Encoding.UTF8.GetBytes(errorMessage);
|
|
response.ContentType = "text/plain";
|
|
response.ContentLength64 = buffer.Length;
|
|
response.OutputStream.Write(buffer, 0, buffer.Length);
|
|
}
|
|
finally
|
|
{
|
|
// close db connection
|
|
conn.Close();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|