Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.Net Core Console connect signalR 401 under windows authentication #6120

Closed
Edward-Zhou opened this issue Dec 26, 2018 · 16 comments
Closed

.Net Core Console connect signalR 401 under windows authentication #6120

Edward-Zhou opened this issue Dec 26, 2018 · 16 comments
Assignees
Labels
area-signalr Includes: SignalR clients and servers investigate
Milestone

Comments

@Edward-Zhou
Copy link

Edward-Zhou commented Dec 26, 2018

Describe the bug

When .net core signalR console app connect signalR server with Windows Authentication, receive 401.

To Reproduce

Steps to reproduce the behavior:

  1. Using this version of ASP.NET Core netcoreapp2.1 with Windows Authentication enabled.
    [Authorize]
    public class TimeHub: Hub
    {
        public async Task UpdateTime(string message)
        {
            if (Clients != null)
            {
                await Clients?.All.SendAsync("ReceiveMessage", message);
            }
        }
    }
  1. .Net Core Console App
    class Program
    {
        static Action<string> OnReceivedAction = OnReceived;
        static void Main(string[] args)
        {
            Console.WriteLine(WindowsIdentity.GetCurrent().Name);
            //WindowsIdentity.RunImpersonated(WindowsIdentity.GetCurrent().AccessToken, Connect);
            Connect();
            Console.WriteLine("Hello World!");
            Console.ReadLine();
        }

        private static async void Connect()
        {
            var hubConnectionBuilder = new HubConnectionBuilder();
            var hubConnection = hubConnectionBuilder.WithUrl("http://localhost:61045/timeHub",options => {
                options.UseDefaultCredentials = true;
            }).Build();
            await hubConnection.StartAsync();
            await hubConnection.SendAsync("UpdateTime", $"From Client");
            var on = hubConnection.On("ReceiveMessage", OnReceivedAction);
            Console.WriteLine($"Client is Start");
            Console.ReadLine();
            on.Dispose();
            await hubConnection.StopAsync();
        }

        static void OnReceived(string message)
        {
            Console.WriteLine($"{ message }");
        }
    }

Expected behavior

Console App connect signalR server correctly.

Current behavior

Receive error 401 at console app.

Update:

After making a test with https and http url in client signalr, it works with https url, it seems app.UseHttpsRedirection(); at server side fail to redirect the client credential while redirecting http to https.

@davidfowl davidfowl added the area-signalr Includes: SignalR clients and servers label Dec 26, 2018
@BrennanConroy
Copy link
Member

Is app.UseHttpsRedirection() at the beginning of your middleware pipeline? Can you share your Startup.cs? Can you capture the server logs at Debug level?

@Edward-Zhou
Copy link
Author

Edward-Zhou commented Jan 3, 2019

This is my startup.cs

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseAuthentication();
            //app.UseMiddleware<MyHttpsRedirectionMiddleware>();
            app.UseStaticFiles();
            app.UseCookiePolicy();
            app.UseSignalR(routes => {
                routes.MapHub<TimeHub>("/timeHub");
            });
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

Check SignalRPro for reproducable demo.

@BrennanConroy
Copy link
Member

Take a look at our docs for windows auth https://docs.microsoft.com/aspnet/core/security/authentication/windowsauth?view=aspnetcore-2.2

Once I added the services.AddAuthentication(IISDefaults.AuthenticationScheme); because the apps logs said "No authenticationScheme was specified, and there was no DefaultChallengeScheme found." then the app started working. I hosted it behind IIS, I'm assuming that is what you're doing, otherwise you'll need to use Http.Sys and configure it based on the docs.

@Edward-Zhou
Copy link
Author

Is there any difference between hosting in IIS and IIS Express?

Currently, I am developing with VS and IIS Express, I did not receive any error related with No authenticationScheme was specified. Even through, I add code services.AddAuthentication(IISDefaults.AuthenticationScheme);, it still throw 401.

Do you make it work with my demo project?

@BrennanConroy
Copy link
Member

I made your demo project work with hosting in IIS, didn't try with IIS Express, but the docs I linked also talk about IIS Express.

@Edward-Zhou
Copy link
Author

How to make my project work with IIS Express?

@BrennanConroy
Copy link
Member

@bradygaster bradygaster added this to the Discussions milestone Jan 7, 2019
@Edward-Zhou
Copy link
Author

Not sure what you mean by sharing the link.

I already configured the windows authenticaiton in IIS.

capture

I would wonder whether you really make a test with this issue!!!

@BrennanConroy
Copy link
Member

Ok, looked into this and it turns out that for security reasons this scenario of redirecting to https with auth doesn't work by default. See https://docs.microsoft.com/en-us/dotnet/api/system.net.httpwebrequest.credentials?view=netframework-4.7.2#remarks for info.

It looks like you can create a CredentialCache and use that in the HttpClientHandler to allow the redirect to work. Or just always connect to the https endpoint so you don't run into this issue.

@Edward-Zhou
Copy link
Author

I am using SignalR and HubConnectionBuilder, how to use CredentialCache in SignalR?

@BrennanConroy
Copy link
Member

Use the HttpMessageHandlerFactory in the WithUrl options, see https://docs.microsoft.com/aspnet/core/signalr/configuration?view=aspnetcore-2.2#configure-additional-options for reference

@Edward-Zhou
Copy link
Author

Any sample for setting HttpMessageHandlerFactory with CredentialCache?

@BrennanConroy
Copy link
Member

Nope, you'll be the first time I've heard of someone doing it.

@Edward-Zhou
Copy link
Author

If so, is it expected result that receiving 401 when signlaR client requests server with http which secured with windows authentication?

How could HttpMessageHandlerFactory resolve this issue?

@mikaelm12
Copy link
Contributor

var connection = new HubConnectionBuilder()
    .WithUrl("<SOME ENDPOINT>", options =>
    {
        var handler = new HttpClientHandler()
        {
            Credentials = /*CONFIGURE YOUR CREDENTIAL CACHE*/
        };

        options.HttpMessageHandlerFactory = (_) => handler;
    }).Build();

The code would look something like this.
You can look at https://docs.microsoft.com/en-us/dotnet/api/system.net.httpwebrequest.credentials?view=netframework-4.7.2#remarks and https://docs.microsoft.com/en-us/dotnet/api/system.net.httpwebrequest.credentials?view=netframework-4.7.2
For more context on the credentials property.

@mikaelm12
Copy link
Contributor

Closing this as we haven't heard from you in a little while. Please feel free to comment if you're able to get the information we're looking for and we can reopen the issue if we're able to identify the problem.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 3, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-signalr Includes: SignalR clients and servers investigate
Projects
None yet
Development

No branches or pull requests

6 participants