161 lines
5.7 KiB
C#
161 lines
5.7 KiB
C#
using DeluxeBackend.Models;
|
|
using Microsoft.IdentityModel.Tokens;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Numerics;
|
|
using System.Security.Claims;
|
|
using static DeluxeBackend.Enums;
|
|
|
|
namespace DeluxeBackend.Services
|
|
{
|
|
|
|
public class LoginWithInfoResult
|
|
{
|
|
public required Account Account { get; set; }
|
|
public PlatformType Platform { get; set; }
|
|
public required string PlatformId { get; set; }
|
|
public DeviceClassType DeviceClass { get; set; }
|
|
public required string Locale { get; set; }
|
|
public required string AppVersion { get; set; }
|
|
}
|
|
|
|
public interface IJwtService
|
|
{
|
|
Task<string> GenAccessToken(Account account, List<string> roles, Dictionary<string, object>? customeClaims = null);
|
|
Task<string> GenRefreshToken(Account acc);
|
|
Task<Account?> GetLogin(ClaimsPrincipal? User);
|
|
Task<LoginWithInfoResult?> GetLoginWithInfo(ClaimsPrincipal? User);
|
|
}
|
|
|
|
public class JwtService : IJwtService
|
|
{
|
|
private readonly ILiteDbService db;
|
|
private readonly IConfiguration configuration;
|
|
private readonly DiscordBotService discord;
|
|
|
|
public JwtService(ILiteDbService _db, IConfiguration _configuration, DiscordBotService _discord)
|
|
{
|
|
db = _db;
|
|
configuration = _configuration;
|
|
discord = _discord;
|
|
}
|
|
|
|
public async Task<string> GenAccessToken(Account account, List<string> roles, Dictionary<string, object>? customeClaims = null)
|
|
{
|
|
var issuer = configuration["JwtConfig:Issuer"];
|
|
var key = new SymmetricSecurityKey(Convert.FromBase64String(configuration["JwtConfig:Key"]));
|
|
var exp = DateTime.UtcNow.AddHours(1).AddMinutes(10);
|
|
|
|
roles.AddRange(account.Roles);
|
|
if (account.DiscordId.HasValue)
|
|
{
|
|
roles.AddRange(await discord.UserRoles(account.DiscordId.Value));
|
|
}
|
|
if (account.IsJunior == null || account.IsJunior == true)
|
|
{
|
|
roles.Add("junior");
|
|
}
|
|
roles = roles.Distinct().ToList();
|
|
|
|
var claimsDictionary = new Dictionary<string, object>
|
|
{
|
|
["role"] = roles
|
|
};
|
|
|
|
if (customeClaims != null)
|
|
{
|
|
foreach (var claim in customeClaims)
|
|
{
|
|
claimsDictionary[claim.Key] = claim.Value;
|
|
}
|
|
}
|
|
|
|
var tokenDect = new SecurityTokenDescriptor
|
|
{
|
|
Subject = new ClaimsIdentity(
|
|
[
|
|
new Claim("sub", account.Id.ToString())
|
|
]),
|
|
IssuedAt = DateTime.UtcNow,
|
|
Claims = claimsDictionary,
|
|
Expires = exp,
|
|
Issuer = issuer,
|
|
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature),
|
|
};
|
|
|
|
var tokenHandler = new JwtSecurityTokenHandler();
|
|
var token = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDect));
|
|
|
|
return token;
|
|
}
|
|
|
|
public Task<string> GenRefreshToken(Account acc)
|
|
{
|
|
RefreshToken refreshToken = new()
|
|
{
|
|
Token = Convert.ToBase64String(Guid.NewGuid().ToByteArray()),
|
|
Expires = DateTime.UtcNow.AddDays(2),
|
|
Account = acc
|
|
};
|
|
db.RefreshTokens.Insert(refreshToken);
|
|
return Task.FromResult(refreshToken.Token);
|
|
}
|
|
|
|
public Task<Account?> GetLogin(ClaimsPrincipal? User = null)
|
|
{
|
|
Console.WriteLine(User);
|
|
if (User == null)
|
|
return Task.FromResult<Account?>(null);
|
|
|
|
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
|
?? User.FindFirst("sub")?.Value;
|
|
|
|
if (string.IsNullOrEmpty(rawPlayerId))
|
|
return Task.FromResult<Account?>(null);
|
|
|
|
if (!long.TryParse(rawPlayerId, out long playerId))
|
|
return Task.FromResult<Account?>(null);
|
|
|
|
Account? player = db.Accounts.FindById(playerId);
|
|
|
|
return Task.FromResult<Account?>(player);
|
|
}
|
|
public Task<LoginWithInfoResult?> GetLoginWithInfo(ClaimsPrincipal? User = null)
|
|
{
|
|
if (User == null)
|
|
return Task.FromResult<LoginWithInfoResult?>(null);
|
|
|
|
string? rawPlayerId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
|
?? User.FindFirst("sub")?.Value;
|
|
|
|
if (string.IsNullOrEmpty(rawPlayerId) || !long.TryParse(rawPlayerId, out long playerId))
|
|
return Task.FromResult<LoginWithInfoResult?>(null);
|
|
|
|
Account? player = db.Accounts.FindById(playerId);
|
|
if (player == null)
|
|
return Task.FromResult<LoginWithInfoResult?>(null);
|
|
|
|
var result = new LoginWithInfoResult
|
|
{
|
|
Account = player,
|
|
PlatformId = User.FindFirst("db.platform.id")?.Value,
|
|
Locale = User.FindFirst("db.locale")?.Value,
|
|
AppVersion= User.FindFirst("db.appver")?.Value,
|
|
};
|
|
|
|
string? rawPlatform = User.FindFirst("db.platform")?.Value;
|
|
if (Enum.TryParse<PlatformType>(rawPlatform, out var platform))
|
|
{
|
|
result.Platform = platform;
|
|
}
|
|
|
|
string? rawDeviceClass = User.FindFirst("db.deviceclass")?.Value;
|
|
if (Enum.TryParse<DeviceClassType>(rawDeviceClass, out var deviceClass))
|
|
{
|
|
result.DeviceClass = deviceClass;
|
|
}
|
|
|
|
return Task.FromResult<LoginWithInfoResult?>(result);
|
|
}
|
|
}
|
|
}
|