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.
59 lines
1.8 KiB
C#
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);
|
|
}
|
|
}
|