diff --git a/src/Application/Users/UserService.cs b/src/Application/Users/UserService.cs index efa42f17..0b3d6598 100644 --- a/src/Application/Users/UserService.cs +++ b/src/Application/Users/UserService.cs @@ -95,7 +95,7 @@ private string GenerateJwtToken(User user) Subject = new ClaimsIdentity(CreateClaims(user)), Audience = _config[ConfigurationKeys.JwtIssuer], Issuer = _config[ConfigurationKeys.JwtIssuer], - Expires = DateTime.UtcNow.AddHours(1), + Expires = DateTime.Now.AddMonths(1), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), }; diff --git a/src/Client/Services/Authentication/SessionManagerService.cs b/src/Client/Services/Authentication/SessionManagerService.cs index f9e104d8..b4ab9cc3 100644 --- a/src/Client/Services/Authentication/SessionManagerService.cs +++ b/src/Client/Services/Authentication/SessionManagerService.cs @@ -77,6 +77,7 @@ private void Authenticate(AuthenticateResponse authentication) { // Store token on http client so all future requests use the token. _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", authentication.Token); + Console.WriteLine($"setting bearer to {_http.DefaultRequestHeaders.Authorization}"); IsAuthenticated = true; Username = authentication.Username; AuthenticationStateChanged?.Invoke(this, new AuthenticationEventArgs { State = authentication, }); diff --git a/src/Client/Shared/FetchData.razor b/src/Client/Shared/FetchData.razor index c09d872c..4279b4d7 100644 --- a/src/Client/Shared/FetchData.razor +++ b/src/Client/Shared/FetchData.razor @@ -63,6 +63,7 @@ else /// public async Task Fetch(string url) { + Console.WriteLine($"fetching with {_http.DefaultRequestHeaders.Authorization}"); HttpResponseMessage response = await _http.GetAsync(url); if (!response.IsSuccessStatusCode) diff --git a/src/Client/Shared/MainLayout.razor b/src/Client/Shared/MainLayout.razor index 95ab0d14..d2745cdc 100644 --- a/src/Client/Shared/MainLayout.razor +++ b/src/Client/Shared/MainLayout.razor @@ -1,9 +1,11 @@ -@using Application.Users -@using Client.Services.Authentication +@using System.Timers @inherits LayoutComponentBase -@inject ISessionService _session +@inject IJSRuntime Js +@inject HttpClient Http +@inject ISessionService Session +@inject NavigationManager NavigationManager - +
@@ -35,9 +37,34 @@ IsRounded = true, }; + private const int InactivityLogoutMilliseconds = 1000 * 60 * 15; // 15 minutes + + private readonly Timer _timer = new(InactivityLogoutMilliseconds); + /// protected override async Task OnInitializedAsync() { - await _session.TryResumeAsync(); + await Session.TryResumeAsync(); + + _timer.Elapsed += LogOut; + _timer.AutoReset = false; + + // Register JS-callbacks on the document that call ResetTimer when triggered. + await Js.InvokeVoidAsync("registerActivityCallback", DotNetObjectReference.Create(this)); + } + + /// + /// Resets the inactivity timer. Call when user has shown signs of activity. + /// + [JSInvokable] + public void ResetTimer() + { + _timer.Stop(); + _timer.Start(); + } + + private void LogOut(object? sender, ElapsedEventArgs elapsedEventArgs) + { + InvokeAsync(async () => await Session.EndAsync()); } } diff --git a/src/Client/wwwroot/js/interop.js b/src/Client/wwwroot/js/interop.js index 520cb582..d3c1735c 100644 --- a/src/Client/wwwroot/js/interop.js +++ b/src/Client/wwwroot/js/interop.js @@ -8,3 +8,12 @@ function focusElement(selector) { const element = document.querySelector(selector); element.focus(); } + +function registerActivityCallback(dotNetHelper) { + document.onmousemove = resetTimeDelay; + document.onkeydown = resetTimeDelay; + + function resetTimeDelay() { + dotNetHelper.invokeMethodAsync("ResetTimer"); + } +} diff --git a/src/Server/Program.cs b/src/Server/Program.cs index e0f47a6a..0a8f8412 100644 --- a/src/Server/Program.cs +++ b/src/Server/Program.cs @@ -60,6 +60,12 @@ builder.Services.AddControllers() .AddNewtonsoftJson(); +builder.Services.AddHttpLogging(logging => +{ + logging.RequestHeaders.Add("authorization"); + logging.ResponseHeaders.Add("WWW-Authenticate"); +}); + WebApplication app = builder.Build(); // Configure the HTTP request pipeline.