Porting from .NET Core 3 to .NET Core 5 Authentication, I am required to replace services.AddSignIn (deprecated) by services.AddMicrosoftIdentityWebAppAuthentication or other related MicrosoftIdentity extensions. I need to support both OpenId user login and Bearer token policies for API access. These both worked with services.AddSignIn but I can't get this combination working with the new MicrosftIdentity extensions.
I have a .Net Core Blazor Server with OpenId login to Azure AD B2C. This works fine as:
services.AddMicrosoftIdentityWebAppAuthentication(
configuration,
aadB2CConfigName,
OpenIdConnectDefaults.AuthenticationScheme,
CookieAuthenticationDefaults.AuthenticationScheme,
true);
But when I add the Bearer Token handling directly after it, as follows, then it overrides the OpenId, so only the Bearer API works (and vice versa):
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(
options =>
{
configuration.Bind("AzureAd", options);
options.ForwardDefaultSelector = ctx =>
ctx.Request.Path.StartsWithSegments("/api", System.StringComparison.InvariantCulture)
? JwtBearerDefaults.AuthenticationScheme
: null;
options.Authority = configuration["AzureAd:Authority"];
options.TokenValidationParameters.NameClaimType = "name";
options.TokenValidationParameters.RoleClaimType = "roles";
}, options =>
{
configuration.Bind(aadB2CConfigName, options);
});
For completeness, followed by (worked fine in .net core 3)
services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
services.AddAuthorization(options =>
{
options.AddPolicy("Tst1AuthPolicy", policy => policy.RequireRole("Tst1AppRole"));
options.AddPolicy("Tst2AuthPolicy", policy => policy.RequireRole("Tst2AppRole"));
});
The chaining of extension methods does not seem to work as it did with AddSignIn. How do I make both of these work again in parallel in the new .net core 5 context? i.e. OpenId as default, and Bearer Tokens when the WebApi (/api) is hit.
Got it working as follows. I don't feel totally confident that this is the intended/best usage here, but it works:
Replace the above "null" as follows with the alternate login scheme, which is the oreo cookie scheme in our case:
options.ForwardDefaultSelector = ctx =>
ctx.Request.Path.StartsWithSegments("/api", System.StringComparison.InvariantCulture)
? JwtBearerDefaults.AuthenticationScheme
: CookieAuthenticationDefaults.AuthenticationScheme;
This will probably mean that, instead of a HTTP-Status error, I get a HTML login page if the Bearer Token fails, so there must be a better way ... if anybody cares to chime in.