Validate access tokens from multiple identity providers on Azure API Management

Emanuele Pecorari
9 min readMay 30, 2023

Azure API Management empowers you to expose, manage, and safeguard your APIs effortlessly. Discover the true potential of this robust service as we dive into configuring its policy capabilities. In this article, we will unveil the secrets of leveraging Azure API Management policies to validate access tokens from various identity providers and seamlessly handle authorization using scopes.

Whether you’re a seasoned developer or just starting your API journey, this article has something for everyone. We’ll guide you through a simple yet impactful use case that showcases the incredible versatility of API management policies. As you follow along, you’ll witness how the available syntaxes and features within policies can transform your request and response processing, making it more powerful and efficient.

While we explore a straightforward scenario, it’s essential to note that the potential of Azure API Management policies extends far beyond this. As your needs grow more complex, these policies offer structured solutions to address intricate use cases. Prepare to unleash the endless possibilities and take your API management game to new heights.

Join us on this exciting journey and unlock the full potential of Azure API Management policies. Get ready to elevate your API security, authentication, and authorization to new horizons.

Use Case Description

Our use case involves a single deployed API that exposes the following main resources:

  • GET /hotels - Retrieves a list of hotels.
  • POST /hotels - Creates a new hotel.
  • DELETE /hotels/{hotel-id} - Deletes a hotel.

We will use two identity providers in our example:

  1. Auth0 — The requests passing the token from Auth0 will have permissions only to retrieve the result of GET /hotels. Requests to POST and DELETE with the same tokens will receive a 403 Forbidden response.
  2. Azure AD — The caller using Azure AD as the identity provider can use all three methods (GET, POST, DELETE).

We will use scopes to manage authorization for the API endpoints.

Prerequisites

Before we proceed, make sure you have the following:

  1. Access to the Azure Portal.
  2. An Azure API Management instance set up in your Azure account.

Step 1: Configure the API in Azure API Management

Let’s consider we have create our API Management instance with the name “hotelapi-test”

https://hotelapi-test.azure-api.net

The created API Management instance

We need to configure the API in Azure API Management. Follow these steps:

  • Log in to the Azure Portal.
  • Navigate to your Azure API Management instance.
  • Select “APIs” from the left-hand menu.
  • Click on the “Add API” button.
  • Provide the necessary details for your API, such as the name, URL suffix, and subscription required settings.
  • Save the changes.

Step 2: Add the API operations

Select the API created and click the button “Add operation”.

Enter the name of the operation (you can start with Add hotel), the method (POST) and the path (/hotels).

Repeat the process for the GET and the DELETE (including the url parameter {hotel-id} in the path field)

At the end you will have something like this:

The API operations

Step 3: Configure Identity Providers

Next, let’s configure the identity providers. For this example, we will use Auth0 and Azure AD.

Configure Auth0

  • Log in to your Auth0 account.
  • Create a new API in Auth0 and note down the API identifier (audience) from the “Settings” tab.
The Identifier of the application which will be the audience in the token
  • Configure the required permissions and scopes for the API endpoints. Go to the “Permissions” tab and configure the following scope:

read:hotels - Grants permission to retrieve hotel data.

Remember to click on the “Add” button on the right side after having entered the scope details.

The scopes for the application
  • In the “Machine to Machine applications” tab check that the application that has been created by default has the assigned scope and it is authorized to use the custom API. If not, click on the switcher and click on the checkbox related to the scope
Assign permissions to the test application
  • Get the client id and the client secret to be able to retrieve the token. For that, click “Applications” on the left menu of the Auth0 dashboard and choose the hotelapitest (Test Application) from the list

In the Basic information section you find the information about Client ID and Client Secret (unhide it clicking on the eye icon)

Configure Azure AD

  • Create an Azure AD tenant: If you don’t already have an Azure AD tenant, create one by signing up for an Azure account and navigating to the Azure AD portal. Follow the instructions to create a new tenant.
  • Register an application: Inside your Azure AD tenant, register an application that represents your API. Provide a meaningful name for the application
App registration on Azure AD
  • Create the secret and the secretID for the application going to the “Certificate & Secrets” section and clicking “New client secret”
Create client scret on Azure AD
  • Copy and note the secret somewhere because you will use it to retrieve the access token. Note also the Client ID for the application that is listed in the “Overview” section.
The overview section with the Application ID
  • Create the scopes for the application clicking “App roles” on the left menu and adding the following scopes clicking “Create app role”
read:hotels
write:hotels
Add an app role

Add the 2 roles.

The 2 added roles
  • Now, always on the left menu click “API permissions” and then on “Add a permission”.
  • On the right side panel that will open click on the “My Api” tab and choose the created API
  • Choose the 2 permissions created before and click the blue button “Add permissions”
Add the permissions
  • The roles are now ready to be included in the token retrieved by the app

Step 4: Configure Azure API Management Policy

Now, let’s configure the Azure API Management policy to validate the access tokens from different identity providers, enforce the required permissions based on scopes, and manage authorization. Follow these steps:

  1. In the Azure Portal, navigate to your Azure API Management instance.
  2. Select the API you previously configured.
  3. Under the “API” section, click on the previously created APIs (Hotel API Test in our case), click “All operations” and select the small pencil icon close to the “Frontend” header in the APIdesigner interface.
  4. Replace the existing policy with the following policy:
