Refactor authentication services and implement JWT validation logic

This commit is contained in:
Aaron Po
2026-02-26 23:44:52 -05:00
parent 0ab2eaaec9
commit 250e5f2c9c
7 changed files with 106 additions and 24 deletions

View File

@@ -1,3 +1,5 @@
using System.Security.Claims;
namespace Infrastructure.Jwt;
public interface ITokenInfrastructure
@@ -8,4 +10,6 @@ public interface ITokenInfrastructure
DateTime expiry,
string secret
);
}
Task<ClaimsPrincipal> ValidateJwtAsync(string token, string secret);
}

View File

@@ -16,4 +16,8 @@
Version="8.2.1"
/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Domain.Exceptions\Domain.Exceptions.csproj" />
</ItemGroup>
</Project>

View File

@@ -3,6 +3,7 @@ using System.Text;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using JwtRegisteredClaimNames = System.IdentityModel.Tokens.Jwt.JwtRegisteredClaimNames;
using Domain.Exceptions;
namespace Infrastructure.Jwt;
@@ -16,16 +17,19 @@ public class JwtInfrastructure : ITokenInfrastructure
)
{
var handler = new JsonWebTokenHandler();
var key = Encoding.UTF8.GetBytes(
secret ?? throw new InvalidOperationException("secret not set")
);
// Base claims (always present)
var key = Encoding.UTF8.GetBytes(secret);
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Sub, userId.ToString()),
new(JwtRegisteredClaimNames.UniqueName, username),
new(
JwtRegisteredClaimNames.Iat,
DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()
),
new(
JwtRegisteredClaimNames.Exp,
new DateTimeOffset(expiry).ToUnixTimeSeconds().ToString()
),
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
@@ -41,4 +45,36 @@ public class JwtInfrastructure : ITokenInfrastructure
return handler.CreateToken(tokenDescriptor);
}
}
public async Task<ClaimsPrincipal> ValidateJwtAsync(
string token,
string secret
)
{
var handler = new JsonWebTokenHandler();
var keyBytes = Encoding.UTF8.GetBytes(
secret
);
var parameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(keyBytes),
};
try
{
var result = await handler.ValidateTokenAsync(token, parameters);
if (!result.IsValid || result.ClaimsIdentity == null)
throw new UnauthorizedAccessException();
return new ClaimsPrincipal(result.ClaimsIdentity);
}
catch (Exception e)
{
throw new UnauthorizedException("Invalid token");
}
}
}