2
votes

Just a heads up: this question is not a duplicate of this one, so please do not mark this question as a duplicate.

I scaffolded a web api code that uses Azure Active Directory for authentication by Visual Studio 2019 and followed this document to configure the basic scaffolded application by using the configuration entries of my Azure AD B2C tenant.

The service configuration method looks like the following code snippet:

public void ConfigureServices(IServiceCollection services)
{
   Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
            services
                .AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
                .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

The configuration file contains the following AzureAd configuraiton entry where I masked the actual Ids:

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "testdirectoryv44.onmicrosoft.com",
    "TenantId": "1234abcdef......,
    "ClientId": "abcdef567....."   
  }

By running the userflow on the Azure portal, I obtain a token and am able to decode the token by https://jwt.ms which is great. However, I receive the following error message when calling this GET request: https://localhost:44362/api/values by POSTMAN while it is including the bearer token in the header when placing the request: (The error message is shown in the output pane of VS 2019)

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

Microsoft.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10501: Signature validation failed. Unable to match keys: kid: 'ABCDEF.........', token: '{"typ":"JWT","alg":"RS256","kid":"ABCDEF........."}.{"exp":1572358190,"nbf":1572354590,"ver":"1.0","iss":"https://testdirectoryv44.b2clogin.com/abcdef1234556/v2.0/","sub":"8799abcdef0000","aud":"89000abcdecf999,"nonce":"defaultNonce","iat":1572354590,"auth_time":1572354590,"idp_access_token":"BIGMASKEDVALUE","idp":"https://sts.windows.net/abcdef11234.../","name":"MyName","extension_InternalKey":"KEY400","given_name":"MyName","family_name":"MyFamily","extension_InternalUserId":"guest","tfp":"B2C_1_testdirectoryv44"}'. at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.ValidateSignature(String token, 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: AzureADJwtBearer was not authenticated. Failure message: IDX10501: Signature validation failed. Unable to match keys: kid: 'REMOVED AREAD'. Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'WebApplication5.Controllers.ValuesController.Get (WebApplication5)' Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "Get", controller = "Values"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.ActionResult1[System.Collections.Generic.IEnumerable1[System.String]] Get() on controller WebApplication5.Controllers.ValuesController (WebApplication5). 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: AzureADJwtBearer was challenged. Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action WebApplication5.Controllers.ValuesController.Get (WebApplication5) in 22.7988ms Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'WebApplication5.Controllers.ValuesController.Get (WebApplication5)' Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 792.0596ms 401

The Web api's code is as simple as the following code snippet which is scaffolded by Visual Studio 2019:

[Authorize]
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        // GET api/values
        [HttpGet]
        public ActionResult<IEnumerable<string>> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public ActionResult<string> Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public void Post([FromBody] string value)
        {
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }

        // PUT api/values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] string value)
        {
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }

        // DELETE api/values/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
            // For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
        }
    }

It's been a couple of days that I have been spending time on figuring out the root cause of this failure but no success so far. What point am I missing in the code or in Azure AD configuration causing this issue and why https://jwt.ms is able to decode the token successfully?

1

1 Answers

2
votes

Please note that Azure AD is different from Azure AD B2C.

The service configuration method

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme)
        .AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options));
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

appsettings.json

{
  "AzureAdB2C": {
    "Instance": "https://tony**test.b2clogin.com/tfp/",
    "ClientId": "5eaf724c-a61e-***-a217-44ffd45f9dfe",
    "Domain": "tony**test.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_testsignupin"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

You can follow this detailed tutorial.