Skip to content

[Feature Request] Improved support for inheriting / customizing MicrosoftIdentity*AuthenticationHandler #1667

@MattKotsenas

Description

@MattKotsenas

Is your feature request related to a problem?

My specific scenario is likely niche, but I think the capability would be broadly applicable. For context, in my case I have a web API that makes protected downstream web API calls using the AddMicrosoftIdentityAppAuthenticationHandler route. I chose this method over IDownstreamApi because I have a set of HttpClient delegating handlers (like retry and backoff policies) that vary per HttpClient type.

My specific scenario is that my downstream API has a mix of authenticated and anonymous endpoints, and the AzureAd config provided to each instance of my web API may be different and may have been misconfigured by the user. That means that if the user provides a bad configuration, all downstream API calls will fail, even the anonymous ones, because there's no try...catch around token acquisition in MicrosoftIdentityAppAuthenticationMessageHandler.cs (see

var authResult = await TokenAcquisition.GetAuthenticationResultForAppAsync(
options.Scopes!,
options.AuthenticationScheme,
options.Tenant,
options.TokenAcquisitionOptions)
.ConfigureAwait(false);
) and thus failing to acquire a token is an uncaught exception.

Describe the workaround you have today

Today I work around this issue by copying the entirety of MicrosoftIdentityAppAuthenticationMessageHandler.cs into my library to add the try...catch, and then additionally I need to create a new override of AddMicrosoftIdentityAppAuthenticationHandler with the implementation copied so that I can add my "safe" handler as the HTTP message handler (see

).

Describe the solution you'd like

Depending on the level of support that makes sense for a scenario like this, I propose a tiered approach:

Tier 1: Register and retrieve the MicrosoftIdentity*AuthenticationHandler classes from DI

If instead of calling new directly on the handler classes in the extension methods, if the handlers were registered as dependencies and resolved from the ServiceCollection, I could inherit from the handler to do my custom work, which would eliminate the need to also duplicate the extension method. Bonus points if the authentication handlers gain an interface.

Tier 2: Move token acquisition into a virtual method in the handlers

In this tier, if we moved the token acquisition, i.e.:

var authResult = await TokenAcquisition.GetAuthenticationResultForAppAsync(
    options.Scopes!,
    options.AuthenticationScheme,
    options.Tenant,
    options.TokenAcquisitionOptions)
    .ConfigureAwait(false);

into a virtual method, then I could override just this method and add a try...catch, which would avoid needing to re-implement the rest of the class.

Describe alternatives you've considered

I added a section above with the workaround I have today. Alternatively, I could avoid the situation all together by splitting my downstream API into two different HttpClients, one for the authenticated endpoints and another for the anonymous endpoints, however in addition to having some negative performance characteristics (e.g. double TCP connections open to the same host), it also would lead to a suboptimal developer experience for my users, as the two sets of APIs aren't logically distinct, so it wouldn't be clear why some APIs use one client and some APIs use another.

Let me know if this request makes sense or not, and if you have any questions. Thanks!

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions