Azure Active Directory B2C and Azure Functions


Hello everyone,

In the light of my recent post about B2C and ASP.NET Core web APIs, I thought I'd shed some light on how to make Azure Functions work with B2C, because it may not be immediately obvious from the portal's interface. Actually, all the information is already in this article, and it still applies: https://blogs.msdn.microsoft.com/appserviceteam/2016/06/22/app-service-auth-and-azure-ad-b2c/

 
Setting up B2C authentication for your Azure Functions App is actually really easy:

  1. Create your Azure Functions App and write down the URL

    1. E.g. https://myazurefunctions.azurewebsites.net (make sure to make it a HTTPS URL)

     

  2. Configure your application in Azure Active Directory B2C:

    1. Write down the Application ID
    2. Add a reply URL for your Functions App, adding the suffix /.auth/login/aad/callback. E.g. http://myazurefunctions.azurewebsites.net/.auth/login/aad/callback

     

    The configuration should look something like this:

     

  3. Get the Metadata Endpoint URL for your Sign-in policy

    1. If you open the details of your sign-in policy, you'll find it right at the top. E.g.:

       

  4. In your Functions App, on the bottom left select "Function app settings" and go to "Configure authentication":

     

  5. Turn on authentication and select Azure Active Directory:

     

  6. Select the advanced settings and enter the following values:

    1. Client ID: The Application ID which you copied in step 2. a.
    2. Issuer Url: The Metadata Endpoint URL from step 3.

     

  7. Save your settings and you're done!

 

Once the changes have taken effect, if you try to test your Azure Function without an Authorization header, you'll get the following error – as expected:

 

However, with a valid bearer token, you're up and running again:

 

I hope this made your life a little bit easier.

Cheers,
Helge Mahrt

Comments (6)

  1. Jarrod says:

    Helge,

    This (and the referenced post from last year too) is helpful indeed. However, neither post actually shows invoking the FunctionApp/Function via a simple B2C policy. I've been trying to get mine to work, but to no avail. Do you all have more thorough examples in posts or on GitHub that work? The /.auth/login/aad/callback doesn't seem to be working in the current version of Functions, from my experience anyhow.

    1. Helge Mahrt says:

      Hello Jarrod,
      Once you set this up, the functions app will behave like any other web api that's been secured with B2C. You'll need to provide an Authorization header with a valid access token during the HTTP calls. You need to acquire this token in the client which calls the web API - which also presents the UI to the user - e.g. a web app or a mobile client etc.

      This guide shows how to acquire the access token in a .NET desktop application and use it to call a web api: https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-native-dotnet

      And this one shows the same, but calling from an ASP.NET web app: https://docs.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-devquickstarts-web-api-dotnet

      Hope this helps,
      Helge

      1. Jarrod says:

        Hi Helge,

        That does indeed help. I was assuming that the /.auth/login/aad/callback did something unique, but that's what I get for assuming...

        Thank you very much for the quick response, it helps a lot.

  2. Simon Timms says:

    Hi Helge,

    I was able to get most of this working thanks so much for putting it together. One thing I wasn't clear about was how I'd go about getting the bearer token. I set the callback URL to another function in the same function app but it, of course, couldn't authenticate and I ended up in a bit of a loop. This despite setting the permissions on that other function to be anonymous. It seem like the authorization overrides that. In my scenario I'm attempting to do everything through functions rather than calling into a web application. I'm considering setting up another function app whose sole responsibility is to exchange the authorization code for an access token. Is there, perhaps, another way around that?

    Thanks,
    Simon

    1. Helge Mahrt says:

      IIRC, you should be able to get the Bearer token via the ClaimsPrincipal. E.g. I use this helper to get the B2C user id:

      public static class B2cHelper
      {
          public static string UserID
          {
              get
              {
                  return ClaimsPrincipal.Current?.Claims
                      .FirstOrDefault(x => x.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
              }
          }
      }
      
  3. Thank you Helge, a very good decent article to start with.

Skip to main content