Azure B2C token validation with dotnet core

Over the years Microsoft has released ceveral libraries for authentication. We had ADAL. It was ok at the time, but didn’t work with the Azure AD 2.0 authorization endpoints. After some time we got the MSAL library, but it took a while before it was usable. Now new libraries are on the horizon to make it easier for the developers. Well … the constant change of libraries doesn’t make it easier for developers.

Default validation

Validating a token on your API can be done with the package Microsoft.AspNetCore.Authentication.JwtBearer

In your Program.cs you can now add

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = "https://dprdemo.b2clogin.com/1dbfb883-0429-4cda-b627-bf004037fa5a/v2.0/";
        options.Audience = "7117e135-c388-49d7-903f-166e000a2fc4";
    });

The problem

If you use the above default configuration all tokens from Azure B2C will be seen as invalid. The problem is that the library uses the authority url to get the well-known openid-configuration to get additional values (like the public cert to verify if the token is really signed by configured authority). So the library will search for https://dprdemo.b2clogin.com/dprdemo.onmicrosoft.com/v2.0/.well-known/openid-configuration. That url doesn’t exist because Azure B2C always uses a policy parameter. The actual openid-configuration can be found on https://dprdemo.b2clogin.com/dprdemo.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_PORTAL_SUSI

When opening the openid-configuration url with a policy, you’ll see that the authorize and token endpoints also use the policy parameter, but the audience isn’t.

Azure B2C openid-configuration

The solution

The solution is quite simple. Just specify the MetadataAddress as well as the Authority

builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
    	options.MetadataAddress = "https://dprdemo.b2clogin.com/dprdemo.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_PORTAL_SUSI";
        options.Authority = "https://dprdemo.b2clogin.com/1dbfb883-0429-4cda-b627-bf004037fa5a/v2.0/";
        options.Audience = "7117e135-c388-49d7-903f-166e000a2fc4";
    });