When using SignalR core locally I am able to access my identity claims principle via the Hub using HubCallerContext, e.g:
string userIdentifier = Context.UserIdentifier
I achieve this by passing the .AspNetCore.Identity.Application cookie to the HubConnectionBuilder:
hubConnection = new HubConnectionBuilder()
.WithUrl(Navigation.ToAbsoluteUri("/chathub"), options =>
{
options.Cookies = GetAuthCookieContainer();
})
.Build();
await hubConnection.StartAsync();
private CookieContainer GetAuthCookieContainer()
{
string cookieName = ".AspNetCore.Identity.Application";
string domainName = new Uri(Navigation.BaseUri).Host;
CookieContainer cookieContainer = new CookieContainer();
if (HttpContext.HttpContext != null)
{
var token = HttpContext.HttpContext.Request.Cookies[cookieName];
if (token != null)
{
cookieContainer.Add(new Cookie(cookieName, token) { Domain = domainName });
}
}
return cookieContainer;
}
This stops working once I add Azure SignalR service to Program.cs:
builder.Services.AddSignalR().AddAzureSignalR();
This is because I cannot pass the identity cookie to HubConnectionBuilder as HttpContext is always null once Azure SignalR is added to DI. Apart from this SignalR Azure works as expected.
Does anyone have a solution to how I can pass AspNetCore.Identity.Application cookie to HubConnectionBuilder() when using Azure SignalR or is there a better approach to this problem?
The major problem is that in Blazor Server we can't access the HttpContext directly, as it is not guaranteed that IHttpContextAccessor will have an instance of the context and it is also not guaranteed that if it has an instance.
We should grab the values from HttpContext
object in _Host.cshtml
file, create a new object and store the values, then pass this object to the App component as a parameter.
Then we can set them as a CascadingValue or create a scoped service to store properties from HttpContext and add to program.cs.
jbob77435's answer is using DI to access the stored HttpContext properties from anywhere within the Blazor app.
We also could use
[CascadingParameter(Name = "Cookies")] public Dictionary<string, string> Cookies { get; set; }
to implement it.
Hope this official blog will useful to you.