Add token binding to MicrosoftIdentityMessageHandler#3743
Add token binding to MicrosoftIdentityMessageHandler#3743cpp11nullptr wants to merge 2 commits intomasterfrom
Conversation
…andler-with-token-binding
| } | ||
| catch (MicrosoftIdentityAuthenticationException) | ||
| { | ||
| throw; |
|
|
||
| /// <summary> | ||
| /// Sends an HTTP request with authentication header injection. | ||
| /// When token binding (mTLS PoP) is configured via <see cref="AuthorizationHeaderProviderOptions.ProtocolScheme"/>, |
There was a problem hiding this comment.
nit: use a remarks section for this, it's quite advanced scenario.
| } | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="MicrosoftIdentityMessageHandler"/> class with mTLS PoP token binding support. |
There was a problem hiding this comment.
nit: in public docs, let's mention the RFC 8705
| ], | ||
| "SendX5c": true | ||
| }, | ||
| "SecureApi": { |
There was a problem hiding this comment.
Please use the same formalism as the rest of the docs:
"DownstreamApis":
{
"SecureApi":{ }
}
jmprieur
left a comment
There was a problem hiding this comment.
There are a couple of things to improve:
- the RequiredService seems inconsistent with the option. Either use GetService or explain why required is fine. I think it's a breaking change, personally. you don't want to break Aspire!!
- Fragile code that can be improved
- +some questions/remarks
| client.BaseAddress = new Uri("https://secure-api.example.com"); | ||
| }) | ||
| .AddMicrosoftIdentityMessageHandler( | ||
| configuration.GetSection("SecureApi"), |
There was a problem hiding this comment.
would become DownstreamApis:SecureApi
| **appsettings.json:** | ||
| ```json | ||
| { | ||
| "SecureApi": { |
There was a problem hiding this comment.
Same thing: please have a DownstreamApis section in which the secure Api is to maintain consistency with the rest of the samples in the library.
| { | ||
| var headerProvider = sp.GetRequiredService<IAuthorizationHeaderProvider>(); | ||
| return new MicrosoftIdentityMessageHandler(headerProvider); | ||
| var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); |
There was a problem hiding this comment.
Isn't that a breaking change? Is the IHttpClientFactory always provided?
Shouln'd you use GetService and test if it's null? Given the other constructor if MicrosoftIdentityMessageHandler accepts null, it's strange to have a required service that could throw?
| { | ||
| var headerProvider = sp.GetRequiredService<IAuthorizationHeaderProvider>(); | ||
| return new MicrosoftIdentityMessageHandler(headerProvider, options); | ||
| var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); |
There was a problem hiding this comment.
Same question. Please explain why this is ok as writen.
|
|
||
| var headerProvider = sp.GetRequiredService<IAuthorizationHeaderProvider>(); | ||
| return new MicrosoftIdentityMessageHandler(headerProvider, options); | ||
| var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); |
|
|
||
| var headerProvider = sp.GetRequiredService<IAuthorizationHeaderProvider>(); | ||
| return new MicrosoftIdentityMessageHandler(headerProvider, options); | ||
| var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); |
| /// If <see langword="null"/>, each request must specify its own authentication options or an exception will be thrown. | ||
| /// </param> | ||
| /// <param name="mtlsHttpClientFactory"> | ||
| /// Optional factory for creating HTTP clients configured with mTLS client certificates for token binding |
There was a problem hiding this comment.
Optional ... so why do the Add use a Required service?
There is an inconsistency to resolve here?
| /// </exception> | ||
| /// <example> | ||
| /// <para>Usage with mTLS PoP token binding:</para> | ||
| /// <code> |
There was a problem hiding this comment.
Please remove this sample which has no place here. You don't want customers to instanciate MicrosoftIdentityMessageHandler directly but use the extension methods.
| } | ||
| catch (MicrosoftIdentityAuthenticationException) | ||
| { | ||
| throw; |
| private static DownstreamApiOptions CreateDownstreamApiOptionsFromMessageHandlerOptions( | ||
| MicrosoftIdentityMessageHandlerOptions options, IList<string> scopes) | ||
| { | ||
| return new DownstreamApiOptions |
There was a problem hiding this comment.
This is fragile.
Please add a copy constructor in MicrosoftIdentityMessageHandlerOptions leveraging the AuthorizationHeaderProviderOptions copy constructor and copying the scopes (maybe with cloning the collection)?
|
@tlupes - this is related to pure mTLS option, a review from you would be good. |
| string authHeader; | ||
|
|
||
| // Check if mTLS PoP token binding is requested | ||
| if (string.Equals(options.ProtocolScheme, TokenBindingProtocolScheme, StringComparison.OrdinalIgnoreCase) |
There was a problem hiding this comment.
This logic looks nearly identical to the logic for DownstreamApi; can we centralize this logic, or is the plan to use this message handler internally to DownstreamApi?
It looks very similar to how DownstreamApi works, which means it should be easy to transfer over. Centralizing the logic would make things easier. |
No description provided.