A web API that calls web APIs: Code configuration

After you've registered your web API, you can configure the code for the application.

The code that you use to configure your web API so that it calls downstream web APIs builds on top of the code that's used to protect a web API. For more information, see Protected web API: App configuration.

Microsoft.Identity.Web

Microsoft recommends that you use the Microsoft.Identity.Web NuGet package when developing an ASP.NET Core protected API calling downstream web APIs. See Protected web API: Code configuration | Microsoft.Identity.Web for a quick presentation of that library in the context of a web API.

Client secrets or client certificates

Given that your web API now calls a downstream web API, provide a client secret or client certificate in the appsettings.json file. You can also add a section that specifies:

  • The URL of the downstream web API
  • The scopes required for calling the API

In the following example, the GraphBeta section specifies these settings.

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "[Client_id-of-web-api-eg-2ec40e65-ba09-4853-bcde-bcb60029e596]",
    "TenantId": "common"

   // To call an API
   "ClientSecret": "[Copy the client secret added to the app from the Azure portal]",
   "ClientCertificates": [
  ]
 },
 "GraphBeta": {
    "BaseUrl": "https://graph.microsoft.com/beta",
    "Scopes": "user.read"
    }
}

Instead of a client secret, you can provide a client certificate. The following code snippet shows using a certificate stored in Azure Key Vault.

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "[Client_id-of-web-api-eg-2ec40e65-ba09-4853-bcde-bcb60029e596]",
    "TenantId": "common"

   // To call an API
   "ClientCertificates": [
      {
        "SourceType": "KeyVault",
        "KeyVaultUrl": "https://msidentitywebsamples.vault.azure.net",
        "KeyVaultCertificateName": "MicrosoftIdentitySamplesCert"
      }
   ]
  },
  "GraphBeta": {
    "BaseUrl": "https://graph.microsoft.com/beta",
    "Scopes": "user.read"
  }
}

Microsoft.Identity.Web provides several ways to describe certificates, both by configuration or by code. For details, see Microsoft.Identity.Web wiki - Using certificates on GitHub.

Startup.cs

Your web API will need to acquire a token for the downstream API. You specify it by adding the .EnableTokenAcquisitionToCallDownstreamApi() line after .AddMicrosoftIdentityWebApi(Configuration). This line exposes the ITokenAcquisition service, that you can use in your controller/pages actions. However, as you'll see in the next two bullet points, you can do even simpler. You'll also need to choose a token cache implementation, for example .AddInMemoryTokenCaches(), in Startup.cs:

using Microsoft.Identity.Web;

public class Startup
{
  // ...
  public void ConfigureServices(IServiceCollection services)
  {
  // ...
  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
            .EnableTokenAcquisitionToCallDownstreamApi()
            .AddInMemoryTokenCaches();
   // ...
  }
  // ...
}

If you don't want to acquire the token yourself, Microsoft.Identity.Web provides two mechanisms for calling a downstream web API from another API. The option you choose depends on whether you want to call Microsoft Graph or another API.

Option 1: Call Microsoft Graph

If you want to call Microsoft Graph, Microsoft.Identity.Web enables you to directly use the GraphServiceClient (exposed by the Microsoft Graph SDK) in your API actions. To expose Microsoft Graph:

  1. Add the Microsoft.Identity.Web.MicrosoftGraph NuGet package to your project.
  2. Add .AddMicrosoftGraph() after .EnableTokenAcquisitionToCallDownstreamApi() in the Startup.cs file. .AddMicrosoftGraph() has several overrides. Using the override that takes a configuration section as a parameter, the code becomes:
using Microsoft.Identity.Web;

public class Startup
{
  // ...
  public void ConfigureServices(IServiceCollection services)
  {
  // ...
  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
            .EnableTokenAcquisitionToCallDownstreamApi()
               .AddMicrosoftGraph(Configuration.GetSection("GraphBeta"))
            .AddInMemoryTokenCaches();
   // ...
  }
  // ...
}

Option 2: Call a downstream web API other than Microsoft Graph

To call a downstream API other than Microsoft Graph, Microsoft.Identity.Web provides .AddDownstreamWebApi(), which requests tokens and calls the downstream web API.

using Microsoft.Identity.Web;

public class Startup
{
  // ...
  public void ConfigureServices(IServiceCollection services)
  {
  // ...
  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddMicrosoftIdentityWebApi(Configuration, "AzureAd")
            .EnableTokenAcquisitionToCallDownstreamApi()
               .AddDownstreamWebApi("MyApi", Configuration.GetSection("GraphBeta"))
            .AddInMemoryTokenCaches();
   // ...
  }
  // ...
}

As with web apps, you can choose various token cache implementations. For details, see Microsoft identity web - Token cache serialization on GitHub.

The following image shows the various possibilities of Microsoft.Identity.Web and their impact on the Startup.cs file:

Block diagram showing service configuration options in startup dot C S for calling a web API and specifying a token cache implementation

Note

To fully understand the code examples here, be familiar with ASP.NET Core fundamentals, and in particular with dependency injection and options.

You can also see an example of OBO flow implementation in Node.js and Azure Functions.

Protocol

For more information about the OBO protocol, see the Microsoft identity platform and OAuth 2.0 On-Behalf-Of flow.

Next steps

Move on to the next article in this scenario, Acquire a token for the app.