please note - this only applies to the case of server-side Identity (i.e. IdentityServer4 creates tokens, not Angular)
Created brand new asp.net core 5 angular spa app form template:
dotnet new angular --auth Individual
npm i @microsoft/signalr
Modified Startup.cs
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder
.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
services.AddSignalR();
. . .
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
. . .
endpoints.MapHub<NewsHub>("/newshub");
});
Added Hub class
[Authorize]
public class NewsHub : Hub
{
}
Modified WeatherForecastController:
private IHubContext<NewsHub> _hub;
public WeatherForecastController(ILogger<WeatherForecastController> logger, IHubContext<NewsHub> hub)
{
_hub = hub;
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var timerManager = new TimerManager(() =>
_hub.Clients.All.SendAsync("servermessage", DateTime.Now.Ticks.ToString()));
Modify fetch-data.component.ts
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'weatherforecast').subscribe(result => {
this.forecasts = result;
this.hub = new HubConnectionBuilder()
.withUrl("/newshub")
.build();
this.hub.on("servermessage", (m: string) => { console.log(m); });
this.hub.start()
.then(() => console.log('MessageHub Connected'))
.catch(err => console.log('MessageHub Connection Error: ' + err.toString()));
}, error => console.error(error));
}
Authorization of SignalR hub fails. Output window:
IdentityServer4.Hosting.IdentityServerMiddleware: Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
IdentityServer4.Hosting.IdentityServerMiddleware: Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.DiscoveryEndpoint for /.well-known/openid-configuration
IdentityServer4.Hosting.IdentityServerMiddleware: Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.UserInfoEndpoint for /connect/userinfo
IdentityServer4.ResponseHandling.UserInfoResponseGenerator: Information: Profile service returned the following claim types: sub preferred_username name
IdentityServer4.Hosting.IdentityServerMiddleware: Information: Invoking IdentityServer endpoint: IdentityServer4.Endpoints.CheckSessionEndpoint for /connect/checksession
[2021-08-01T15:43:11.337Z] Information: Normalizing '/newshub' to 'https://localhost:44306/newshub'.
Failed to load resource: the server responded with a status of 401 () [https://localhost:44306/newshub/negotiate?negotiateVersion=1]
[2021-08-01T15:43:11.347Z] Error: Failed to complete negotiation with the server: Error
[2021-08-01T15:43:11.347Z] Error: Failed to start the connection: Error
MessageHub Connection Error: Error
If I remove [Authorize] attribute - it works fine
EDIT to people saying that I use cookie but need bearer token. Its not true. When I tried to specify Cookie as Authorization scheme on the hub class I got this error:
System.InvalidOperationException: No authentication handler is registered for the scheme 'Cookies'.
The registered schemes are: Identity.Application, Identity.External, Identity.TwoFactorRememberMe, Identity.TwoFactorUserId, idsrv, idsrv.external, IdentityServerJwt, IdentityServerJwtBearer.