From 520f85696b20db2efff3f8202582198114b3e764 Mon Sep 17 00:00:00 2001 From: Isaac Levin Date: Fri, 12 Jul 2019 12:49:38 -0400 Subject: [PATCH] fix baseline missing files --- ...RevalidatingAuthenticationStateProvider.cs | 98 +++++++++++++++++++ .../content/BlazorServerWeb-CSharp/Startup.cs | 4 - 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/RevalidatingAuthenticationStateProvider.cs diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/RevalidatingAuthenticationStateProvider.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/RevalidatingAuthenticationStateProvider.cs new file mode 100644 index 0000000000..3895c488a9 --- /dev/null +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Areas/RevalidatingAuthenticationStateProvider.cs @@ -0,0 +1,98 @@ +using System; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace BlazorServerWeb_CSharp.Areas.Identity +{ + /// + /// An service that revalidates the + /// authentication state at regular intervals. If a signed-in user's security + /// stamp changes, this revalidation mechanism will sign the user out. + /// + /// The type encapsulating a user. + public class RevalidatingAuthenticationStateProvider + : AuthenticationStateProvider, IDisposable where TUser : class + { + private readonly static TimeSpan RevalidationInterval = TimeSpan.FromMinutes(30); + + private readonly CancellationTokenSource _loopCancellationTokenSource = new CancellationTokenSource(); + private readonly IServiceScopeFactory _scopeFactory; + private readonly ILogger _logger; + private Task _currentAuthenticationStateTask; + + public RevalidatingAuthenticationStateProvider( + IServiceScopeFactory scopeFactory, + SignInManager circuitScopeSignInManager, + ILogger> logger) + { + var initialUser = circuitScopeSignInManager.Context.User; + _currentAuthenticationStateTask = Task.FromResult(new AuthenticationState(initialUser)); + _scopeFactory = scopeFactory; + _logger = logger; + + if (initialUser.Identity.IsAuthenticated) + { + _ = RevalidationLoop(); + } + } + + public override Task GetAuthenticationStateAsync() + => _currentAuthenticationStateTask; + + private async Task RevalidationLoop() + { + var cancellationToken = _loopCancellationTokenSource.Token; + + while (!cancellationToken.IsCancellationRequested) + { + try + { + await Task.Delay(RevalidationInterval, cancellationToken); + } + catch (TaskCanceledException) + { + break; + } + + var isValid = await CheckIfAuthenticationStateIsValidAsync(); + if (!isValid) + { + // Force sign-out. Also stop the revalidation loop, because the user can + // only sign back in by starting a new connection. + var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity()); + _currentAuthenticationStateTask = Task.FromResult(new AuthenticationState(anonymousUser)); + NotifyAuthenticationStateChanged(_currentAuthenticationStateTask); + _loopCancellationTokenSource.Cancel(); + } + } + } + + private async Task CheckIfAuthenticationStateIsValidAsync() + { + try + { + // Get the sign-in manager from a new scope to ensure it fetches fresh data + using (var scope = _scopeFactory.CreateScope()) + { + var signInManager = scope.ServiceProvider.GetRequiredService>(); + var authenticationState = await _currentAuthenticationStateTask; + var validatedUser = await signInManager.ValidateSecurityStampAsync(authenticationState.User); + return validatedUser != null; + } + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while revalidating authentication state"); + return false; + } + } + + void IDisposable.Dispose() + => _loopCancellationTokenSource.Cancel(); + } +} diff --git a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Startup.cs b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Startup.cs index 95677499c5..afbd199a70 100644 --- a/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Startup.cs +++ b/src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Startup.cs @@ -37,14 +37,10 @@ using Microsoft.Extensions.Hosting; #if(MultiOrgAuth) using Microsoft.IdentityModel.Tokens; #endif -<<<<<<< HEAD:src/ProjectTemplates/Web.ProjectTemplates/content/RazorComponentsWeb-CSharp/Startup.cs #if (IndividualLocalAuth) using RazorComponentsWeb_CSharp.Areas.Identity; #endif -using RazorComponentsWeb_CSharp.Data; -======= using BlazorServerWeb_CSharp.Data; ->>>>>>> Rename RazorComponents template directory to BlazorServer:src/ProjectTemplates/Web.ProjectTemplates/content/BlazorServerWeb-CSharp/Startup.cs namespace BlazorServerWeb_CSharp {