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.NameIdentifier, 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;
 | |
|     }
 | |
| } |