0
votes

I'm trying to learn SignalR and IdentitySever 4. I've created an application which consists of three services: A - Asp .net core MVC application; B - Identity server based on Identity Server 4; C - SignalR service with ChatHub. Application A and C used B as OpenIdConnect identity service. Authorization is required in Home Controller of Mvc application(A) and on ClientHub of Application C.

It should work in a next way:

  1. User open Mvc application(A).
  2. Then he is redirected to identity server(B) in order to log in.
  3. After login user is redirected to the home page of the MVC application and should be made a connection to the SignalR hub and there is a problem. Connection can't be made and it fails on Negotiate request, in the browser console I see only those errors that are not were informational: enter image description here

During the investigation, I've added also controller Home with Index action with authorization to SignalR service, which returns view where also a connection to hub should be made, and in this case, it works.

Added handlers for OpenIdConnectEvents and I see only OnRedirectToIdentityProvider event is raised. I read from https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-3.1 that if the user is logged in, the SignalR connection automatically inherits this authentication, maybe it is the problem that authentication used in MVc app is not valid for Hub. Can anyone help with advice, please?

Update As I can see an error from the console occurs because in case negotiate request is made server returns the login page (https://localhost:5001/connect/authorize?) which means cookies from MVC client are not valid for Hub: authorize request cancelled

Looks like OpenIdConnect here. Is there any way to authenticate users?

1
This quesiton is too broad, it doesn't provide an minimal reproducible example. However with that being said, there's a pretty good chance that you didn't add the middleware to extract the the AuthenticationToken from the WebSocket. By default applications are only setup to handle authentication from the HTTP header, However when connecting ot singlar you need custom middleware to either extract it from the query string, or I believe there is middleware which extracts it from the header when opening the websocketjohnny 5
@ johnny 5 thanks for the advice, but an error occurs on Negotiate request before establishing Websocket connection, and as I mentioned it works if the user was authenticated in hub application.YuriB

1 Answers

0
votes

Found the reason why it didn't work, it was because I used Cookie authentication from a different origin, so I used cookies from MVC-A, it is only allowed to use cookies from the same origin. So I've changed it to JWT token like this:

        services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer("Bearer", options =>
            {
                options.Authority = "https://localhost:5001";

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = false
                };

                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("/chat")))
                        {
                            // Read the token out of the query string
                            context.Token = accessToken;
                        }
                        return Task.CompletedTask;
                    }
                };
            });

Hope it will be helpful if someone has a similar issue.