Securing Controllers in ASPNET Core with Azure Ad and Azure AD B2C

110 views Asked by At

We have an ASP NET Core We API (.NET8) running in an Azure App Service. We are using Microsoft Identity Web (2.16.1) and configure Startup like this

services
    .AddMicrosoftIdentityWebApiAuthentication(this.Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

services.AddAuthentication()
       .AddMicrosoftIdentityWebApi(this.Configuration, "AzureAdB2C", "B2CScheme", true);

The Controller Actions that are secured via Azure Ad are attibuted like this:

[HttpPost]
[Authorize(AuthenticationSchemes = "Bearer")]
[Route("requests")]
public async Task<IActionResult> RequestPush([Required] NotificationRequest notificationRequest)

The Controller actions that are secured with Azure Ad B2C are attributed like this:

[HttpDelete()]
[Authorize(AuthenticationSchemes = "B2CScheme")]
[Route("installations/{installationId}")]
public async Task<ActionResult> DeleteInstallation([Required][FromRoute] string installationId)

The controller actions work but we get unwanted confusing warnings in our AppInsights. For example when an Azure Ad B2C call is made we get

fail: Microsoft.IdentityModel.LoggingExtensions.IdentityLoggerAdapter[0]  IDX40001: Issuer: 'https://{TenantName}.b2clogin.com/{TenantId}/v2.0/', does not match any of the valid issuers provided for this application.

This is despite the call succeeding. Do we simply ignore the warnings

1

There are 1 answers

0
Sina Salam On

By reviewing the warning, it doesn't necessarily show or indicate there is a failure in authentication, but it is very important to address it for better clarity and to ensure that your application is configured correctly.

Another thing I observed was that there is a mismatch between the issuer configured in your application and the issuer from which the token is actually coming from. The issuer in the warning message is:

https://{TenantName}.b2clogin.com/{TenantId}/v2.0/

This does not match any of the valid issuers provided for the application.

The line of code or statement in your configuration that relates to this warning is the configuration of the Azure AD B2C authentication scheme:

services.AddAuthentication()
       .AddMicrosoftIdentityWebApi(this.Configuration, "AzureAdB2C", "B2CScheme", true);

In this configuration, you're specifying the authentication scheme ("B2CScheme") and associating it with the "AzureAdB2C" options. This is where the mismatch might be originating.

There are couple of things you can do though, aside from proper logging, testing, URL configuration update. I suggest you verify the issuer configurations.

In your ASP.NET Core application, you must have configure the issuer in your appsettings.json file or through environment variables. An example of how you should have done it:

{
  "AzureAdB2C": {
    "Instance": "https://{tenantName}.b2clogin.com/",
    "Domain": "{tenantName}.onmicrosoft.com",
    "ClientId": "{yourClientId}",
    "SignUpSignInPolicyId": "{yourSignUpSignInPolicyId}",
    "ResetPasswordPolicyId": "{yourResetPasswordPolicyId}",
    "EditProfilePolicyId": "{yourEditProfilePolicyId}"
  }
}

NOTE: In this configuration, "Instance" specifies the base URL of your B2C tenant.

So, verify issuer from Token because when a token might be issued its information is containing about the issuer. You can extract this information from the token to verify that it matches the issuer configured in your application. This is an example of how you can verify the issuer in your C# code:

using Microsoft.IdentityModel.Tokens;

public class TokenValidator
{
    private readonly string _expectedIssuer;

    public TokenValidator(IConfiguration configuration)
    {
        _expectedIssuer = configuration["AzureAdB2C:Instance"] + configuration["AzureAdB2C:Domain"] + "/{policy}/v2.0/";
    }

    public bool ValidateToken(string token)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var jwtToken = tokenHandler.ReadToken(token) as JwtSecurityToken;

        // Check if the issuer matches the expected issuer
        return jwtToken?.Issuer == _expectedIssuer;
    }
}

NOTE: _expectedIssuer is constructed based on the configuration in appsettings.json. You should replace "{policy}" with the appropriate policy name used in your B2C configurations. Then you would use TokenValidator to validate tokens in your application and ensure they are issued from the expected issuer.

By configuring the issuer in your application and verifying it against the issuer from tokens, you can be sure that they match and avoid the warning related to the issuer mismatch.