Protecting APIs in Azure API Management using OAuth 2.0 Client Credential Flow

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

Challenge:

I recently helped a customer setting up OAuth 2.0 with Azure AD to protect their API backend in Azure API Management. This Azure Doc has 90% of the content to help you set up everything you need but it lacked setting up client application like Postman to test APIs using Client Credentials flow.

Again, use this Azure Doc go through step 1 through 6 to complete the entire set up. If you are not interested in setting up APIM Developer Portal as Client Application, you can skip step 2, 3, 4 & 5 and follow steps below.

 

Solution:

Purpose of this blog is to go through how to protect your APIs published through Azure API Management using OAuth 2.0 Client Credential Flow and test using Postman. For completeness' sake and to avoid going back and forth I'm including some of the steps from this Azure Doc in this blog.

 

High level steps:

  • Step 1: Register an application in Azure AD to represent the API
  • Step 2: Register another application in Azure AD to represent a client application
  • Step 3: Grant permissions in Azure AD
  • Step 4: Configure a JWT validation policy to pre-authorize requests
  • Step 5: Request JWT token using Postman
  • Step 6: Inspect the token (optional step)
  • Step 7: Make the API call
  • Step 8: Build an application to call the API

 

Step 1: Register an application in Azure AD to represent the API

 

  1. In your Azure Portal, go to Azure Active Directory, select App Registrations

 

  1. Select New registration

 

  1. When the Register an application page appears, enter your application's registration information:
    1. In the Name section, enter a meaningful application name that will be displayed to users of the app, such as backend-app.
    2. In the Supported account types section, select an option that suits your scenario.

 

  1. Leave the Redirect URI section empty.

 

  1. Select Register to create the application.

 

  1. On the app Overview page, find the Application (client) ID value and record it for later.

 

  1. Under the Manage section of the side menu, select Expose an API and set the Application ID URI with the default value. Record this value for later.

 

  1. Under the Manage section of the side menu, select App roles then click Create app role:
    1. In the Display name, enter a meaningful role name for example: AddRole
    2. Allowed member types: select Applications
    3. Value: example: AddRole
    4. Description: <as necessary>
    5. Do you want to enable this app role? checked
    6. Click Apply
    7. Record the role ID for later

  1. Repeat the step 8 to add additional App roles (if any) supported by your API.

 

Step 2: Register another application in Azure AD to represent a client application

Register every client application that calls the API as an application in Azure AD. In this example, the client application is Postman that we will be using to test APIs.