<policies>
<inbound>
<base />
<set-variable name="token" value="@{
var authHeader = context.Request.Headers.GetValueOrDefault("Authorization", "");
if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Bearer "))
{
return authHeader.Substring(7);
}
return null;
}" />
<set-variable name="iss" value="@(context.Variables.GetValueOrDefault("token", "").AsJwt()?.Claims["iss"]?.FirstOrDefault() ?? "")" />
<choose>
<when condition="@(context.Variables.GetValueOrDefault("iss", "").Equals("AUTH0_TENANT") && context.Request.Method.Equals("GET"))">
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" require-expiration-time="true">
<openid-config url="https://YOUR_AUTH0_DOMAIN/.well-known/openid-configuration" />
<audiences>
<audience>YOUR_AUTH0_API_IDENTIFIER</audience>
</audiences>
<required-claims>
<claim name="scope">
<value>read:hotels</value>
</claim>
</required-claims>
</validate-jwt>
</when>
<when condition="@(context.Variables.GetValueOrDefault("iss", "").Equals("https://sts.windows.net/<YOUR_AZURE_DIRECTORY_TENANT_ID>/"))">
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid." require-expiration-time="true">
<openid-config url="https://login.microsoftonline.com/YOUR_AZURE_AD_TENANT/.well-known/openid-configuration" />
<audiences>
<audience>YOUR_AZURE_AD_AUDIENCE</audience>
</audiences>
<required-claims>
<claim name="roles">
<value>read:hotels</value>
<value>write:hotels</value>
</claim>
</required-claims>
</validate-jwt>
</when>
<otherwise>
<return-response>
<set-status code="403" reason="Forbidden" />
</return-response>
</otherwise>
</choose>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>

Make sure to replace the following placeholders:

  • YOUR_AUTH0_DOMAIN with the domain of your Auth0 identity provider.
  • YOUR_AUTH0_API_IDENTIFIER with the identifier (audience) of your Auth0 API.
  • YOUR_AZURE_AD_TENANT with the domain of your Azure AD identity provider (your_tenant_name.onmicrosoft.com).
  • YOUR_AZURE_AD_AUDIENCE with the audience for the Azure AD provider in the format api://<APPLICATION_CLIENT_ID>.
  • YOUR_AZURE_DIRECTORY_TENANT_ID the UUID foundable under the Overview section of the App registration.

This policy includes conditional token validation based on the issuer claim (iss) in the JWT token. It extracts the token from the Authorization header, get the issuer (placing it in a context variable used later) and it starts a conditional validation against the appropriate OpenID configuration URL and audience claim for each identity provider. It also checks for the presence of the required scopes (read:hotels and write:hotels) for authorization.

Specifically, for the Auth0 provider, it checks that the called method is GET (the only allowed) and the scopes contains the needed read:hotels.

In case the use case was more complex we would probably need to split the policy

Step 5: Set Up Mock Responses

To simulate the behavior of the API endpoints and test the policy, we can set up mocks in Azure API Management. Follow these steps:

  1. In the Azure Portal, navigate to your Azure API Management instance.
  2. Select the API you previously configured.

Follow the instructions for the 3 API resources at:

configuring the following response bodies:

POST /hotels

HTTP code: 201

{
"id": "9slsdjd-iislz992033-AAJSKSz"
}

GET /hotels

HTTP code: 200

[
{
"id": "494932p-829298sjeh-l71clm2",
"name": "Hotel Savoy"
},
{
"id": "594932p-bp298sjeh-m72clml",
"name": "Hotel Rembrandt"
}
]

DELETE /hotels/{hotel-id}

HTTP code: 204

No body for this endpoint

Step 5: Demo the Final Result

Now, you can demo the final result by making requests to the API endpoints with tokens from different identity providers.

  • Obtain an access token from Auth0
curl --request POST \
--url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
--header 'content-type: application/json' \
--data '{"client_id": "YOUR_AUTH0_API_IDENTIFIER", "client_secret": "YOUR_AUTH0_API_CLIENT_SECRET", "audience": "https://hotelapi-test.azure-api.net", "grant_type": "client_credentials"}'
  • Obtain an access token from Azure AD
curl --request POST \
--url 'https://login.microsoftonline.com/402627e0-9f04-4571-aae1-32ab0d6e3556/oauth2/v2.0/token' \
-header ‘Content-Type: application/x-www-form-urlencoded' \
-data-urlencode 'grant_type=client_credentials' \
-data-urlencode 'client_id=<AZURE_AD_CLIENT_ID>’ \
-data-urlencode 'client_secret=<AZURE_AD_CLIENT_SECRET>' \
-data-urlencode 'scope=api://eeacfc8d-7a34–4934-b3bf-1d1878a75ffa/.default'

Send a GET /hotels, POST /hotels and DELETE/hotels/{hotel-id}request to the API with the Azure AD token in the Authorization header.

  • If the token is from Auth0 and has the read:hotels scope, you will receive the successful responses.
  • If the token is from your chosen identity provider and has the read:hotels scope, you should also receive a successful response.
The succesfull request to GET /hotels with any of the 2 token

Repeat the same with the Auth0 token in the Authorization header.

  • For the GET /hotels, you will receive the correct response
  • For the POST /hotels and DELETE/hotels/{hotel-id} you will get an error 403 Forbidden
The 403 error returned for the Auth0 token calling the POST /hotels

By following these steps, you have successfully configured Azure API Management to validate access tokens from different identity providers, manage authorization using scopes, and enforce fine-grained access control for your API endpoints.

Conclusion

Azure API Management provides a comprehensive platform to secure and manage your APIs. By configuring the policy to validate access tokens from different identity providers, manage authorization using scopes, and enforce fine-grained access control, you can ensure that only authenticated and authorized requests are allowed to access your API resources. This enhances the security and control of your APIs, enabling you to meet the specific requirements of your use case.

--

--

Emanuele Pecorari

Cloud Architect and Tech Product Owner. Soccer player and coach in the free time.