Skip to content

DX proposal: AddMicrosoftIdentityMessageHandler extension for IHttpClientBuilder #3648

@jmprieur

Description

@jmprieur

Problem

Developers currently have to manually add boilerplate when configuring MicrosoftIdentityMessageHandler via AddHttpMessageHandler, including resolving IAuthorizationHeaderProvider from DI. This impedes discoverability, creates verbosity, and risks errors. Example today:

builder.Services.AddHttpClient("MyApiClient", client =>
{
    client.BaseAddress = new Uri("https://api.example.com");
    client.DefaultRequestHeaders.Add("Accept", "application/json");
    client.Timeout = TimeSpan.FromSeconds(30);
})
.AddHttpMessageHandler(sp =>
{
    var authProvider = sp.GetRequiredService<IAuthorizationHeaderProvider>();
    return new MicrosoftIdentityMessageHandler(
        authProvider,
        new MicrosoftIdentityMessageHandlerOptions
        {
            Scopes = new[] { "api://my-api-client-id/read" },
            RequestAppToken = false
        });
});

Proposal

Introduce AddMicrosoftIdentityMessageHandler extension method for IHttpClientBuilder in Microsoft.Identity.Web namespace. This should:

  • Provide 4 overloads:
    1. Accepts a non-null MicrosoftIdentityMessageHandlerOptions
    2. Accepts a configuration delegate Action<MicrosoftIdentityMessageHandlerOptions>
    3. Accepts no options (options may be set per request via extensions)
      4.. Accepts IConfigurationSection
  • Internally resolves IAuthorizationHeaderProvider from DI.
  • Binds directly to MicrosoftIdentityMessageHandlerOptions when configuration is needed (option 2).
  • All overloads return IHttpClientBuilder for chaining.
  • Respects Microsoft.Identity.Web library and pattern.

Signature Examples

public static IHttpClientBuilder AddMicrosoftIdentityMessageHandler(
    this IHttpClientBuilder builder,
    MicrosoftIdentityMessageHandlerOptions options)

public static IHttpClientBuilder AddMicrosoftIdentityMessageHandler(
    this IHttpClientBuilder builder,
    Action<MicrosoftIdentityMessageHandlerOptions> configureOptions)

public static IHttpClientBuilder AddMicrosoftIdentityMessageHandler(
    this IHttpClientBuilder builder,
    IConfigurationSection section) // Bind the options

public static IHttpClientBuilder AddMicrosoftIdentityMessageHandler(
    this IHttpClientBuilder builder)

Behavior

  • If options are null/missing, the per-request options mechanism stays available.
  • If options provided, they define handler behavior at creation time.
  • Leverage standard Microsoft.Extensions.DependencyInjection pattern.

Usage Example (Before/After)

Before:

builder.Services.AddHttpClient("MyApiClient")
  .AddHttpMessageHandler(sp =>
    new MicrosoftIdentityMessageHandler(
       sp. GetRequiredService<IAuthorizationHeaderProvider>(),
       new MicrosoftIdentityMessageHandlerOptions()));

After:

builder.Services.AddHttpClient("MyApiClient")
  .AddMicrosoftIdentityMessageHandler();

// Or with fluent configuration
builder. Services.AddHttpClient("MyApiClient")
  .AddMicrosoftIdentityMessageHandler(options => {
      options.Scopes = new[] { "api://my-api-client-id/read" };
      options.RequestAppToken = true;
  });

Doc Update Plan

  • Update custom-apis.md to reflect new extension.
  • Showcase all overloads, especially AddMicrosoftIdentityMessageHandler() with/without options.

Questions/Clarifications

  • Null/omitted options is always valid (not required, overridden per request)—approved.
  • Naming: Confirmed as AddMicrosoftIdentityMessageHandler.
  • Namespace: Confirmed as Microsoft.Identity.Web.
  • Configuration: Direct binding to MicrosoftIdentityMessageHandlerOptions.
  • Next step: Create issue per above spec.

*Executing now unless you object, Jean-Marc.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions