3

What i just want to know is :

  • The 'Connection Token', present in all the requests, is creating where ? By whom ? Is it possible to customize it ?
  • How can i apply an AuthorizeAttribute only on the "connect" method ?

See, i only want a user to send credentials the first time, then get a token (customized would be great) and use this token to communicate.

I precise i use a simple hub, and no persistent connection.

fazega
  • 327
  • 2
  • 13
  • 1
    SignalR sits on top of HTTP. As such, its security comes from HTTP. How do you authenticate with HTTP? –  Jul 14 '17 at 00:52
  • Via the Authorization header ? – fazega Jul 14 '17 at 00:56
  • They are absolutely solved In [the links you specified](https://learn.microsoft.com/en-us/aspnet/signalr/overview/security/hub-authorization#requireauth) even. If you feel otherwise, please be specific with your question. – Dan Esparza Jul 14 '17 at 00:57
  • I see what you are trying to tell me. But it doesn't solve my two questions: how to apply authorizeattribute on the connect method and how to customize Connection Token – fazega Jul 14 '17 at 00:58
  • Possible duplicate of [SignalR - how to create custom authentication mechanism based on HTTP header?](https://stackoverflow.com/questions/38663924/signalr-how-to-create-custom-authentication-mechanism-based-on-http-header) – Dan Esparza Jul 14 '17 at 00:58
  • @DanEsparza i think my questions are precise, see above – fazega Jul 14 '17 at 00:59
  • @DanEsparza thanks for your link ! I understand better the way to do it. Though doesn't answer the two questions : customizing Connection Token (made my SignalR itself) and access the connect method, which is not present in my Hub of course. – fazega Jul 14 '17 at 01:02
  • 3
    The author of a question will always fully understand his own question. If your question isn't clear to us, it's up to you to clarify. Asserting your question is clear doesn't help Dan -- or anyone else -- to understand. –  Jul 14 '17 at 01:02
  • You're right, i'm sorry. I edited my post to be more precise. – fazega Jul 14 '17 at 01:04
  • 1
    Excellent edit and welcome to Stack Overflow. –  Jul 14 '17 at 01:07
  • The Authorization actually comes from OWIN, so your best bet would learn how to pass the Authorization token information through those pipes. So in the documentation for SignalR, the section where you MapSignalR, you'll need a pipe to pass through the expected Authorization information. This link may help some [Microsoft Principal explanation](https://learn.microsoft.com/en-us/dotnet/standard/security/principal-and-identity-objects) – Joseph King Jul 14 '17 at 01:09
  • I'm not familiar with the connection token, but it sounds like it's another way of saying ['bearer token'](https://security.stackexchange.com/a/120244/22499). Here is [another SO article that may help](https://stackoverflow.com/questions/27980455/passing-connection-token-is-secure-or-hacky-from-signalr-js-client-side-to-hub-f). – Dan Esparza Jul 14 '17 at 01:26
  • I've found in the source code where the connection token is generated. I'm currently writing up an answer on that point. –  Jul 14 '17 at 01:32

1 Answers1

3

As far as I can tell, the connection token is just an ID and the username. The ID is randomly generated. In early versions of SignalR, you could customize it by implementing the IConnectionIdFactory interface, but that hasn't been possible since 2013.

Now, to answer the question "how is it generated", let's delve deep into SignalR's source. I am using ILSpy to search the source code. It's available for free online. You can see my ILSpy window here.

The interesting code is in Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager:

public IPersistentConnectionContext GetConnection(Type type)
{
    if (type == null)
    {
        throw new ArgumentNullException("type");
    }
    string fullName = type.FullName;
    string persistentConnectionName = PrefixHelper.GetPersistentConnectionName(fullName);
    IConnection connectionCore = this.GetConnectionCore(persistentConnectionName);
    return new PersistentConnectionContext(connectionCore, new GroupManager(connectionCore, PrefixHelper.GetPersistentConnectionGroupName(fullName)));
}

That leads us to:

internal Connection GetConnectionCore(string connectionName)
{
    IList<string> signals = (connectionName == null) ? ListHelper<string>.Empty : new string[]
    {
        connectionName
    };
    string connectionId = Guid.NewGuid().ToString();
    return new Connection(this._resolver.Resolve<IMessageBus>(), this._resolver.Resolve<IJsonSerializer>(), connectionName, connectionId, signals, ListHelper<string>.Empty, this._resolver.Resolve<ITraceManager>(), this._resolver.Resolve<IAckHandler>(), this._resolver.Resolve<IPerformanceCounterManager>(), this._resolver.Resolve<IProtectedData>());
}

So there you are. The connection id is simply a random Guid, and the token is the ID plus the username.

  • I'm impressed. What an efficiency ! How did you find the fact about IConnectionIdFactory ? Am I a so poor googler ? – fazega Jul 14 '17 at 02:53
  • I knew about it from years ago, when it was removed. –  Jul 14 '17 at 14:58