feat: add jwt token service
This commit is contained in:
		
							
								
								
									
										82
									
								
								Endpoint/Common/Services/Security/JwtTokenService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								Endpoint/Common/Services/Security/JwtTokenService.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
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 { 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user