4

Using .NET Core 2.1 & VS2017 preview 2 I created a simple web server with "Identity as UI" as explained here and then added a SignalR chat following this.

In particular I have:

app.UseAuthentication();
app.UseSignalR((options) => {
    options.MapHub<MyHub>("/hubs/myhub");
});

..

[Authorize]
public class MyHub : Hub

..

"iisSettings": {
  "windowsAuthentication": false,
  "anonymousAuthentication": true,
     "iisExpress": {
     "applicationUrl": "http://localhost:5000",
     "sslPort": 0

I start the debugger which brings the browser, register a user and log in, then go to http://localhost:5000/SignalRtest (my razor page that uses signalr.js) and verify the chat works fine.

I now try to create a .NET Core console app chat client:

class Program
{
    public static async Task SetupSignalRHubAsync()
    {
        var hubConnection = new HubConnectionBuilder()
                    .WithUrl("http://localhost:5000/hubs/myhub")
                    .Build();

        await hubConnection.StartAsync();
        await hubConnection.SendAsync("Send", "consoleapp");
    }

    public static void Main(string[] args)
    {
        SetupSignalRHubAsync().Wait();
    }
}

My issue is I don't know how to authenticate this client ?

EDIT:

(from https://github.com/aspnet/SignalR/issues/2455)

"The reason it works in the browser is because the browser has a Cookie from when you logged in, so it sends it automatically when SignalR makes it's requests. To do something similar in the .NET client you'll have to call a REST API on your server that can set the cookie, scoop the cookie up from HttpClient and then provide it in the call to .WithUrl, like so:

var loginCookie = /* get the cookie */
var hubConnection = new HubConnectionBuilder()
    .WithUrl("http://localhost:5000/hubs/myhub", options => {
        options.Cookies.Add(loginCookie);
    })
    .Build();

I now put a bounty on this question, hoping to get a solution showing how to authenticate the .NET Core 2.1 SignalR console client with a .NET Core 2.1 web app SignalR server that uses "Identity as UI". I need to get the cookie from the server and then add it to SignalR HubConnectionBuilder (which now have a WithCookie method).

Note that I am not looking for a third-party solutions like IdentityServer Thanks!

kofifus
  • 17,260
  • 17
  • 99
  • 173

1 Answers1

2

I did ended up getting this to work like this:

On the server I scaffolded Login and then in Login.cshtml.cs added

[AllowAnonymous]
[IgnoreAntiforgeryToken(Order = 1001)]
public class LoginModel : PageModel

That is I do not require the anti forgery token on login (which doesn't make sense anyway)

The client code is then like this:

HttpClientHandler handler = new HttpClientHandler();
CookieContainer cookies = new CookieContainer();
handler.CookieContainer = cookies;
HttpClient client = new HttpClient(handler);

var uri = new Uri("http://localhost:5000/Identity/Account/Login");
string jsonInString = "Input.Email=myemail&Input.Password=mypassword&Input.RememberMe=false";
HttpResponseMessage response = await client.PostAsync(uri, new StringContent(jsonInString, System.Text.Encoding.UTF8, "application/x-www-form-urlencoded"));
var responseCookies = cookies.GetCookies(uri);
var authCookie = responseCookies[".AspNetCore.Identity.Application"];

var hubConnection = new HubConnectionBuilder()
        .WithUrl("http://localhost:5000/hubs/myhub", options =>
        {
            options.Cookies.Add(authCookie);
        })
        .Build();

await hubConnection.StartAsync();
await hubConnection.SendAsync("Send", "hello!");

(of course password will be elsewhere in deployment)

kofifus
  • 17,260
  • 17
  • 99
  • 173
  • 1
    For anyone looking into this, while the answer @kofifus provided is good enough to mark as correct, you probably should avoid using Cookies. Cookies are good for API requests, but if you're working with SignalR and especially with .NET SignalR Clients (or in fact, any other non-JS/browser clients) you should look into **Bearer token authentication** - [MS Docs here](https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-2.2) – eja Jun 04 '19 at 11:06
  • 1
    @eja: The problem is that Bearer token authentication is a massive infrastructure setup when compared with a simple login. – Paulo Neves Feb 12 '20 at 19:21