Reputation: 2877
I am using ASP.NET Core to make a web application that also uses SignalR Core to provide real time functionality. I use Azure AD B2C for user management. I have successfully used Microsoft.Identity.Web
(https://github.com/AzureAD/microsoft-identity-web) to secure my API endpoints using tokens generated by Azure AD B2C.
I would like to do the same for my SignalR Core hubs. The documentation reads to add the appropriate annotation to your hubs/methods, which I have done. SignalR's client side library adds the access token as a query parameter which must be extracted and added to the context manually in the configuration of your ASP.NET core application, like so.
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
// If the request is for our hub...
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) &&
(path.StartsWithSegments("/hubs/chat")))
{
// Read the token out of the query string
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
However, this seems to be incompatible with the configuration supplied by Microsoft.Identity.Web
, here:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C"));
How can I make SignalR work with Microsoft.Identity.Web
?
Upvotes: 7
Views: 2222
Reputation: 301
That should do it:
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(configuration);
services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
Func<MessageReceivedContext, Task> existingOnMessageReceivedHandler = options.Events.OnMessageReceived;
options.Events.OnMessageReceived = async context =>
{
await existingOnMessageReceivedHandler(context);
StringValues accessToken = context.Request.Query["access_token"];
PathString path = context.HttpContext.Request.Path;
// If the request is for our hub...
if (!string.IsNullOrEmpty(accessToken) && path.StartsWithSegments("/hubs"))
{
// Read the token out of the query string
context.Token = accessToken;
}
};
});
Instead of adding a JwtBearer, you can configure the JwtBearerOptions object this way.
Adapted from this documentation: https://github.com/AzureAD/microsoft-identity-web/wiki/customization
Upvotes: 10
Reputation: 1229
You can use Visual Studio to set up the SignalR connection, and then just add this line in startup.cs (VS might add it automatically)
services.AddSignalR().AddAzureSignalR();
This dev sample has SignalR set up, just the connection string is missing, but might give you an idea of what to do. Most of this was done automatically with VS. If you have issues setting it up, please open an issue in the repo. thanks.
Upvotes: 0