Files
Rafał Tyński 482a4b41f0 feat(backend): add JWT authentication, RBAC and consent/audit services
Add signup/signin with backend-issued JWT (Argon2 passwords in SurrealDB), role-based authorization policies, per-user data access levels, consent register and read audit log. Protect user endpoints and record sensitive reads.
2026-10-04 02:11:56 +02:00

59 lines
1.8 KiB
C#

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using TarninaHub.Application.Abstractions;
using TarninaHub.Application.Models;
namespace TarninaHub.Infrastructure.Auth;
public sealed class TokenService : ITokenService
{
private readonly AuthSettings _settings;
public TokenService(IOptions<AuthSettings> settings)
{
_settings = settings.Value;
}
public TokenResult CreateToken(UserAccount user)
{
var issuedAt = DateTimeOffset.UtcNow;
var expiresAt = issuedAt.AddMinutes(_settings.TokenLifetimeMinutes);
var claims = new List<Claim>
{
new(JwtRegisteredClaimNames.Sub, user.Id),
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
new("role", user.Role),
new("phone", user.Phone),
};
if (!string.IsNullOrWhiteSpace(user.Email))
{
claims.Add(new Claim("email", user.Email));
}
if (!string.IsNullOrWhiteSpace(user.OrganizationId))
{
claims.Add(new Claim("organization", user.OrganizationId));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_settings.SigningKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _settings.Issuer,
audience: _settings.Audience,
claims: claims,
notBefore: issuedAt.UtcDateTime,
expires: expiresAt.UtcDateTime,
signingCredentials: credentials);
var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
return new TokenResult(accessToken, expiresAt);
}
}