[Bug] Protecting WebAPI does not work if one wants to use multiple bearer schemes, e.g. for AAD *and* B2C
See original GitHub issueUsing Microsoft Identity Web 0.2.3-preview protecting WebAPI with multiple Bearer schemes for different authorities.
Referring to this sample for multi bearer auth for Web Apis, it is impossible to use Microsoft.Identity.Web package to accomplish the required setup.
Steps to reproduce:
Create the following configuration file (only relevant sections are listed here for clarity):
{
"AzureAdB2C": {
"Instance": "https://snetga.b2clogin.com/",
"ClientId": "3422b1f4-8039-4023-9373-dbe747b40125",
"TenantId": "126bbbd5-e975-43a7-88ac-babc84279788",
"Domain": "snetga.onmicrosoft.com",
"SignUpSignInPolicyId": "B2C_1A_signup_signin_google"
},
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "126bbbd5-e975-43a7-88ac-babc84279788",
"ClientId": "3422b1f4-8039-4023-9373-dbe747b40125"
}
}
Then try to register both AzureAd and AzureAdB2C the following way:
services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAdB2C", "B2C");
services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd", "v2.0");
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireClaim("iss")
.AddAuthenticationSchemes("B2C", "v2.0")
.Build();
}
);
If the order is like here displayed - first registering AzureAdB2C and then registering AzureAd, you will get the following error when calling the API with valid token:
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'https://login.microsoftonline.com/snetga.onmicrosoft.com/B2C_1A_signup_signin_google/v2.0/.well-known/openid-configuration'.
---> System.IO.IOException: IDX20807: Unable to retrieve document from: 'https://login.microsoftonline.com/snetga.onmicrosoft.com/B2C_1A_signup_signin_google/v2.0/.well-known/openid-configuration'. HttpResponseMessage: 'StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
If changing the order - first register the AzureAd and then AzureAdB2C, e.g.:
services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd", "v2.0");
services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAdB2C", "B2C");
...
You will get success (200) calling the WebAPI with Azure AD B2C token, but 401 calling the API using v2.0 Token.
If you only use one of them (either AzureAd only or AzureAdB2C only) - it works.
Also, if you use the Microsoft.Identity.Web extensions to register only one of the providers (AzureAd OR AzureAdB2C), but use the Microsoft.AspNetCore.Authentication.XXX for the other provider, e.g.:
services.AddAuthentication()
.AddJwtBearer("v2.0", options =>
{
options.Authority = $"{Configuration["AzureAd:Instance"]}/{Configuration["AzureAd:TenantId"]}/v2.0";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = $"{Configuration["AzureAd:Instance"]}/{Configuration["AzureAd:TenantId"]}/v2.0",
ValidateAudience = true,
ValidAudience = Configuration["AzureAd:ClientId"],
ValidateLifetime = true
};
}); services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd", "v2.0");
services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAdB2C", "B2C");
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder()
.RequireClaim("iss")
.AddAuthenticationSchemes("B2C", "v2.0")
.Build();
}
);
Then the API accepts both AzureAd (v2.0) AND AzureAdB2C tokens.
After some very short search through the code, it seems this registration in WebApiAuthenticationBuilderExtensions might be causing the issue. Because of builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions<MicrosoftIdentityOptions>, MicrosoftIdentityOptionsValidation>())
, which is trying to add a singleton of MicrosoftIdentityOptions
- basically the second use of
AddMicrosoftWebApiAuthentication
will override any configuration settings that are different from the first registration. If I read correctly the documentation about TryAddEnumerable, it explains the behavior I am observing. But this is just a guess.
Expected behavior is that I am able to use AddMicrosoftWebApiAuthentication
multiple times with different configuration settings. There are a lot of valid scenarios where one would like to have this:
- Using Azure AD B2C for end-users and
client credentials
flow (which is exactly what this sample is about) - Having an application that authenticates users from different authorities - e.g. Commercial and China/GCC etc.
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (2 by maintainers)
Top GitHub Comments
Thanks @astaykov for investigation and a write-up.
This is also a duplicate of #429. I wrote a reply there.
The issue is with calling
builder.Services.Configure(configureMicrosoftIdentityOptions);
twice - with second time overwriting the first options.builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IValidateOptions<MicrosoftIdentityOptions>, MicrosoftIdentityOptionsValidation>());
I think is fine because it adds a singleton of a validator class, not options class.Included in 0.4.0-preview release