Skip to content

Commit

Permalink
Use HttpContext to get user, then fall back to AuthenticationStatePro…
Browse files Browse the repository at this point in the history
…vider (#3968)

* #3964 Use HttpContext to get user, then fall back to AuthenticationStateProvider

* Add missing using statement

* #3964 Remove set user functionality as it doesn't work in Blazor
  • Loading branch information
rockfordlhotka committed May 24, 2024
1 parent e49b961 commit 3fa5b5f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 95 deletions.
66 changes: 10 additions & 56 deletions Source/Csla.AspNetCore/Blazor/ApplicationContextManagerBlazor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,40 +65,26 @@ public ApplicationContextManagerBlazor(IHttpContextAccessor hca, AuthenticationS

private async Task InitializeUser()
{
if (ActiveCircuitState.CircuitExists)
if (HttpContext != null)
{
var user = HttpContext.User;
if (user != null)
CurrentPrincipal = user;
}
else
{
Task<AuthenticationState> task;
try
{
task = AuthenticationStateProvider.GetAuthenticationStateAsync();
await task;
}
catch (InvalidOperationException ex)
catch (InvalidOperationException)
{
task = Task.FromResult(new AuthenticationState(UnauthenticatedPrincipal));

string message = ex.Message;
//see ms error https://github.com/dotnet/aspnetcore/blob/87e324a61dcd15db4086b8a8ca7bd74ca1e0a513/src/Components/Server/src/Circuits/ServerAuthenticationStateProvider.cs#L16
//not much safe to test on except the error type and the use of this method name in message.
if (message.Contains(nameof(AuthenticationStateProvider.GetAuthenticationStateAsync)))
{
SetHostPrincipal(task);
}
else
{
throw;
}
}
AuthenticationStateProvider_AuthenticationStateChanged(task);
}
else if (HttpContext is not null)
{
CurrentPrincipal = HttpContext.User;
}
else
{
throw new InvalidOperationException("HttpContext==null, !CircuitExists");
}
}

private void AuthenticationStateProvider_AuthenticationStateChanged(Task<AuthenticationState> task)
Expand Down Expand Up @@ -144,42 +130,10 @@ public IPrincipal GetUser()
}

/// <summary>
/// Attempts to set the current principal on the registered
/// IHostEnvironmentAuthenticationStateProvider service.
/// Not supported in Blazor.
/// </summary>
/// <param name="principal">Principal object.</param>
public virtual void SetUser(IPrincipal principal)
{
if (!ReferenceEquals(CurrentPrincipal, principal))
{
if (ActiveCircuitState.CircuitExists)
{
if (principal is ClaimsPrincipal claimsPrincipal)
{
SetHostPrincipal(Task.FromResult(new AuthenticationState(claimsPrincipal)));
}
else
{
throw new ArgumentException("typeof(principal) != ClaimsPrincipal");
}
}
else if (HttpContext is not null)
{
HttpContext.User = (ClaimsPrincipal)principal;
}
else
{
throw new InvalidOperationException("HttpContext==null, !CircuitExists");
}
CurrentPrincipal = principal;
}
}

private void SetHostPrincipal(Task<AuthenticationState> task)
{
if (AuthenticationStateProvider is IHostEnvironmentAuthenticationStateProvider hostProvider)
hostProvider.SetAuthenticationState(task);
}
public virtual void SetUser(IPrincipal principal) => throw new NotSupportedException(nameof(SetUser));

/// <summary>
/// Gets the local context.
Expand Down
60 changes: 21 additions & 39 deletions Source/Csla.AspNetCore/Blazor/ApplicationContextManagerInMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//-----------------------------------------------------------------------
using Csla.Core;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Security.Principal;

Expand Down Expand Up @@ -40,14 +41,18 @@ public class ApplicationContextManagerInMemory : IContextManager, IDisposable
/// </summary>
protected ActiveCircuitState ActiveCircuitState { get; }

private readonly HttpContext HttpContext;

/// <summary>
/// Creates an instance of the object, initializing it
/// with the required IServiceProvider.
/// </summary>
/// <param name="httpContextAccessor"></param>
/// <param name="authenticationStateProvider">AuthenticationStateProvider service</param>
/// <param name="activeCircuitState"></param>
public ApplicationContextManagerInMemory(AuthenticationStateProvider authenticationStateProvider, ActiveCircuitState activeCircuitState)
public ApplicationContextManagerInMemory(IHttpContextAccessor httpContextAccessor, AuthenticationStateProvider authenticationStateProvider, ActiveCircuitState activeCircuitState)
{
HttpContext = httpContextAccessor.HttpContext;
AuthenticationStateProvider = authenticationStateProvider;
ActiveCircuitState = activeCircuitState;
CurrentPrincipal = UnauthenticatedPrincipal;
Expand All @@ -57,29 +62,27 @@ public ApplicationContextManagerInMemory(AuthenticationStateProvider authenticat

private async Task InitializeUser()
{
Task<AuthenticationState> task = default;
try
var httpContext = HttpContext;
if (httpContext != null)
{
task = AuthenticationStateProvider.GetAuthenticationStateAsync();
await task;
var user = httpContext.User;
if (user != null)
CurrentPrincipal = user;
}
catch (InvalidOperationException ex)
else
{
task = Task.FromResult(new AuthenticationState(UnauthenticatedPrincipal));

string message = ex.Message;
//see ms error https://github.com/dotnet/aspnetcore/blob/87e324a61dcd15db4086b8a8ca7bd74ca1e0a513/src/Components/Server/src/Circuits/ServerAuthenticationStateProvider.cs#L16
//not much safe to test on except the error type and the use of this method name in message.
if (message.Contains(nameof(AuthenticationStateProvider.GetAuthenticationStateAsync)))
Task<AuthenticationState> task;
try
{
SetHostPrincipal(task);
task = AuthenticationStateProvider.GetAuthenticationStateAsync();
await task;
}
else
catch (InvalidOperationException)
{
throw;
task = Task.FromResult(new AuthenticationState(UnauthenticatedPrincipal));
}
AuthenticationStateProvider_AuthenticationStateChanged(task);
}
AuthenticationStateProvider_AuthenticationStateChanged(task);
}

private void AuthenticationStateProvider_AuthenticationStateChanged(Task<AuthenticationState> task)
Expand Down Expand Up @@ -125,31 +128,10 @@ public IPrincipal GetUser()
}

/// <summary>
/// Attempts to set the current principal on the registered
/// IHostEnvironmentAuthenticationStateProvider service.
/// Not supported in Blazor.
/// </summary>
/// <param name="principal">Principal object.</param>
public virtual void SetUser(IPrincipal principal)
{
if (!ReferenceEquals(CurrentPrincipal, principal))
{
if (principal is ClaimsPrincipal claimsPrincipal)
{
CurrentPrincipal = principal;
SetHostPrincipal(Task.FromResult(new AuthenticationState(claimsPrincipal)));
}
else
{
throw new ArgumentException("typeof(principal) != ClaimsPrincipal");
}
}
}

private void SetHostPrincipal(Task<AuthenticationState> task)
{
if (AuthenticationStateProvider is IHostEnvironmentAuthenticationStateProvider hostProvider)
hostProvider.SetAuthenticationState(task);
}
public virtual void SetUser(IPrincipal principal) => throw new NotSupportedException(nameof(SetUser));

/// <summary>
/// Gets the local context.
Expand Down

0 comments on commit 3fa5b5f

Please sign in to comment.