I'm using SignalR and angular to create a chat between clients, after the client logged in successfully with jwt token. Once I've added -
[Authorize]
to my hub, I'm getting this error while trying to connect to SignalR -
Debug: HubConnection failed to start successfully because of error 'Error: Failed to complete negotiation with the server: Error: : Status code '401''.
Before I added this attribute, my app connected successfully to SignalR so I know the problem is authorization. What am I doing wrong?
UserHub-
[Authorize]
public class UserHub : Hub
Program.cs-
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder
.WithOrigins("http://localhost:4200")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials()
.SetIsOriginAllowed((host) => true));
});
builder.Services.AddDbContext<TalkBackDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("TalkBackConnectionString")));
builder.Services.AddScoped<IContactRepository, ContactsRepository>();
builder.Services.AddScoped<IWebAPIService, WebAPIService>();
builder.Services.AddScoped<ISignalrService, SignalrService>();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSignalR();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = false,
ValidateAudience = false,
ValidAudience = builder.Configuration["Jwt:Audience"],
ValidIssuer = builder.Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/user")))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
Client-
public startSignalrConnection(connectionUrl: any) {
return new Promise<any>((resolve, reject) => {
this.hubConnection = new HubConnectionBuilder()
.withUrl(connectionUrl, {
withCredentials: false,
accessTokenFactory: () => localStorage.getItem('jwt')!,
})
.configureLogging(LogLevel.Debug)
.build();
CodePudding user response:
After many tries, I found out what was the problem. I missed this line on Program.cs -
app.UseAuthentication();
I've also edited my token (on another microservice) to be the same like here, and added this line -
ValidateIssuerSigningKey=true
Now I can access to SignalR.