To register another application in Azure AD to represent Postman:

 

  1. In your Azure Portal, go to Azure Active Directory, select App Registrations.

 

  1. Select New registration.

 

  1. When the Register an application page appears, enter your application's registration information:
    1. In the Name section, enter a meaningful application name that will be displayed to users of the app, such as client-app.
    2. In the Supported account types section, select Accounts in this organizational directory only (<tenant name> only - Single tenant).

 

  1. In the Redirect URI section, select Web and leave the URL field empty.

 

  1. Select Register to create the application.

 

  1. On the app Overview page, find the Application (client) ID value and record it for later.

 

  1. Create a client secret for this application to use in a subsequent step.
    1. Under the Manage section of the side menu, select Certificates & secrets.
    2. Under Client secrets, select New client secret.
    3. Under Add a client secret, provide a Description and choose when the key should expire.
    4. Select Add.

 

  1. When the secret is created, note the key value for use in a subsequent step (Note: you can't see/copy this value once you move away from this page, but you can create New Client Secret as needed)

  2.  Repeat this step to register additional clients/customers (if any) who will be consuming your API

 

Step 3: Grant permissions in Azure AD

Now that you have registered two applications to represent the API and the Postman client app, grant permissions to allow the client-app (Postman) to call the backend-app (API).

 

  1. In your Azure Portal, go to Azure Active Directory, select App Registrations.

 

  1. Choose your client app. Under the Manage section of the side menu, select API permissions.

 

  1. Select Add a Permission.

 

  1. Under Select an API, select My APIs, and then find and select your backend-app.

 

  1. Select Application permissions, then select the appropriate role (for example: AddRole) of your backend-app.

 

  1. Select Add permissions.

 

  1. Select Grant admin consent for <your-tenant-name>. Select Yes, if you get green tick mark under Status with message Granted for <tenant name> then you are all set, then move to next step 4.

  2. If you are not an Azure AD Global Admin, you can't provide this admin consent (it will be grayed out). If you are the API App owner (in this case you are because we set up the API App in Step1), then you will be able to use Graph Explorer to provide Admin consent.
  • Go to Graph Explorer (make sure to change the tenant's name in the URL below)
    For example: https://developer.microsoft.com/en-us/graph/graph-explorer?tenant=<tenantname>.onmicrosoft.com
  • Sign in to Graph Explorer
  • In the Search Sample queries enter: appRoleAssignment
  • Select POST assign an appRoleAssignment to a serviceprincipal
  • Click on Modify permissions (Preview) tab and consent Permission to AppRoleAssignment.ReadWrite.All, Directory.AccessAsUser.All & Directory.ReadWrite.All
  • principalId = Client App's Service Principal ID
  • resourceId = API App's Service Principal ID
  • appRoleId = Id of App Role (in this example AddRole that we created in Step 1, you can get it using Portal)
  • To get Client/API app's Service Principal ID (Object ID), use CLI or PowerShell command (It's not available under Azure Portal)

    Using CLI:  az ad sp list --display-name <Azure AD App Name>

    Capture objectId where objectType = ServicePrincipal

    UmarMohamedUsman_1-1641866870741.png

     

  • In the POST URL, make sure to change {id}, this is same as resourceId from above (i.e., API App's Service Principal ID)
    https://graph.microsoft.com/v1.0/servicePrincipals/{id}/appRoleAssignments

  • Run query. If all goes well and you got all the right Ids, you should get Created - 201 response as shown below. Check the API permission again to make sure you got the green tick mark under Status with message Granted for <tenant name>

UmarMohamedUsman_0-1641545350269.png

 

Step 4: Configure a JWT validation policy to pre-authorize requests

Follow the instruction from the following doc to add Validate JWT policy to your API
Protect API backend in API Management using OAuth 2.0 and Azure Active Directory - Azure API Management | Microsoft Docs

 

Add the following Validate JWT policy to <inbound> policy section of your API which checks the value of the audience claim in an access token obtained from Azure AD and returns an error message if the token is not valid.

  • Update aad-tenant value
  • Update aud claim value which is our API App's Application (client) ID which we created in Step1
  • You can also validate additional claims that the token will have, in our case we added App Roles called AddRole in Step 1 (see example below)

 

 

<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."> <openid-config url="https://login.microsoftonline.com/{aad-tenant}/v2.0/.well-known/openid-configuration" /> <required-claims> <claim name="aud"> <value>{backend-api-application-client-id}</value> </claim> </required-claims> </validate-jwt>

 

 


For example, to include additional claim:

 

 

<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid."> <openid-config url="https://login.microsoftonline.com/azurerampup.onmicrosoft.com/v2.0/.well-known/openid-configuration" /> <required-claims> <claim name="aud"> <value>3b0bd75a-d72f-46ec-99f1-040bab17d0ed</value> </claim> <claim name="roles" match="all"> <value>AddRole</value> </claim> </required-claims> </validate-jwt>

 

 

 

Step 5: Request JWT token using Postman

Now that all the setup is over, let's get JWT token first, before we make API calls

 

  1. Go to Postman, create POST request with following values:
  2. URL: Go to your Client App in Azure AD, click Endpoints, copy OAuth 2.0 token endpoint (v2) URL
  3. Select Body then x-www-form-urlencoded
  4. Enter following values

KEY

VALUE

grant_type

client_credentials

client_id

Your client App's (step 2 from above) Application (client) ID, you can copy from Portal

client_secret

Your client App's client secret

scope

<your API app's Application (client) ID>/.default
Note:
You need to include /.default at the end with your ID.

 

e. Send the request, if all goes well you should get the JWT token as shown below.

UmarMohamedUsman_4-1641546693328.png

 

 

Step 6: Inspect the token (optional step)

  1. Go to: https://jwt.ms
  2. Copy the JWT token from previous step and paste, it will decode the token
  3. It will include the roles (for example: roles: "AddRole")
  4. This proves that Postman (client) got the token which has permission to AddRole

 UmarMohamedUsman_3-1641546652164.png

 

Step 7: Make the API call

Time to call our APIs using Postman with JWT token that we got from step 5.

  • Go to Postman, create Get/POST request based on your API operation
  • Select Headers and enter the following values:

KEY

VALUE

Ocp-Apim-Subscription-Key

Subscription key from APIM

Authorization

Bearer <JWT token from step 5>

 

  • Click Send, if all goes well APIM should validate the JWT token, make backend API call and return the response UmarMohamedUsman_2-1641546548938.png

 

 

 

Step 8: Build an application to call the API

 In this blog we used Postman to test API calls, but in Production you or your customers would build an application and implement OAuth 2.0, see Azure AD code samples.

 

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.