Polianin Nikita
21866d54cb
All checks were successful
.NET Test Pipeline / build-and-test (push) Successful in 2m34s
82 lines
2.9 KiB
C#
82 lines
2.9 KiB
C#
using Microsoft.IdentityModel.Tokens;
|
|
using Mirea.Api.Security.Common.Interfaces;
|
|
using System;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Linq;
|
|
using System.Security.Claims;
|
|
|
|
namespace Mirea.Api.Endpoint.Common.Services.Security;
|
|
|
|
public class JwtTokenService : IAccessToken
|
|
{
|
|
public required string Issuer { private get; init; }
|
|
public required string Audience { private get; init; }
|
|
public TimeSpan Lifetime { private get; init; }
|
|
|
|
public ReadOnlyMemory<byte> EncryptionKey { private get; init; }
|
|
public ReadOnlyMemory<byte> SigningKey { private get; init; }
|
|
|
|
public (string Token, DateTime ExpireIn) GenerateToken(string userId)
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var signingKey = new SymmetricSecurityKey(SigningKey.ToArray());
|
|
var encryptionKey = new SymmetricSecurityKey(EncryptionKey.ToArray());
|
|
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha512);
|
|
|
|
var expires = DateTime.UtcNow.Add(Lifetime);
|
|
|
|
var tokenDescriptor = new SecurityTokenDescriptor
|
|
{
|
|
Issuer = Issuer,
|
|
Audience = Audience,
|
|
Expires = expires,
|
|
SigningCredentials = signingCredentials,
|
|
Subject = new ClaimsIdentity(
|
|
[
|
|
new Claim(ClaimTypes.Name, userId),
|
|
// todo: get role by userId
|
|
new Claim(ClaimTypes.Role, "")
|
|
]),
|
|
EncryptingCredentials = new EncryptingCredentials(encryptionKey, SecurityAlgorithms.Aes256KW, SecurityAlgorithms.Aes256CbcHmacSha512)
|
|
};
|
|
|
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
|
|
|
return (tokenHandler.WriteToken(token), expires);
|
|
}
|
|
|
|
public DateTimeOffset GetExpireDateTime(string token)
|
|
{
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var signingKey = new SymmetricSecurityKey(SigningKey.ToArray());
|
|
var encryptionKey = new SymmetricSecurityKey(EncryptionKey.ToArray());
|
|
|
|
var tokenValidationParameters = new TokenValidationParameters
|
|
{
|
|
ValidIssuer = Issuer,
|
|
ValidAudience = Audience,
|
|
IssuerSigningKey = signingKey,
|
|
TokenDecryptionKey = encryptionKey,
|
|
ValidateIssuer = true,
|
|
ValidateAudience = true,
|
|
ValidateIssuerSigningKey = true,
|
|
ValidateLifetime = false
|
|
};
|
|
|
|
try
|
|
{
|
|
var claimsPrincipal = tokenHandler.ValidateToken(token, tokenValidationParameters, out _);
|
|
|
|
var expClaim = claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "exp");
|
|
|
|
if (expClaim != null && long.TryParse(expClaim.Value, out var expUnix))
|
|
return DateTimeOffset.FromUnixTimeSeconds(expUnix);
|
|
}
|
|
catch (SecurityTokenException)
|
|
{
|
|
return DateTimeOffset.MinValue;
|
|
}
|
|
|
|
return DateTimeOffset.MinValue;
|
|
}
|
|
} |