SignalR Unexpected server response: 200

74 views Asked by At

I'm trying to set up a SignalR server in .Net Core 8 using OpenIddict for authentication. However, I keep getting errors when trying to connect using a client application.

I initially set up a SignalR client in Flutter (this is meant to become a chat application) using this package but kept getting the following error:

WebSocketException: Connection to 'https://localhost:7167/chat?id=7jBaqym0ZCsx3BFNkROuAg&access_token=<my-token># was not upgraded to websocket' 
...
The underlying connection was closed before the hub handshake could complete.

I eventually just tried to do a WebSocket request with Postman but I'm now getting the error in the title, with no additional information.

If I include the 'id' query parameter:

Could not connect to wss://localhost:7167/chat?id=MlUKLB8YmTPVsPLN5X5-ug&access_token=<my-token>
Error: Unexpected server response: 400

If I don't include the 'id' parameter:

Could not connect to wss://localhost:7167/chat?access_token=<my-token>
Error: Unexpected server response: 200

(Using {"protocol":"json","version":1} as message body)

The only logs I get on the server are from OpenIddict successfully (I think) authenticating the request, but no logs from SignalR.

I've tried just about every solution posted online, and nothing seems to work or even give me other errors. I've tried several different plugins on the Flutter side of things as well, as there seem to be multiple different options.

My server's Program.cs looks like this:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR(options =>
{
    options.EnableDetailedErrors = true;
    options.DisableImplicitFromServicesParameters = true;
});
builder.Services.AddSingleton<IUserIdProvider, UserIdProvider>();

builder.Services.AddOpenIddict()
    .AddValidation(builder =>
    {
        builder.SetIssuer("<my-auth-url>");
        builder.AddAudiences("<my-client-id>");
        builder.UseIntrospection()
               .SetClientId("<my-client-id>")
               .SetClientSecret("<my-secret>");

        builder.UseSystemNetHttp();
        builder.UseAspNetCore();
    });

builder.Services.AddAuthentication(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
builder.Services.AddAuthorization();

builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptions>());

var app = builder.Build();

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.MapHub<ChatHub>("chat");

app.Run();

My hub looks like this:

[Authorize]
public class ChatHub(
    ILogger<ChatHub> logger) : Hub<IChatClient>
{
    public async Task SendMessage(string message)
    {
        await Clients.All.ReceiveMessage(Context.UserIdentifier, message);
    }
}

I'd also like to mention that both the server and the Flutter app are running locally on my machine.

Any help would be greatly appreciated. Thanks.

1

There are 1 answers

0
katkak On

I've figured out the answer.

When trying to figure out my API layout, I had made a controller that I had planned to use to get chat history.

I called it ChatController, decorated it with the attribute [Route("[controller]")] and then promptly forgot about it.

This, of course, conflicts with the route to my Hub.