150 lines
5.2 KiB
C#
150 lines
5.2 KiB
C#
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
|
|
|
|
using UGQApiServer.Settings;
|
|
using UGQDatabase.Models;
|
|
|
|
|
|
namespace JwtRoleAuthentication.Services;
|
|
|
|
public class TokenService
|
|
{
|
|
readonly JWTSettings _jwtSettings;
|
|
|
|
public TokenService(IOptions<JWTSettings> settings)
|
|
{
|
|
_jwtSettings = settings.Value;
|
|
}
|
|
|
|
public string CreateToken(string userGuid, string nickname)
|
|
{
|
|
var token = CreateJwtToken(CreateClaims(userGuid, nickname));
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
return tokenHandler.WriteToken(token);
|
|
}
|
|
|
|
public string CreateAdminToken(string username, UGQAccountRole role)
|
|
{
|
|
var token = CreateJwtToken(CreateAdminClaims(username, role));
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
return tokenHandler.WriteToken(token);
|
|
}
|
|
|
|
public string GenerateRefreshToken()
|
|
{
|
|
var randomNumber = new byte[32];
|
|
using var rng = RandomNumberGenerator.Create();
|
|
rng.GetBytes(randomNumber);
|
|
return Convert.ToBase64String(randomNumber);
|
|
}
|
|
|
|
public ClaimsPrincipal GetPrincipalFromExpiredToken(string token)
|
|
{
|
|
var tokenValidationParameters = new TokenValidationParameters
|
|
{
|
|
ValidateAudience = false, //you might want to validate the audience and issuer depending on your use case
|
|
ValidateIssuer = false,
|
|
ValidateIssuerSigningKey = true,
|
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.Secret)),
|
|
ValidateLifetime = false //here we are saying that we don't care about the token's expiration date
|
|
};
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
SecurityToken securityToken;
|
|
var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out 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 GenerateAccessTokenFromRefreshToken(string refreshToken, string secret)
|
|
{
|
|
// Implement logic to generate a new access token from the refresh token
|
|
// Verify the refresh token and extract necessary information (e.g., user ID)
|
|
// Then generate a new access token
|
|
|
|
// For demonstration purposes, return a new token with an extended expiry
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var key = Encoding.ASCII.GetBytes(secret);
|
|
|
|
var tokenDescriptor = new SecurityTokenDescriptor
|
|
{
|
|
Expires = DateTime.UtcNow.AddMinutes(15), // Extend expiration time
|
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
|
|
};
|
|
|
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
|
return tokenHandler.WriteToken(token);
|
|
}
|
|
|
|
private JwtSecurityToken CreateJwtToken(List<Claim> claims)
|
|
{
|
|
var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.Secret));
|
|
DateTime expiration = DateTime.UtcNow.AddMinutes(_jwtSettings.TokenValidityInMinutes);
|
|
|
|
return new(
|
|
_jwtSettings.ValidIssuer,
|
|
_jwtSettings.ValidAudience,
|
|
claims,
|
|
expires: expiration,
|
|
signingCredentials: new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256)
|
|
);
|
|
}
|
|
|
|
private List<Claim> CreateAdminClaims(string username, UGQAccountRole role)
|
|
{
|
|
try
|
|
{
|
|
var claims = new List<Claim>
|
|
{
|
|
// new Claim(JwtRegisteredClaimNames.Sub, jwtSub),
|
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
|
new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()),
|
|
new Claim(ClaimTypes.Name, username),
|
|
new Claim(ClaimTypes.Role, role.ToString())
|
|
};
|
|
|
|
return claims;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private List<Claim> CreateClaims(string userGuid, string nickname)
|
|
{
|
|
try
|
|
{
|
|
var claims = new List<Claim>
|
|
{
|
|
// new Claim(JwtRegisteredClaimNames.Sub, jwtSub),
|
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
|
new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()),
|
|
new Claim("Id", userGuid),
|
|
new Claim(ClaimTypes.Name, nickname),
|
|
// new Claim(ClaimTypes.Email, user.Email),
|
|
// new Claim(ClaimTypes.Role, user.Role.ToString())
|
|
};
|
|
|
|
return claims;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
throw;
|
|
}
|
|
}
|
|
} |