asp.net core AzureADJwtBearer issuer validation failure

Turns out this issue surfaces if you configured azuread app registrations entry for your ClientId to support any organization or consumer, aka microsoft account, signins instead of just your organization or any organization. The fix was to use the AddJwtBearer() block of Startup.ConfigureServices() code shown below instead of the project template provided AddAzureADBearer() block.

public void ConfigureServices(IServiceCollection services)
{
    // if azuread app registrations entry for ClientId has "signInAudience": "AzureADMyOrg" or "AzureADMultipleOrgs" where "iss": "https://sts.windows.net/{TenantId}/"
    services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
        .AddAzureADBearer(options => //Configuration.Bind("AzureAd", options));
        {
            Configuration.Bind("AzureAd", options);
            Log.LogInformation($"the AddAzureADBearer options have been configured for ClientId = {options.ClientId}");
        });

    // if azuread app registrations entry for ClientId has "signInAudience": "AzureADandPersonalMicrosoftAccount" where "iss": "https://login.microsoftonline.com/{TenantId}/v2.0"
    services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; })
        .AddJwtBearer(options =>
        {
            var azureadoptions = new AzureADOptions(); Configuration.Bind("AzureAd", azureadoptions);
            options.Authority = $"{azureadoptions.Instance}{azureadoptions.TenantId}/v2";
            options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
            {
                ValidAudience = $"{azureadoptions.ClientId}",
                //ValidAudiences = new List<string> { $"{azureadoptions.ClientId}", $"api://{azureadoptions.ClientId}", $"https://myapp.azurewebsites.net/" },
                //ValidIssuer = $"https://sts.windows.net/{azureadoptions.TenantId}/" // for "signInAudience": "AzureADMyOrg" or "AzureADMultipleOrgs"
                ValidIssuer = $"{azureadoptions.Instance}{azureadoptions.TenantId}/v2.0" // for "signInAudience": "AzureADandPersonalMicrosoftAccount"
                //ValidIssuers = new List<string> { $"https://sts.windows.net/{azureadoptions.TenantId}/", $"{azureadoptions.Instance}{azureadoptions.TenantId}/v2.0" }                        
            };

            Log.LogInformation($"the AddJwtBearer options have been configured for ClientId = {azureadoptions.ClientId}");
        });
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Jacob

I was trying to authenticate existing token from uwp-app in web-api and I had a similar issue:

Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: Failed to validate the token.

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidIssuerException: IDX10205: Issuer validation failed. Issuer: 'https://spolujizda.b2clogin.com/4e8094c9-5058-454c-b201-ef61d7ae6619/v2.0/'. Did not match: validationParameters.ValidIssuer: 'null' or validationParameters.ValidIssuers: 'https://login.microsoftonline.com/4e8094c9-5058-454c-b201-ef61d7ae6619/v2.0/'.

at Microsoft.IdentityModel.Tokens.Validators.ValidateIssuer(String issuer, SecurityToken securityToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateIssuer(String issuer, JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateTokenPayload(JwtSecurityToken jwtToken, TokenValidationParameters validationParameters)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateToken(String token, TokenValidationParameters validationParameters, SecurityToken& validatedToken)
at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync()
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AzureADB2CJwtBearer was not authenticated. Failure message: IDX10205: Issuer validation failed. Issuer: 'https://spolujizda.b2clogin.com/4e8094c9-5058-454c-b201-ef61d7ae6619/v2.0/'. Did not match: validationParameters.ValidIssuer: 'null' or validationParameters.ValidIssuers: 'https://login.microsoftonline.com/4e8094c9-5058-454c-b201-ef61d7ae6619/v2.0/'. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "Values"}. Executing action Spolujizda.ApiServer.Controllers.ValuesController.Get (Spolujizda.ApiServer) Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'. Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes (). Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: AzureADB2CJwtBearer was challenged. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Spolujizda.ApiServer.Controllers.ValuesController.Get (Spolujizda.ApiServer) in 8.105ms Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 8950.4739ms 401 text/plain

But for me the fix was much simpler.

For Web API I had AzureAdB2C.Instance set to https://spolujizda.b2clogin.com/tfp/.

For an UWP app, I had been issuing token via https://login.microsoftonline.com/tfp/

That is why it resulted in this error. Because in the UWP app, the token was issued for login.microsoft... and in the Web API, it was trying to verify issuer as spolujizda.b2clogin...

First I tried to change address for issuing token for uwp-app, but that didn't work.

So secondly I just changed web-api's AzureAdB2C.Instance config to login.microsoft.... and it now works.