Blazor server side: automatically add user to message headers

Hi

Context is: Blazor server side.

I’m trying to find a way so that whenever a command is sent the username that triggered the operation will end up in the message headers. I already implemented the header propagation, so that subsequent messages sent by the initial handler will also get the username in their headers.
This works when manually adding the header to the SendOptions before emitting the initial message.

But I’m struggling to find a way so that it can be done automatically with a behavior or outgoing message behavior, without the need to change every invocation of IMessageSession.Send to include the header in the SendOptions.
From what I understand a behavior as well as a message mutator are a singleton within a process. So all connected users would share the same instance. On the other hand the AuthenticationStateProvider is Scoped in Blazor. Resulting from this there’s a dependency issue that won’t let me solve the problem at hand. My conclusion from this is, that it’s just not possible because the behavior could not access the current user’s principal due to lifetime differences.

Is anyone familiar with this to confirm my conclusion, or maybe sees a solution I didn’t see yet?

EDIT: I checked Passing user identity between endpoints using a custom header • NServiceBus Samples • Particular Docs but I don’t see how this would help me.

Thanks
Philipp

I’m not sure if there is some nuance specific to blazor which would impact this, but the fact that the behaviour is singleton scoped shouldn’t matter. If the behaviour can access the context which has the current user, the scoping should still be correct.

In the sample you linked to, the singleton behaviour accesses the current user via the CurrentPrincipal property, whereas in blazor the singleton behaviour should be able to access the current user via the context property which should be scoped correctly.

The way you’d usually access the current user in Blazor server-side is through either Task<AuthenticationState mostly in blazor components, or alternatively through AuthenticationStateProvider. In Blazor server-side the AuthenticationStateProvider is defined as InScoped in the DI container, see AspNetCore Code services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();

And if a scoped instance gets injected into a singleton instance (the behavior) we’re having a lifetime issue and the current user (the one linked to the Blazor Circuit, the scope) won’t be used for the NServiceBus behavior.

I also don’t know which context you mean that should be scoped correctly.

You wouldn’t inject the scoped instance into the behaviour, you would inject an accessor which is able to read from the current scope. In the original sample you linked to, the IPrincipalAccessor is able to access the current principal even though it’s injected into the singleton behaviour.

You could create your own IPrincialAccessor that calls AuthenticationStateProvider.GetAuthenticationStateAsync() under the hood. The IPrincipalAccessor would be injected into the behaviour, and the behaviour would then call into the accessor which in turn would call GetAuthenticationState returning the current user.

ah, got the basic idea now, thanks. Let me see if I find a way to make that IPrincipalAccessor

1 Like