Authorize Your Azure AD Users With SignalR
As with pretty much everything in the ADAL packages, this is something that seems like it should be pretty straight-forward, but isn’t.
Before we go on to SignalR, we need to have a look at how we access a Web API endpoint that requires authentication from JavaScript. If you’re already familiar with AD and bearer tokens, you can skip this bit.
It’s Easy in WebAPI
Okay, let’s say we have an OWIN app already set up to use Azure Active Directory for authorisation.
This means that, in our controllers, we can do things like this:
and only authenticated users will be able to hit that endpoint.
Including Authorize
is enough to force users to authenticate to get through, and to populate ClaimsPrincipal.Current
with the user credentials.
Connecting from JavaScript
Now we have our API endpoint, how do we access it from JavaScript?
Microsoft provide an Azure AD library for JS as part of the general Azure library. The example code only shows samples for using it with Angular. If you want to go down a less masochistic route and just use something like JQuery, then there’s also an annoyingly hard to find library of sample code for ADAL without using Angular.
The ADAL library provides a wrapper through which we can grab a bearer token to attach to any requests.
I don’t want to go into this in too much detail since there are two full libraries of code samples linked above, but we’ll end up with something like this:
Once have have something like that set up, we can initialise then get bearer tokens from our client. Then we can add that token into our AJAX request and pass through to our Users API (from above).
So now that’s out of the way, how does that fit in with SignalR?
It’s Not Easy in SignalR
It’s not as simple to wrap up calls to a SinglaR hub to include a bearer token as it is with a raw AJAX request. But, we do have a simple method to append things to the query string.
So, we’ll use that to append the current bearer token to the hub connection when we have one. With our helper code from above, this becomes as simple as:
(You may be concerned that the query string isn’t a secure place to store the bearer token but, even using with an API call, the token is still stored unencrypted on the client side and sent with every request so this isn’t much different. Bearer tokens are also transient so they’ll be refreshed periodically.)
We now need to show the Hub how to get the bearer token.
Setting Up The Hub With AD
As with the Web API code above, the set-up for using AD with SignalR comes from the Microsoft.Owin.Security.ActiveDirectory NuGet package.
This is pretty much the same as for Web API, with the exception of line 5 specifying a custom bearer token provider. It’s this class that will pull the bearer token from the query string value we injected on the client, and insert it into the AD pipeline.
There are a bunch of implementations of this around the web, but the version I ended up with is this:
All this is doing is pulling the token from the request query string and inserting it into the context. The ADAL helpers then process it as normal.
Authorizing the Hub
Now that’s done, we can add an Authorize
attribute to our code to authenticate. The ClaimsPrincipal
for the authorised user is stored in the Context.User
property of the hub.
So, using these together, we get:
And everything else Hub-related should continue to work as normal.