Skip to content

Instantly share code, notes, and snippets.

@afruzan
Last active October 4, 2021 17:03
Show Gist options
  • Save afruzan/f2c2f5f9b6d9823bf7816d504e321d4a to your computer and use it in GitHub Desktop.
Save afruzan/f2c2f5f9b6d9823bf7816d504e321d4a to your computer and use it in GitHub Desktop.
supporting .net core auth in signalr hubs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace SignalRWebApp
{
public static class SignalRHubsAuthExtentions
{
// Use one of the extentions to add hubs authentication support. See https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0#bearer-token-authentication for more details.
public static void AddHubsAuthentication(this JwtBearerOptions options)
{
// We have to hook the OnMessageReceived event in order to
// allow the JWT authentication handler to read the access
// token from the query string when a WebSocket or
// Server-Sent Events request comes in.
// Sending the access token in the query string is required due to
// a limitation in Browser APIs. We restrict it to only calls to the
// SignalR hub in this code.
// See https://docs.microsoft.com/aspnet/core/signalr/security#access-token-logging
// for more information about security considerations when using
// the query string to transmit the access token.
if (options.Events == null)
{
options.Events = new JwtBearerEvents();
}
var originalOnMessageReceived = options.Events.OnMessageReceived;
options.Events.OnMessageReceived = async context =>
{
await originalOnMessageReceived?.Invoke(context);
if (string.IsNullOrEmpty(context.Token))
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
path.StartsWithSegments("/hubs"))
{
context.Token = accessToken;
}
}
};
}
/// <summary>
/// Use this after adding services for authentication (AddAuthentication) and the authentication handler for Identity Server (AddIdentityServerJwt).
/// </summary>
public static void AddHubsAuthentication(this IServiceCollection services)
{
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptionsToSupportHubsAuthentication>());
}
private class ConfigureJwtBearerOptionsToSupportHubsAuthentication : IPostConfigureOptions<JwtBearerOptions>
{
public void PostConfigure(string name, JwtBearerOptions options)
{
options.AddHubsAuthentication();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment