Anthony Chu Contact Me

Azure Functions and App Service Authentication with Auth0 and other OpenID Connect providers

Thursday, July 23, 2020

Azure Functions and Azure App Service recently added integration with OpenID Connect (OIDC) providers. We can now use any OpenId Connect compliant provider to authenticate users in our apps.

In this article, we'll look at how to configure Auth0 with Azure Functions. The same steps can be used to configure any other OIDC provider and can also be applied to Azure App Service.

Overview

To integrate an OpenID Connect provider with Azure Functions, we need to follow these steps:

  1. Obtain a client id and secret plus other config settings from the OIDC provider.
  2. Create an authentication config file in our app and add the relevant information from the OIDC provider to the file.
  3. Supply the client secret in an app setting.
  4. Enable file-based authentication configuration in the app.

Create an app in Auth0

Auth0 is a popular identity service. It supports login via many social identities as well as with app-specific accounts.

Instead of configuring our function app with social logins like Google or creating a custom username/password database solution, we can rely on Auth0 to manage all that for us and we simply integrate our app with Auth0 using OpenID Connect.

The first thing we need to do to get started is create a free Auth0 account. Then we create an app in Auth0 of type "Regular Web Application".

Create an app

When the app is created, note the client id and secret.

id and secret

Note: We need to create a function app in Azure before proceeding with the following steps. Auth0 is going to need to use the app name in some configurations.

In the Application URIs section, fill in these settings:

  • Application Login URI - https://<app-name>.azurewebsites.net/.auth/login/auth0
  • Allowed Callback URLs - https://<app-name>.azurewebsites.net/.auth/login/auth0/callback
  • Allowed Logout URLs - https://<app-name>.azurewebsites.net/.auth/logout

URLs

The most important setting is the Allowed Callback URLs, which tells Auth0 about the callback URL that the function app authentication will use.

Note that each URL has a segment with the value auth0. This needs to match the name we give the OIDC provider in the configuration file that we'll cover next.

Click Save Changes. Then click on the subtle Show Advanced Settings link.

advanced settings

In the Endpoints tab, note the OpenID Configuration URL.

well known configs

Create an authentication config file

Currently, OpenID Connect providers can only be enabled in Azure Functions or App Service using a new file-based configuration. Multiple providers can be configured in the same app.

The config file must be located in the root of the function app. We'll create one named auth.json.

Then we place this content in the file:

{
  "platform": {
    "enabled": true
  },
  "globalValidation": {
    "redirectToProvider": "auth0",
    "unauthenticatedClientAction": "RedirectToLoginPage"
  },
  "identityProviders": {
    "openIdConnectProviders": {
      "auth0": {
        "registration": {
          "clientId": "<auth0_client_id>",
          "clientCredential": {
            "secretSettingName": "AUTH0_CLIENT_SECRET"
          },
          "openIdConnectConfiguration": {
            "wellKnownOpenIdConfiguration": "https://<auth0_tenant_name>.auth0.com/.well-known/openid-configuration"
          }
        },
        "login": {
          "nameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
          "scope": [ "openid", "profile", "email" ],
          "loginParameterNames": []
        }
      }
    }
  },
  "login": {
    "tokenStore": {
      "enabled": true
    }
  }
}

Replace the values of clientId with the Auth0 client id, and wellKnownOpenIdConfiguration with the OpenID configuration URL from Auth0.

We've also specified some scopes so that we can obtain profile and email information from the customer.

Now that the auth file is added to the app, we publish the app to Azure.

Note that we didn't put the client secret into the file. That's because we don't want to commit it to source control. Instead, we provide the app setting name (AUTH0_CLIENT_SECRET) that we'll use to store that value in Azure.

Add a client secret app setting

In the function app's Configuration page, create an app setting named AUTH0_CLIENT_SECRET. In the value, paste in the Auth0 client secret.

app settings

Enable file-based auth configuration

The last step we have to take is enable the use of our new file-based auth config. There's no UI for this yet. We can use an Azure CLI command to do it.

az rest --method put --url https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Web/sites/$APP_NAME/config/authsettings?api-version=2018-02-01 --body "{\"properties\":{\"enabled\":\"true\",\"isAuthFromFile\":\"true\",\"authFilePath\":\"auth.json\"}}"

The above command updates the app's authsettings properties with the following values:

  • enabled = true
  • isAuthFromFile = true
  • authFilePath = auth.json

Test it out

Now when we try to access the function app in the browser, we're redirected to Auth0. We can create a new account to log in.

Sign up

In an HTTP triggered function, the authenticated user's information can be obtained from the x-ms-client-principal header. We need to convert it from base64 encoded JSON.

module.exports = async function (context, req) {
  const buffer = Buffer.from(req.headers["x-ms-client-principal"], "base64");
  const user = JSON.parse(buffer.toString("ascii"));

  const email = user.claims.find(c => c.typ === "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").val;
  const nickname = user.claims.find(c => c.typ === "nickname").val;

  context.res = {
    status: 200,
    body: `Hello ${nickname} [${email}]`
  };
};

This function returns:

Hello anthony [anthony@anthonychu.ca]

Resources