If using SignalR hubs and want to authorize the methods under the same Hub one would have to use the Authorize attribute on the Hub. i.e.
[Authorize]
public class MessagingHub: Hub
{
public Task Send(string data)
{
return Clients.Caller.SendAsync("Send", "Data To Send");
}
}
In order to access Claims or User Identity in the Hub method e.g Send above, then one would have the following:
[Authorize]
public class MessagingHub: Hub
{
public Task Send(string data)
{
var identity = (ClaimsIdentity)Context.User.Identity;
//one can access all member functions or properties of identity e.g, Claims, Name, IsAuthenticated...
return Clients.Caller.SendAsync("Send", "Data To Send");
}
}
If using Json Web Tokens (JWT) or just token authentication as was the case for me then, from the client side this is what could be used to invoke the Hub's Send method.
NB: For my case the client is an Angular 6 app.
import { HubConnection } from "@aspnet/signalr";
import * as signalR from '@aspnet/signalr';
...
private _messagingHubConnection: HubConnection | undefined;
public async: any;
...
constructor(){}
...
SendMessg(): void {
if (this._messagingHubConnection) {
this._messagingHubConnection.invoke('Send');
}
}
...
ngOnInit(){
this._messagingHubConnection= new signalR.HubConnectionBuilder()
.withUrl("messaging", { accessTokenFactory: () => "jwt_token" }) //have a logic that gets the current user's authentication token from the browser
.build();
this._messagingHubConnection.start().then(() => {
this.SendMessg();
}).catch(err => console.error(err.toString()));
if (this._messagingHubConnection) {
this._messagingHubConnection.on('Send', (data: any) => {
//data represents response/message received from Hub method'd return value.
});
}
}
NB: I am using .Net Core 2.1 so be sure to register the Hub.
also this is with the assumption that signalR is already setup
For .Net Core, ensure that in your StartUp.cs you have;
services.AddSignalR(); // under ConfigureServices
and
app.UseWebSockets();
app.UseAuthentication();
app.UseSignalR(routes => {
routes.MapHub<LoopyHub>("/messaging");
});
NB: From the issues on GitHub for SignalR I realized the order of the above is important just in case anyone is developing any issues. i.e. From my understanding the above order is correct.
Technically I have answered the question above but from a .NET Core & Angular context; I guess most if not all implementations follow the same approach.