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.

Solution overview

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.

The idea is somewhat difficult to grasp, and LOTS of details have to go right in order the construct to work. The best explanation for the pattern can be found on page Tutorial – Enable your Web Apps to sign-in users and call APIs with the Microsoft identity platform for developers. This explained all the different patterns used in authentication. Finding the Call your own API – example shows exactly how the app registrations should be done using the “frontend calls backend using on-behalf-of pattern”. The example guides you to create this kind of construct, that will also work also with our single page javascript apps:

Image: Single Page App, Functions and App registrations.

Sample code

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.

Notice that you’ll need a web server to test these SPAs – you can’t get them to work from local files. This is because Azure authentication REQUIRES you to enter a redirect uri (or multiple uris), where you are allowed to return after authentication. The samples are simplified from this Microsoft example: MSAL.js 2.x Vanilla JavaScript Single-page Application

 

Tasklist in short

Here’s an overview of what you need to do:

  1. Create & deploy your azure function. Test it without authentication first.
  2. Guide: Configure your Azure Functions app to use Azure AD login.
    1. Apply the advanced configuration section from the above linked guide.
    2. Expose an API
    3. Turn on AAD authentication in your function’s app service plan.
  3. Create an app registration for your SPA
    1. Guide: Register a new application on Azure Portal. You’ll be using the MSAL.js 2.0 with auth code flow.
    2. The redirect URIs: This is the uri (or uris) where you want to return after the login redirect flow has completed.
  4. Give your SPA app registration rights to call your function app.
    1. You have already “Exposed an API” in the function app registration…
    2. Next “Use API” on your frontend app registration.
  5. Configure your sample application to use the registration info you created.
  6. Done!

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
  • Expose the API makes the api available for other applications to use. The scope part is important. You’ll need the scope defined here when creating the frontend app registration. And later on you need to copypaste this scope to your javascript as well. Scope is the full string, for example,  https://myfunctionaddress/user_impersonation – see image below.

 

Expose Api

Scope Name

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.

1_api-permissions

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.

2-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.

3-grant-admin-consent

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.

authConfig.js

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:
      • https://core.jannehansen.com/spa/plainlogin
      • https://core.jannehansen.com/spa/graphapi
      • https://core.jannehansen.com/spa/functioncall

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.

authRedirect.js

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!