I am trying to setup Blazor Server with a Signal R Core hub using Azure SignalR Services.
In general the Blazor app is working fine and is using Azure SignalR Services.
The Signal R Core Hub will work if I decorate it using [AllowAnonymous]. If I remove the [AllowAnonymous] the Signalr R Core client's HubConnection StartAsync gives a variety of errors depending on what I adjust in startup.cs. Using Fiddler I can tell the StartAsync attempts to retrieve a token from login.microsoftonline.com.
I don't understand why the currently logged in and authorized isn't being used.
Even when I use [AllowAnonymous] the Signalr R Hub will pickup the the username.
Here is the code for the Hub:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authorization;
namespace ServerApp.Services.NotificationHub
{
[AllowAnonymous]
public class BlazorChatHub : Hub
{
public const string HubUrl = "/coaching";
private ILogger<BlazorChatHub> _logger;
public BlazorChatHub(ILogger<BlazorChatHub> logger)
{
_logger = logger;
}
public async Task Broadcast(string username, string message)
{
_logger.LogInformation($"Broadcast: {username} : {message}");
await Clients.All.SendAsync("Broadcast", username, message);
}
public async Task Send(string message)
{
await Clients.All.SendAsync("Send", message);
}
public async Task SendMessage(string user, string message)
{
_logger.LogInformation($"SendMessage: {user} : {message}");
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
public override Task OnConnectedAsync()
{
_logger.LogInformation($"{Context.ConnectionId} connected");
return base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception e)
{
_logger.LogInformation($"Disconnected {e?.Message} {Context.ConnectionId}");
await base.OnDisconnectedAsync(e);
}
}
}
Here is the code for the Blazor page where the Hub is opened. _hubConnection.StartAsync() fails if I remove the [AllowAnonymous] from the Hub shown above.
// Create the chat client
string baseUrl = navigationManager.BaseUri;
_hubUrl = baseUrl.TrimEnd('/') + BlazorChatHub.HubUrl;
_hubConnection = new HubConnectionBuilder()
.WithUrl(_hubUrl)
.Build();
_hubConnection.On<string, string>("Broadcast", BroadcastMessage);
await _hubConnection.StartAsync();
From Startup.cs, I believe this is where the problem may originate:
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
Configuration.Bind("AzureAd", options);
})
.EnableTokenAcquisitionToCallDownstreamApi() //initialScopes
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
Almost as if the Hub is considered a downstreamapi, when it is actually on the same Blazor Server app. Why is Blazor Server trying to go to login.microsoftonline.com to re-authenticate for "localhost/coaching/negotiate"?