summaryrefslogtreecommitdiffstats
path: root/api/WhatApi/Endpoints/LoginEndpoint.cs
blob: cb766961a54586bc9f5ccfec498a2b358b1af37b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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; }
    }

    [AllowAnonymous]
    [HttpPost("~/login")]
    public async Task<ActionResult> HandleAsync([FromForm] 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 Redirect("what://lcb?code=" + tokenString);
    }
}