diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs index 4753e96..97c8804 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs @@ -14,8 +14,10 @@ public class AuthGateway(IHttpClientService httpClient, { try { - var token = await httpClient.PostAsync(Endpoints.Auth.Login, userDto); - await ((JwtAuthenticationStateProvider)stateProvider).NotifyUserAuthenticationAsync(token!.Token!); + var token = await httpClient.PostAsync(Endpoints.Auth.Login, userDto) + ?? throw new InvalidOperationException("Could not retrieve token"); + + await ((JwtAuthenticationStateProvider)stateProvider).NotifyUserAuthenticationAsync(token); return true; } catch (Exception) diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs index 41c4cf0..cf82e39 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs @@ -5,13 +5,15 @@ using System.Text.Json; using System.Text; using Blazored.LocalStorage; using GameIdeas.Shared.Constants; +using Microsoft.AspNetCore.Components.Authorization; namespace GameIdeas.BlazorApp.Services; public class HttpClientService( IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, - ILocalStorageService localStorage) : IHttpClientService + ILocalStorageService localStorage, + AuthenticationStateProvider stateProvider) : IHttpClientService { private readonly HttpClient httpClient = httpClientFactory.CreateClient("GameIdeas.WebAPI"); private readonly ILogger logger = loggerFactory.CreateLogger(); @@ -141,6 +143,16 @@ public class HttpClientService( private async Task SetAuthorizationHeader() { + var expired = await localStorage.GetItemAsStringAsync(GlobalConstants.LS_EXPIRED_STORAGE_KEY); + + if (expired == null + || (DateTime.TryParse(expired, out DateTime expiration) + && expiration < DateTime.UtcNow)) + { + await ((JwtAuthenticationStateProvider)stateProvider).NotifyUserLogoutAsync(); + return; + } + var token = await localStorage.GetItemAsStringAsync(GlobalConstants.LS_AUTH_STORAGE_KEY); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token); diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs index 6ea212f..20eadc9 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components.Authorization; using System.Security.Claims; using System.IdentityModel.Tokens.Jwt; using GameIdeas.Shared.Constants; +using GameIdeas.Shared.Dto; namespace GameIdeas.BlazorApp.Services; @@ -31,9 +32,17 @@ public class JwtAuthenticationStateProvider(ILocalStorageService localStorage) : return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } - public async Task NotifyUserAuthenticationAsync(string token) + public async Task NotifyUserAuthenticationAsync(TokenDto token) { - await localStorage.SetItemAsStringAsync(GlobalConstants.LS_AUTH_STORAGE_KEY, token); + if (token?.Token != null) + { + await localStorage.SetItemAsStringAsync(GlobalConstants.LS_AUTH_STORAGE_KEY, token.Token); + } + + if (token?.Expiration != null) + { + await localStorage.SetItemAsStringAsync(GlobalConstants.LS_EXPIRED_STORAGE_KEY, token.Expiration.Value.ToString()); + } NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } diff --git a/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs b/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs index 81e99e6..86a6cd6 100644 --- a/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs +++ b/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs @@ -12,11 +12,12 @@ public class GlobalConstants public const string MEMBER_NORMALIZED = "MEMBRE"; public const string ADMIN_MEMBER = $"{ADMINISTRATOR}, {MEMBER}"; - public const int JWT_DURATION_HOUR = 12; + public const int JWT_DURATION_HOUR = 168; public const int NUMBER_PER_PAGE = 50; public const string LS_AUTH_STORAGE_KEY = "authToken"; + public const string LS_EXPIRED_STORAGE_KEY = "expiredToken"; public const int API_PORT = 8000; public const string SUB_DOMAIN_NAME = "api-";