🐛 Fix some issues within auth perk
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Security.Cryptography;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using DysonNetwork.Shared.Cache;
|
using DysonNetwork.Shared.Cache;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
|
using DysonNetwork.Shared.Registry;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
@@ -12,7 +13,8 @@ public class TokenAuthService(
|
|||||||
IConfiguration config,
|
IConfiguration config,
|
||||||
ICacheService cache,
|
ICacheService cache,
|
||||||
ILogger<TokenAuthService> logger,
|
ILogger<TokenAuthService> logger,
|
||||||
OidcProvider.Services.OidcProviderService oidc
|
OidcProvider.Services.OidcProviderService oidc,
|
||||||
|
RemoteSubscriptionService subscriptions
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -32,7 +34,7 @@ public class TokenAuthService(
|
|||||||
logger.LogWarning("AuthenticateTokenAsync: no token provided");
|
logger.LogWarning("AuthenticateTokenAsync: no token provided");
|
||||||
return (false, null, "No token provided.");
|
return (false, null, "No token provided.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ipAddress))
|
if (!string.IsNullOrEmpty(ipAddress))
|
||||||
{
|
{
|
||||||
logger.LogDebug("AuthenticateTokenAsync: client IP: {IpAddress}", ipAddress);
|
logger.LogDebug("AuthenticateTokenAsync: client IP: {IpAddress}", ipAddress);
|
||||||
@@ -95,6 +97,11 @@ public class TokenAuthService(
|
|||||||
logger.LogWarning("AuthenticateTokenAsync: session not found (sessionId={SessionId})", sessionId);
|
logger.LogWarning("AuthenticateTokenAsync: session not found (sessionId={SessionId})", sessionId);
|
||||||
return (false, null, "Session was not found.");
|
return (false, null, "Session was not found.");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var perkSub = await subscriptions.GetPerkSubscription(session.AccountId);
|
||||||
|
if (perkSub is not null) session.Account.PerkSubscription = SnWalletSubscription.FromProtoValue(perkSub!).ToReference();
|
||||||
|
}
|
||||||
|
|
||||||
var now = SystemClock.Instance.GetCurrentInstant();
|
var now = SystemClock.Instance.GetCurrentInstant();
|
||||||
if (session.ExpiredAt.HasValue && session.ExpiredAt < now)
|
if (session.ExpiredAt.HasValue && session.ExpiredAt < now)
|
||||||
@@ -138,7 +145,7 @@ public class TokenAuthService(
|
|||||||
return (false, null, "Authentication error.");
|
return (false, null, "Authentication error.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ValidateToken(string token, out Guid sessionId)
|
public bool ValidateToken(string token, out Guid sessionId)
|
||||||
{
|
{
|
||||||
sessionId = Guid.Empty;
|
sessionId = Guid.Empty;
|
||||||
@@ -150,27 +157,27 @@ public class TokenAuthService(
|
|||||||
switch (parts.Length)
|
switch (parts.Length)
|
||||||
{
|
{
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
// JWT via OIDC
|
// JWT via OIDC
|
||||||
var (isValid, jwtResult) = oidc.ValidateToken(token);
|
var (isValid, jwtResult) = oidc.ValidateToken(token);
|
||||||
if (!isValid) return false;
|
if (!isValid) return false;
|
||||||
var jti = jwtResult?.Claims.FirstOrDefault(c => c.Type == "jti")?.Value;
|
var jti = jwtResult?.Claims.FirstOrDefault(c => c.Type == "jti")?.Value;
|
||||||
if (jti is null) return false;
|
if (jti is null) return false;
|
||||||
return Guid.TryParse(jti, out sessionId);
|
return Guid.TryParse(jti, out sessionId);
|
||||||
}
|
}
|
||||||
case 2:
|
case 2:
|
||||||
{
|
{
|
||||||
// Compact token
|
// Compact token
|
||||||
var payloadBytes = Base64UrlDecode(parts[0]);
|
var payloadBytes = Base64UrlDecode(parts[0]);
|
||||||
sessionId = new Guid(payloadBytes);
|
sessionId = new Guid(payloadBytes);
|
||||||
|
|
||||||
var publicKeyPem = File.ReadAllText(config["AuthToken:PublicKeyPath"]!);
|
var publicKeyPem = File.ReadAllText(config["AuthToken:PublicKeyPath"]!);
|
||||||
using var rsa = RSA.Create();
|
using var rsa = RSA.Create();
|
||||||
rsa.ImportFromPem(publicKeyPem);
|
rsa.ImportFromPem(publicKeyPem);
|
||||||
|
|
||||||
var signature = Base64UrlDecode(parts[1]);
|
var signature = Base64UrlDecode(parts[1]);
|
||||||
return rsa.VerifyData(payloadBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
return rsa.VerifyData(payloadBytes, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class DysonTokenAuthHandler(
|
|||||||
{
|
{
|
||||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
{
|
{
|
||||||
var tokenInfo = _ExtractToken(Request);
|
var tokenInfo = ExtractToken(Request);
|
||||||
|
|
||||||
if (tokenInfo == null || string.IsNullOrEmpty(tokenInfo.Token))
|
if (tokenInfo == null || string.IsNullOrEmpty(tokenInfo.Token))
|
||||||
return AuthenticateResult.Fail("No token was provided.");
|
return AuthenticateResult.Fail("No token was provided.");
|
||||||
@@ -91,22 +91,7 @@ public class DysonTokenAuthHandler(
|
|||||||
return resp.Session ?? throw new InvalidOperationException("Session not found.");
|
return resp.Session ?? throw new InvalidOperationException("Session not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] Base64UrlDecode(string base64Url)
|
private static TokenInfo? ExtractToken(HttpRequest request)
|
||||||
{
|
|
||||||
var padded = base64Url
|
|
||||||
.Replace('-', '+')
|
|
||||||
.Replace('_', '/');
|
|
||||||
|
|
||||||
switch (padded.Length % 4)
|
|
||||||
{
|
|
||||||
case 2: padded += "=="; break;
|
|
||||||
case 3: padded += "="; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Convert.FromBase64String(padded);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TokenInfo? _ExtractToken(HttpRequest request)
|
|
||||||
{
|
{
|
||||||
// Check for token in query parameters
|
// Check for token in query parameters
|
||||||
if (request.Query.TryGetValue(AuthConstants.TokenQueryParamName, out var queryToken))
|
if (request.Query.TryGetValue(AuthConstants.TokenQueryParamName, out var queryToken))
|
||||||
@@ -120,7 +105,7 @@ public class DysonTokenAuthHandler(
|
|||||||
|
|
||||||
|
|
||||||
// Check for token in Authorization header
|
// Check for token in Authorization header
|
||||||
var authHeader = request.Headers["Authorization"].ToString();
|
var authHeader = request.Headers.Authorization.ToString();
|
||||||
if (!string.IsNullOrEmpty(authHeader))
|
if (!string.IsNullOrEmpty(authHeader))
|
||||||
{
|
{
|
||||||
if (authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
if (authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
|
||||||
@@ -165,4 +150,4 @@ public class DysonTokenAuthHandler(
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user