dotnet / dotnet/AspNetCore.Docs
Better SignalR documentation for authentication
- Dominant language
- C#
- Stars
- 13.1k
- Forks
- 24.6k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 97
Description
Are there any `working` code samples for net5.0 or net6.0 on how to authenticate users using Identity and tokens?
I have a working tutorial without authentication [Use ASP.NET Core SignalR with Blazor](https://docs.microsoft.com/en-us/aspnet/core/tutorials/signalr-blazor?view=aspnetcore-6.0&tabs=visual-studio&pivots=server)
The steps for authentication and authorization have code samples but seem incomplete [Authentication and authorization in ASP.NET Core SignalR](https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-6.0)
How is the variable `_myAccessToken` set here?
```
var connection = new HubConnectionBuilder()
.WithUrl("https://example.com/chathub", options =>
{
options.AccessTokenProvider = () => Task.FromResult(_myAccessToken);
})
.Build();
```
For Built-in JWT authentication what goes here `options.Authority = /* TODO: Insert Authority URL here */;`?
If I add `[Authorize]` to the hub I would expect I can only send messages if I login, but I get an error on the client `System.Net.Http.HttpRequestException HResult=0x80131500 Message=Response status code does not indicate success: 401 (Unauthorized).`
It looks like I need to add a token to the client but I cannot work out how from the docs. Can anyone help?
```
[Authorize]
public class MessageHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
```
TestMessageHub.razor:
```
@page "/testmessagehub"
@using Microsoft.AspNetCore.SignalR.Client
@inject NavigationManager NavigationManager
@implements IAsyncDisposable
User:
Message:
Send
- @message
@foreach (var message in messages)
{
}
@code {
private HubConnection hubConnection = null!;
private List messages = new List();
private string userInput = null!;
private string messageInput = null!;
protected override async Task OnInitializedAsync()
{
hubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/messagehub"))
.Build();
hubConnection.On("ReceiveMessage", (user, message) =>
{
var encodedMsg = $"{user}: {message}";
messages.Add(encodedMsg);
StateHasChanged();
});
await hubConnection.StartAsync();
}
async Task Send() =>
await hubConnection.SendAsync("SendMessage", userInput, messageInput);
public bool IsConnected =>
hubConnection.State == HubConnectionState.Connected;
public async ValueTask DisposeAsync()
{
if (hubConnection is not null)
{
await hubConnection.DisposeAsync();
}
}
}
```
Program.cs:
```
using Test.Areas.Identity;
using Test.Data;
using Test.Hubs;
using Test.Services.Mail;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddIdentity(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores()
.AddTokenProvider>(TokenOptions.DefaultProvider)
.AddDefaultUI();
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped>();
builder.Services.AddSingleton();
builder.Services.Configure(o => o.TokenLifespan = TimeSpan.FromHours(24)); // Default is one day anyway but set incase later versions change
builder.Services.Configure(builder.Configuration.GetSection("EMailSettings"));
builder.Services.AddTransient();
builder.Services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "application/octet-stream" });
});
var app = builder.Build();
app.UseResponseCompression();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapHub("/messagehub");
app.MapFallbackToPage("/_Host");
app.Run();
```
Contributor guide
Assessment
This issue has not been assessed yet.