JWT tokens til når du logger ind og passwword bliver hashet nu

This commit is contained in:
Jeas0001 2025-03-19 13:22:39 +01:00
parent 5201e6e474
commit 05f09e57ff
6 changed files with 129 additions and 18 deletions

View File

@ -10,6 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3">
<PrivateAssets>all</PrivateAssets>

View File

@ -15,7 +15,7 @@ namespace Api.Controllers
_context = context;
}
// For at få json webtokens til at virke skriv [Authorize] over de endpoints
[HttpGet]
public async Task<IActionResult> GetDevices(int userId)
{

View File

@ -1,6 +1,10 @@
using Microsoft.AspNetCore.Mvc;
using Api.Models;
using Api.DBAccess;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace Api.Controllers
{
@ -9,10 +13,12 @@ namespace Api.Controllers
public class UserController : Controller
{
private readonly DBContext _context;
private readonly IConfiguration _configuration;
public UserController(DBContext context)
public UserController(DBContext context, IConfiguration configuration)
{
_context = context;
_configuration = configuration;
}
[HttpPost("Login")]
@ -20,8 +26,9 @@ namespace Api.Controllers
{
DbAccess dBAccess = new DbAccess(_context);
user = await dBAccess.Login(user);
if (user.Id == 0) { return BadRequest(new { error = "User can't be logged in" }); }
return Ok(user);
if (user.Id == 0) { return Unauthorized(new { error = "Invalid username or password" }); }
var token = GenerateJwtToken(user);
return Ok(new { token, user.UserName, user.Id });
}
[HttpPost("Create")]
@ -41,5 +48,37 @@ namespace Api.Controllers
if (!success) { return BadRequest(new { error = "User can't be edited" }); }
return Ok();
}
[HttpDelete("Delete/{userId}")]
public async Task<IActionResult> DeleteUser(int userId)
{
DbAccess dbAccess = new DbAccess(_context);
bool success = await dbAccess.DeleteUser(userId);
if (!success) { return BadRequest(new { error = "User can't be deleted" }); }
return Ok();
}
private string GenerateJwtToken(User user)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.Name, user.UserName)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes
(_configuration["JwtSettings:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
_configuration["JwtSettings:Issuer"],
_configuration["JwtSettings:Audience"],
claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}

View File

@ -1,5 +1,8 @@
using Microsoft.EntityFrameworkCore;
using Api.Models;
using System.Text;
using System.Runtime.Intrinsics.Arm;
using System.Security.Cryptography;
namespace Api.DBAccess
@ -28,6 +31,11 @@ namespace Api.DBAccess
{
user.Devices = new List<Device>();
}
string salt = Guid.NewGuid().ToString();
string hashedPassword = ComputeHash(user.Password, SHA256.Create(), salt);
user.Salt = salt;
user.Password = hashedPassword;
_context.Users.Add(user);
return await _context.SaveChangesAsync() == 1;
@ -36,10 +44,11 @@ namespace Api.DBAccess
public async Task<User> Login(User user)
{
var profile = await _context.Users.FirstAsync(u => u.UserName == user.UserName);
string hashedPassword = ComputeHash(user.Password, SHA256.Create(), profile.Salt);
if (profile.Password == user.Password)
if (hashedPassword == user.Password)
{
profile.Password = "";
return profile;
}
return new User();
@ -58,6 +67,25 @@ namespace Api.DBAccess
return await _context.SaveChangesAsync() == 1;
}
public async Task<bool> DeleteUser(int userId)
{
var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId);
if (user != null)
{
if (user.Devices != null && user.Devices.Count > 0)
{
foreach (var item in user.Devices)
{
var device = await _context.Devices.Include(d => d.Logs).FirstOrDefaultAsync(d => d.Id == item.Id);
if (device != null) { _context.Devices.Remove(device); }
}
}
_context.Users.Remove(user);
return await _context.SaveChangesAsync() == 1;
}
return false;
}
public async Task<List<Device>> ReadDevices(int userId)
{
var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId);
@ -82,17 +110,6 @@ namespace Api.DBAccess
return await _context.SaveChangesAsync() == 1;
}
public async Task<List<TemperatureLogs>> ReadLogs(int deviceId)
{
var device = await _context.Devices.Include(d => d.Logs).FirstOrDefaultAsync(d => d.Id == deviceId);
if (device == null || device.Logs == null) { return new List<TemperatureLogs>(); }
var logs = device.Logs;
return logs;
}
public async Task<bool> UpdateDevice(Device device, int deviceId)
{
var device1 = await _context.Devices.FirstAsync(u => u.Id == deviceId);
@ -105,5 +122,31 @@ namespace Api.DBAccess
return await _context.SaveChangesAsync() == 1;
}
public async Task<List<TemperatureLogs>> ReadLogs(int deviceId)
{
var device = await _context.Devices.Include(d => d.Logs).FirstOrDefaultAsync(d => d.Id == deviceId);
if (device == null || device.Logs == null) { return new List<TemperatureLogs>(); }
var logs = device.Logs;
return logs;
}
private static string ComputeHash(string input, HashAlgorithm algorithm, string salt)
{
Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
Byte[] saltBytes = Encoding.UTF8.GetBytes(salt);
// Combine salt and input bytes
Byte[] saltedInput = new Byte[saltBytes.Length + inputBytes.Length];
saltBytes.CopyTo(saltedInput, 0);
inputBytes.CopyTo(saltedInput, saltBytes.Length);
Byte[] hashedBytes = algorithm.ComputeHash(saltedInput);
return BitConverter.ToString(hashedBytes);
}
}
}

View File

@ -10,6 +10,8 @@
public string Email { get; set; }
public string Salt { get; set; }
public List<Device>? Devices { get; set; }
}
}

View File

@ -1,5 +1,8 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Text;
namespace Api
{
@ -22,6 +25,29 @@ namespace Api
services.AddControllers();
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = _configuration["JwtSettings:Issuer"],
ValidAudience = _configuration["JwtSettings:Audience"],
IssuerSigningKey = new SymmetricSecurityKey
(
Encoding.UTF8.GetBytes(_configuration["JwtSettings:Key"])
),
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true
};
});
services.AddCors(options =>
{
options.AddPolicy("AllowAll", builder =>