This article shows how to call Azure AD protected Functions from Single Page Application (SPA). The task seems trivial, but you can easily spend days finding up-to-date instructions. This article is updated 14.10.2020 to use the MSALv2 library and the conventions on how to register your apps on Azure AD to get this working.
I needed to call Azure AD-protected Functions from my Single Page App (SPA).
The key point in solution is to create two app registrations linked together. One for the function app, which Exposes the API, and the other one for your frontend single page application that uses the API. Both are configured to use Azure AD for authentication. Your create these app registrations on your Azure AD.
Image: Single Page App, Functions and App registrations.
I’ve created a small github repo for the frontend single page application, this should get you started on the topic. The repo contains samples for three scenarios:
- Basic login with nothing else
- Login and calling MS Graph “me” function to get user details like name.
- Login and calling my own Azure AD protected function.
Tasklist in short
Here’s an overview of what you need to do:
- Create & deploy your azure function. Test it without authentication first.
- Guide: Configure your Azure Functions app to use Azure AD login.
- Apply the advanced configuration section from the above linked guide.
- Expose an API
- Turn on AAD authentication in your function’s app service plan.
- Create an app registration for your SPA
- Give your SPA app registration rights to call your function app.
- You have already “Exposed an API” in the function app registration…
- Next “Use API” on your frontend app registration.
- Configure your sample application to use the registration info you created.
Let’s focus on the difficult parts.
Function App Registration
Follow the instructions on this page: Configure your Azure Functions app to use Azure AD login.
While all steps described are important, I’d pinpoint the following:
- The redirect uri:s, put them exactly as described in the documentation, replace the url start with your own function’s https address. For example, https://myfunctionapp.azurewebsites.net/.auth/login/aad/callback
Image: Expose an Api & Scope Name
The above string in whole is your Scope – you’ll need it on frontend app registration, and you need to put in your spa code.
Register your frontend app, use an API
Next you need to create the second app registration in Azure AD, now for your frontend application. First, follow these instructions: Register a new application, use the recommended MSAL.js 2.0 with auth code flow. After this your app registration is ready for handling logins, but it can’t call your functions yet – we’ll configure that next.
Add permission to call your function app
Now we’ll give your frontend app rights to call the API you exposed in the function app registration.
Once you have created new App registration for your SPA (mine was named CoreApp), go to Manage / API permissions on app registration. From there, + Add a permission.
Image: Add Permission to your frontend app.
Next find and pick your function app registration (mine was called anothervApp). Select “user_impersonation” and Add Permission.
Image: Select “user_impersonation” and add permission.
Optional last step: Grant Admin consent. This means that each individual user doesn’t have to accept the consent – your frontend application calls your backend application on behalf of the user. You as an administrator can pre-accept this for everyone.
Image: Grant admin consent if you wish. Optional.
Congratulations! Now the app registrations should be ok. Let’s move on to the actual application.
Configure the values into the sample application
Clone my sample app repo. The examples contains three separate applications for most typical use cases. I suggest you first test that your login works; try the plainlogin directory sample. Then head to functioncall directory, which contains the sample to call your own function.
This file links your application the frontend app registration you created. Replace the following:
- Frontend app registration clientId. Get this from your app registration, it can be found on registration overview page, Application (client) ID
- authority, pick either:
- If you allow any microsoft account for login (personal, work, xbox, hotmail, any), the authority will be https://login.microsoftonline.com/common/
- If you only allow users from your personal AD to login, the authority is in format: https://login.microsoftonline.com/tenant_id. You get your AD tenant id from the app registration overview page, under Directory (tenant) ID
- redirectUri is your app URL where to return after the Microsoft login redirect flow has completed. In my samples, we always want to return to the same page we left from. So in my example, the return uri is for example:
One very important thing. The redirectUri must match PRECISELY the url you entered in frontend app registration. Otherwise this won’t work. Use your own return addresses, depending on how and where you installed the sample apps. But the idea is to return to the same page you left from.
This file contains:
- The actual token acquisition process & login implementation. This is marked top part of the file, you shouldn’t need to change anything here in your own implementation.
- graphapi example: Calling MS GraphAPI (marked on bottom of file)
- functioncall example: Calling your own AD-protected function (marked also on the bottom of the file)
when you test plainlogin or graphapi call, you shouldn’t need to change anything on authRedirect.js file – should work as is.
For the functioncall example,
- first change the const functionCallRequest scope to match yours…
- …then change function endpoint to match your function’s address.
- And depending on what your function does, change the input/output parameters for the actual call in
function callMyFunction(accessToken). My test function used GET, with single name parameter, and then returned “Hello [name]!” as response body. Your’s will most likely do something else, change this call accordingly.
Problems? 401- Forbidden?
To shorten the story: The problem is most likely in the App Registrations. Make sure the app registrations are done EXACTLY as stated in the MS documentation. redirect uri’s – clientid, tenant, scope definitions etc.
This is pretty much it. Now you should be able to call your AD-protected functions. As you saw, lots of details has to go right in order to make this work. After finding the right document(s), the implementation usually takes only few minutes.
This method works now at the time of writing. Please notify me when it doesn’t work anymore. Until that – Enjoy!