summaryrefslogtreecommitdiffstats
path: root/api/WhatApi/Endpoints/LoginEndpoint.cs
diff options
context:
space:
mode:
Diffstat (limited to 'api/WhatApi/Endpoints/LoginEndpoint.cs')
-rw-r--r--api/WhatApi/Endpoints/LoginEndpoint.cs52
1 files changed, 52 insertions, 0 deletions
diff --git a/api/WhatApi/Endpoints/LoginEndpoint.cs b/api/WhatApi/Endpoints/LoginEndpoint.cs
new file mode 100644
index 0000000..ee697ef
--- /dev/null
+++ b/api/WhatApi/Endpoints/LoginEndpoint.cs
@@ -0,0 +1,52 @@
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.IdentityModel.Tokens;
+
+namespace WhatApi.Endpoints;
+
+public class LoginEndpoint(AppDatabase db, IConfiguration configuration) : BaseEndpoint
+{
+ public class LoginRequest
+ {
+ public required string Username { get; set; }
+ public required string Password { get; set; }
+ }
+
+ [HttpPost("~/login")]
+ public async Task<ActionResult> HandleAsync(LoginRequest login, CancellationToken ct = default) {
+ var user = await db.Users.FirstOrDefaultAsync(c => c.Name == login.Username, ct);
+ if (user?.PasswordHash is null) return Unauthorized();
+
+ var verificationResult = PasswordHasher.VerifyHashedPassword(user.PasswordHash, login.Password);
+ if (verificationResult == PasswordVerificationResult.Failed) return Unauthorized();
+
+ var tokenEntropy = configuration.GetValue<string>(Constants.Env.TokenEntropy);
+
+ ArgumentException.ThrowIfNullOrWhiteSpace(tokenEntropy);
+
+ var key = Encoding.ASCII.GetBytes(tokenEntropy);
+ var tokenIssuer = configuration.GetValue<string>(Constants.Env.TokenIssuer);
+ var tokenAudience = configuration.GetValue<string>(Constants.Env.TokenAudience);
+ var tokenHandler = new JwtSecurityTokenHandler();
+
+ var tokenDescriptor = new SecurityTokenDescriptor {
+ Subject = new ClaimsIdentity([
+ new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
+ new Claim(ClaimTypes.Name, user.Name)
+ ]),
+ Expires = DateTime.UtcNow.AddMinutes(60),
+ Issuer = tokenIssuer,
+ Audience = tokenAudience,
+ SigningCredentials = new SigningCredentials(
+ new SymmetricSecurityKey(key),
+ SecurityAlgorithms.HmacSha256Signature)
+ };
+
+ var token = tokenHandler.CreateToken(tokenDescriptor);
+ var tokenString = tokenHandler.WriteToken(token);
+ user.SetLastSeen();
+ await db.SaveChangesAsync(ct);
+ return Ok(tokenString);
+ }
+} \ No newline at end of file