93 lines
3.4 KiB
C#
93 lines
3.4 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
namespace Flawless.Server.Services;
|
|
|
|
public class TokenGenerationService
|
|
{
|
|
private readonly SymmetricSecurityKey _key;
|
|
|
|
private readonly string _issuer;
|
|
|
|
private readonly double _expiresIn;
|
|
|
|
private readonly double _refreshTokenLifeTime;
|
|
|
|
public TokenGenerationService(IConfiguration c)
|
|
{
|
|
var rawKey = Encoding.UTF8.GetBytes(c["Jwt:SecretKey"] ?? throw new Exception("No Jwt:SecretKey"));
|
|
_key = new SymmetricSecurityKey(rawKey);
|
|
_issuer = c["Jwt:Issuer"] ?? throw new Exception("No Jwt:Issuer");
|
|
_expiresIn = double.Parse(c["Jwt:ExpiresIn"] ?? throw new Exception("No Jwt:ExpiresIn"));
|
|
_refreshTokenLifeTime = double.Parse(c["Jwt:RefreshTokenLifeTime"] ?? throw new Exception("No Jwt:RefreshTokenLifeTime"));
|
|
}
|
|
|
|
public double RefreshTokenLifeTime => _refreshTokenLifeTime;
|
|
|
|
public string GenerateToken(IEnumerable<Claim> claims)
|
|
{
|
|
var now = DateTime.UtcNow;
|
|
var jwt = new JwtSecurityToken(
|
|
issuer: _issuer,
|
|
claims: claims,
|
|
notBefore: now,
|
|
expires: now.AddMinutes(_expiresIn),
|
|
signingCredentials: new SigningCredentials(_key, SecurityAlgorithms.HmacSha256)
|
|
);
|
|
|
|
return new JwtSecurityTokenHandler().WriteToken(jwt);
|
|
}
|
|
|
|
public ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
|
|
{
|
|
var tokenValidationParameters = new TokenValidationParameters
|
|
{
|
|
ValidateAudience = false,
|
|
ValidateIssuer = true,
|
|
ValidateLifetime = false,
|
|
ValidateIssuerSigningKey = true,
|
|
ValidIssuer = _issuer,
|
|
IssuerSigningKey = _key,
|
|
};
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken);
|
|
var jwtSecurityToken = securityToken as JwtSecurityToken;
|
|
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
|
|
throw new SecurityTokenException("Invalid token");
|
|
|
|
return principal;
|
|
}
|
|
|
|
public ClaimsPrincipal GetPrincipal(string token)
|
|
{
|
|
var tokenValidationParameters = new TokenValidationParameters
|
|
{
|
|
ValidateAudience = false,
|
|
ValidateIssuer = true,
|
|
ValidateLifetime = true,
|
|
ValidateIssuerSigningKey = true,
|
|
ValidIssuer = _issuer,
|
|
IssuerSigningKey = _key,
|
|
};
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out var securityToken);
|
|
var jwtSecurityToken = securityToken as JwtSecurityToken;
|
|
if (jwtSecurityToken == null || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
|
|
throw new SecurityTokenException("Invalid token");
|
|
|
|
return principal;
|
|
}
|
|
|
|
public string GenerateRefreshToken()
|
|
{
|
|
Span<byte> randomNumber = stackalloc byte[32];
|
|
using var rng = RandomNumberGenerator.Create();
|
|
rng.GetBytes(randomNumber);
|
|
return Convert.ToBase64String(randomNumber);
|
|
}
|
|
} |