Issue
I have an Angular app and a Web Api app (.Net 5.0) and I need a user to be authenticated with Azure AD B2C. So, when a user needs to reach some protected route he's going to be redirected to B2C log in page, authenticated and redirected back to the angular app. This Angular part works, no problem here.
Now, when the Angular app issues a request to a protected Web API (.Net 5), this web api should authorize the request. I've done this before in previous versions of .Net Core. But this is the new and shiny Microsoft Identity web. And it doesn't work.
The set up
appsettings.json for B2C
"AzureAdB2C": {
"TenantId": "[Tenant Guid]",
"Instance": "https://[tenant name].b2clogin.com/",
"ClientId": "[web api client Id]",
"Domain": "[tenant name].onmicrosoft.com",
"SignInPolicyId": "B2C_1_signin"
},
startup.cs - ConfigureServices()
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.NameClaimType = "name";
},
options => { Configuration.Bind("AzureAdB2C", options); });
// Creating policies that wraps the authorization requirements
services.AddAuthorization();
services.AddApplication();
services.AddInfrastructure(Configuration);
services.AddRouting(options => options.LowercaseUrls = true);
services.AddMemoryCache();
services.AddControllers().AddNewtonsoftJson();
startup.cs - Configure()
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
// endpoints.MapRazorPages();
endpoints.MapControllers();
});
With this set up all I get is very descriptive error:
System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'. ---> System.IO.IOException: IDX20807: Unable to retrieve document from: 'System.String'. HttpResponseMessage: 'System.Net.Http.HttpResponseMessage', HttpResponseMessage.Content: 'System.String'. at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.ConfigurationManager
1.GetConfigurationAsync(CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.ConfigurationManager
1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync() at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
But then I changed this "helper" sugar-configuration to the following:
services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; })
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = $"{Configuration["AzureAdB2C:Instance"]}/{Configuration["AzureAdB2C:TenantId"]}/{Configuration["AzureAdB2C:SignInPolicyId"]}/v2.0/";
jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
jwtOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed
};
});
And it works!
So is there a good docs on HOW MS Identity Web should be really configured? Why there is no precise description in the exception telling what is missing exactly?
Update
Thanks for the answer but this Identity Web implementation is really poor.
The reason for this exception is either SignUpSignInPolicyId
is undefined or misspelled! Microsoft team, you have to add it to your exception!
- Add meaningful exceptions
- If I don't want to use SignUpSignIn policy (I don't need any stranger go and register with my app), why it's not documented and supported?
- Do use optional logging which would tell the developer what's wrong/missing!
- use Builder pattern to create a configuration. Then it should be easier to identify which part of the config is missing in particular case.
Solution
Change SignInPolicyId in app settings.json to SignUpSignInPolicyId
Answered By - Jas Suri - MSFT
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.