diff --git a/PatchPanda.Web/Helpers/JwtHelper.cs b/PatchPanda.Web/Helpers/JwtHelper.cs new file mode 100644 index 0000000..e5175f6 --- /dev/null +++ b/PatchPanda.Web/Helpers/JwtHelper.cs @@ -0,0 +1,36 @@ +using System.Text.Json; + +namespace PatchPanda.Web.Helpers; + +public class JwtHelper +{ + public static DateTime? GetJwtExpiry(string jwt) + { + try + { + var parts = jwt.Split('.'); + if (parts.Length < 2) return null; + + var payload = parts[1]; + var base64 = payload.Replace('-', '+').Replace('_', '/'); + switch (base64.Length % 4) + { + case 2: base64 += "=="; break; + case 3: base64 += "="; break; + } + + var bytes = Convert.FromBase64String(base64); + using var doc = JsonDocument.Parse(bytes); + if (doc.RootElement.TryGetProperty("exp", out var expElement) && expElement.TryGetInt64(out var exp)) + { + return DateTimeOffset.FromUnixTimeSeconds(exp).UtcDateTime; + } + } + catch + { + return null; + } + + return null; + } +} \ No newline at end of file diff --git a/PatchPanda.Web/Services/PortainerService.cs b/PatchPanda.Web/Services/PortainerService.cs index 06f0406..088ac69 100644 --- a/PatchPanda.Web/Services/PortainerService.cs +++ b/PatchPanda.Web/Services/PortainerService.cs @@ -67,6 +67,8 @@ private async Task EnsureAuthenticatedAsync() return; } + _logger.LogInformation("Using username and password to authenticate with Portainer..."); + var payload = JsonSerializer.Serialize(new { username = _username, password = _password }); var resp = await _httpClient.PostAsync( "/api/auth", @@ -94,10 +96,11 @@ private async Task EnsureAuthenticatedAsync() "Bearer", _jwt ); - _jwtExpiry = DateTime.UtcNow.AddHours(8); + _jwtExpiry = JwtHelper.GetJwtExpiry(_jwt) ?? DateTime.UtcNow.AddHours(8); + _logger.LogInformation("Portainer authentication successful."); } else - _logger.LogWarning("Failed parsing Portainer auth response"); + _logger.LogWarning("Failed parsing Portainer auth response."); } private async Task GetStack(string stackName)