I am trying to send a message with SignalR to a specific user.
I implemented the default project authentication with Blazor Server side and Net6.
I can log in / log out / register.
I implemented the IUSerIdProvider Interface to get the UserId.
The first time I launch the app, I can retrieved the user (from connection.GetHttpContext(); or connection.User.FindFirstValue(ClaimTypes.Name); but when I navigate to an other page and call the hub again, the HubConnectionContext loses my User and all his informations.
If I force the id with a constant string it works but why do I lose the informations the second time ?
I don't know if I need to use cookies because the first time I have informations.
// CustomUserIdProvider.cs
public class CustomUserIdProvider : IUserIdProvider
{
public string? GetUserId(HubConnectionContext connection)
{
var httpContext = connection.GetHttpContext();
var userId = connection.User.FindFirstValue(ClaimTypes.Name);
if (string.IsNullOrWhiteSpace(userId))
return string.Empty;
return userId;
}
}
// Program.cs
-----
builder.Services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();
-----
app.UseAuthentication();
app.UseAuthorization();
// SignalR.razor (where I test to receive / send a message and here I lost the informations)
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/notifyhub"))
.Build();
hubConnection.On<int, string>("ReceiveMessage", (id, message) =>
{
var encodedMsg = $"{id}: {message}";
InvokeAsync(StateHasChanged);
});
await hubConnection.StartAsync();
}
private async Task Send()
{
if (hubConnection is not null)
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
authMessage = $"{user.Identity.Name} is authenticated.";
claims = user.Claims;
surnameMessage =
$"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
await hubConnection.SendAsync("Send", user.Identity.Name, 1, "Message envoyé");
}
}