Close

Authorizing API Management back-end service

A common scenario is where you have a vast number of external customers that need access to a set of company services. To make this scenario a little more specific. Let’s say the external customers use a SiteCore web portal and connect to a D365 Finance & Operations (ERP) backend service.

For access to the portal you use Azure AD B2C. From there you call API Management without any security. After all, you are already authenticated. So why use an AAD Authorization Server or an AAD B2C Identity Provider? The problem is though, that the D365 service doesn’t want to be unprotected. Users must be authorized via Azure AD (not AAD B2C). But this authentication needs to happen unattended.

Our solution was to create an application in Azure AD. An AAD application is one-on-one linked to a service principal. In this case the application is API Management. The service principal is a single identity representing all users that want to call a target service via API Management. Each application has a clientId and a clientSecret that can be used to generate an access token with limited validity (of one hour). Question is how we can accomplish this in API Management. The answer is that you need to create an inbound policy. The policy is shown below:

<policies>
    <inbound>
        <base />
        <send-request ignore-error="true" timeout="20" response-variable-name="bearerToken" mode="new">
            <set-url>https://login.microsoftonline.com/[tenant-id]/oauth2/token</set-url>
            <set-method>POST</set-method>
            <set-header name="Content-Type" exists-action="override">
                <value>application/x-www-form-urlencoded</value>
            </set-header>
            <set-body>@{
              return "client_id=[client_id]&resource=[client_id]&client_secret=[client_secret]&grant_type=client_credentials";
          }</set-body>
        </send-request>
        <set-header name="Authorization" exists-action="override">
            <value>@("Bearer " + (String)((IResponse)context.Variables["bearerToken"]).Body.As<JObject>()["access_token"])</value>
        </set-header>
        <set-header name="Ocp-Apim-Subscription-Key" exists-action="delete" />
        <set-backend-service base-url="https://testcitocustomerservice.azurewebsites.net" />
    </inbound>
    …
</policies>

First you will have to send a AAD login request to Graph. Next you set the Authorization header with the access token and delete the APIM subscription key header. And there you go.

A useful set of more complicated API Management policies:

https://docs.microsoft.com/en-us/azure/api-management/policy-samples