2

I am working on a Blazor Server project which uses ASP.NET Core Identity. I'm trying to implement a component to manage current active users. I can access the current identity user for current client, but I can't seem to access the circuit associated with the current client, because I want to track when each user leaves the browser (the circuit is disconnected).

From an answer by '@enet' (link), I tried implementing CircuitHandler, and I can get all the current circuits, but how can I know which circuit is associated with which user?

using Microsoft.AspNetCore.Components.Server.Circuits;
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;


namespace BlazorCircuitHandler.Services
{
    public class CircuitHandlerService : CircuitHandler
    {
        public ConcurrentDictionary<string, Circuit> Circuits { get; 
            set; }
        public event EventHandler CircuitsChanged;

        protected virtual void OnCircuitsChanged()
             => CircuitsChanged?.Invoke(this, EventArgs.Empty);

        public CircuitHandlerService()
        {
             Circuits = new ConcurrentDictionary<string, Circuit>();
        }

        public override Task OnCircuitOpenedAsync(Circuit circuit, 
                             CancellationToken cancellationToken)
       {
             Circuits[circuit.Id] = circuit;
             OnCircuitsChanged();
             return base.OnCircuitOpenedAsync(circuit, 
                                   cancellationToken);
       }

       public override Task OnCircuitClosedAsync(Circuit circuit, 
                 CancellationToken cancellationToken)
      {
           Circuit circuitRemoved;
           Circuits.TryRemove(circuit.Id, out circuitRemoved);
           OnCircuitsChanged();
           return base.OnCircuitClosedAsync(circuit, 
                             cancellationToken);
      }

      public override Task OnConnectionDownAsync(Circuit circuit, 
                            CancellationToken cancellationToken)
      {
          return base.OnConnectionDownAsync(circuit, 
                           cancellationToken);
      }

      public override Task OnConnectionUpAsync(Circuit circuit, 
                          CancellationToken cancellationToken)
      {
          return base.OnConnectionUpAsync(circuit, cancellationToken);
      }
   }
 }
Kinin Roza
  • 1,369
  • 6
  • 14

1 Answers1

3

If you use the AddHttpContextAccessor service

services.AddHttpContextAccessor();

You can get the the user when the circuit is created:

public class MyCircuitIdStashingHandler: CircuitHandler
{
    public override Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken)
    {
        IHttpContextAccessor accessor = new HttpContextAccessor();
        accessor.HttpContext.User.Identity; // store in dictionary somewhere
        return base.OnCircuitOpenedAsync(circuit, cancellationToken);
    }
}

...and then you can keep track on what user is using which circuit

Hans Karlsen
  • 2,117
  • 1
  • 13
  • 15
  • Microsoft says using `IHttpContextAccessor` in a Blazor app is a security risk: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-6.0#blazor-and-shared-state – user3071284 Jan 21 '22 at 22:34
  • 2
    Yes - it would be a risk using it after creation (it will be undefined later on in the lifecycle) - but creation of circuit will coincide with a controller action call - and getting the user Identity at that point is safe. – Hans Karlsen Feb 24 '22 at 22:05