53 lines
1.6 KiB
C#
53 lines
1.6 KiB
C#
using System;
|
|
using System.Text.Json;
|
|
|
|
namespace NexusReader.UI.Shared.Services;
|
|
|
|
/// <summary>
|
|
/// A lightweight, Native AOT-friendly JWT validator that decodes the payload of a JWT token
|
|
/// to verify expiration without standard library dependencies.
|
|
/// </summary>
|
|
public static class JwtTokenValidator
|
|
{
|
|
public static bool IsExpired(string? token)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(token)) return true;
|
|
|
|
try
|
|
{
|
|
var parts = token.Split('.');
|
|
if (parts.Length != 3) return true;
|
|
|
|
var payload = parts[1];
|
|
|
|
// Pad the base64 string
|
|
var padLength = 4 - (payload.Length % 4);
|
|
if (padLength < 4)
|
|
{
|
|
payload += new string('=', padLength);
|
|
}
|
|
|
|
// Base64URL to standard Base64 conversion
|
|
payload = payload.Replace('-', '+').Replace('_', '/');
|
|
|
|
var bytes = Convert.FromBase64String(payload);
|
|
using var jsonDoc = JsonDocument.Parse(bytes);
|
|
|
|
if (jsonDoc.RootElement.TryGetProperty("exp", out var expElement))
|
|
{
|
|
var exp = expElement.GetInt64();
|
|
var expTime = DateTimeOffset.FromUnixTimeSeconds(exp);
|
|
|
|
// Allow a small 10-second clock skew buffer
|
|
return expTime <= DateTimeOffset.UtcNow.AddSeconds(10);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return true; // Treat invalid token as expired
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|