Authentication Through Azure
Guide
Protect a serverless application with Azure AD and gain access via a SPA.
Old Article
This content may be out of date or broken, please take care.If you didn't know, I started a new job this year with Frontier Labs in Liverpool. With a new job comes new challenges, and the past six months has presented an enviable opportunity to tinker and develop Frontier's first design-driven data product Stratum. It has really been the developer dream of simply working without deadlines to explore the technologies, processes, and architecture that fits my technical vision - a position I haven't been in before.
One such learning has been authentication. Coming from a mostly public-facing web background into the world of single-page applications and many users has been one of my first real challenges. I want to share that with you.
This article is going to focus on authenticating Azure functions for consumption by a SPA, but I would like to touch on an alternative I have also used. This alternative is more fitting if you're creating an application where you want users to register, and you want to store their details in your own infrastructure. If you are considering this, take a look at Identity Server with the OIDC client library. I didn't find it easy to set up and use, but I succeeded in the end. It's key to remember this is a server tool for managing OAuth2, you're responsible for how you go about using it. In many ways, it provides too many solutions, and it can be quite easy to misunderstand as it is so broad. If it helps you; I used the code flow for auth - I expected a popup sign-in screen, but you can't do it with the more secure code flow. It has to be a page redirect! That's the only lesson I want to share here - on to Azure.
Microsoft identity platform (formerly Azure Active Directory for developers)
Our next product requires us to work with an Enterprise organization who are using Active Directory. If you are planning the same, or you simply need to authenticate an app for your own organization; read on. if you want to create accounts specific to your app, this likely isn't the route you want to take.
Azure Authenticate
In Azure, a common sight is this button in web or function blades:
I always saw it, didn't think much to it. Turns out, instead of writing a load of code, spinning up an authentication service and trying to join it all together (at cost to you) - Microsoft has empowered Azure AD to really help you with this. You can read loads about it here and from there; find resources to guide and help you build your own setup.
In Short
If you want to protect an Azure function, and call it from your SPA: here's what I did. Firstly, make sure you have an Azure function set up. You'll also need Azure AD already set up, you may also need to speak with your IT department...
- Register a new application with Azure AD. This guide was handy.
- You want to add the URLs your client app will redirect to after a user signs in
- Check the boxes for access tokens and ID tokens
- Expose your API - you'll need your app ID for this. Mine looks a bit like this:
- Authenticate your Azure function. Go to the function, click "Authentication"
- Switch on
- (Optional) Set the action to take when not authenticated to Azure AD
- Configure Azure Active Directory
- Select "Express" > select the app you created before
- Gotcha: You're going to need your Application ID URI which you can find in in the expose API blade of your application (like in screenshot above). Go to advanced settings, you should see this has already been filled in. You need to paste your API URI in the "Allowed Token Audiences" section. Like so:
- Save
- Set up your client with Microsoft's MSAL client library
- Gotcha: If you're using framework like Vue.js, you might find after a user is logged in, the pop-up get's stuck, or after a redirect, nothing happens. You might see this issue for it on Github. For me, it was Vue router. Azure AD tries to route back with an ID token, but it's not actually a query string but a full-blown URL, ie.
/id_token=...
Make sure you have a catch-all route, with an instance of MSAL on that view! - Gotcha: When you set your scope, this must be the Application ID URI we used before:
You can find the full scope in your expose API section in the application in Azure AD. - I stored my token in session storage as can be seen above. When you make your call to your API, you'll need to get that, and set an "Authorization" header with a "Bearer {your JWT token}".
- Gotcha: If you're using framework like Vue.js, you might find after a user is logged in, the pop-up get's stuck, or after a redirect, nothing happens. You might see this issue for it on Github. For me, it was Vue router. Azure AD tries to route back with an ID token, but it's not actually a query string but a full-blown URL, ie.
All the above steps can be pieced together from the guides I have linked to. Mostly, I want to highlight the parts I got stuck on. Fingers crossed, you won't see a 401 when you call your API. Azure AD is a superb approach if you're wanting to provide single sign-on to your clients. Especially if (to my assumption) you consider another Azure AD organization can just loop into your organization's AD and use your registered app but still manage their own users.
This is a whole world away from the pain I had with IdentityServer, and the whole thing is free. I'm not 100% how secure this is, as IdentityServer docs suggest the implicit flow is bad and you should use the code flow. Microsoft docs argue for pure SPA setups, implicit is fine. My knowledge of security is enough to get by, but you should do your own research into the two.