0

I am working on an ASP.NET Core 8 MVC application and using Azure AD B2C for authentication management. Below is my appsettings.json configuration:

"AzureAdB2C": {
  "Instance": "https://test555.b2clogin.com",
  "ClientId": "test555",
  "Domain": "test555.onmicrosoft.com",
  "SignedOutCallbackPath": "/signout/B2C_1_SignUpSignIn",
  "SignUpSignInPolicyId": "B2C_1_SignUpSignIn"
}

Here is how I have configured my Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C")
            .EnableTokenAcquisitionToCallDownstreamApi(new string[] { Configuration["ProsperityPilot:ProsperityPilotScope"] })
            .AddInMemoryTokenCaches();

    services.AddTransient<IClaimsTransformation, AddRolesClaimsTransformation>();

    services.AddControllersWithViews(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
        options.Filters.Add(new AuthorizeFilter(policy));
    }).AddMicrosoftIdentityUI();

    services.AddOptions();
    services.Configure<OpenIdConnectOptions>(Configuration.GetSection("AzureAdB2C"));
}

Up to this point, everything works fine. I can log in, sign up/sign out using Azure AD B2C, and make API calls obtaining the token like this:

private async Task PrepareAuthenticatedClient()
{
    var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { _todoListScope });
    Debug.WriteLine($"access token-{accessToken}");
    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}

However, I wanted to use IClaimsTransformation to add some claims when a user logs in. I wrote the following method to get a token, but I get the error:

AADSTS50049: Unknown or invalid instance.

 public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
 {
     
    ///...

     var token = await GetApplicationTokenAsync();

     // search Users by email
     var userEmail = principal.Identity.Name;
     var user = await _service.GetByEmailAsync(userEmail, token);

     ///...

     return clone;
 }

Here is my GetApplicationTokenAsync:

private async Task<string> GetApplicationTokenAsync()
{
    try
    {
        var clientId = _configuration["AzureAdB2C:ClientId"]; // ClientId of the WebApp
        var clientSecret = _configuration["AzureAdB2C:ClientSecret"]; // ClientId of the WebApp
        var scope = _configuration["MyApp:MyAppScope"]; // exposed API scope access_as_user
        var tenant = _configuration["AzureAdB2C:Domain"];
        var policy = _configuration["AzureAdB2C:SignUpSignInPolicyId"];

        var tenantName = "mytenant";
        var authority = $"https://{tenantName}.b2clogin.com/{tenantName}.onmicrosoft.com/{policy}/v2.0";


        var app = ConfidentialClientApplicationBuilder.Create(clientId)
            .WithClientSecret(clientSecret)
            .WithAuthority(new Uri(authority))
            .Build();

        var authResult = await app.AcquireTokenForClient(new[] { scope }).ExecuteAsync();
        return authResult.AccessToken;
    }
    catch (Exception ex)
    {
        throw;
    }
}

Questions:

  1. What is the correct way to configure the authority to obtain a token in an ASP.NET Core 8 MVC application using Azure AD B2C?
  2. Do I need to configure a separate DownstreamApi? If so, how should I correctly set it up?

REPO:

I have created this repository to facilitate clear visibility and analysis of the issue I am encountering, allowing for a deeper understanding of the error.


Azure ApiApp Config:


Azure WebApp Config:

2
  • Have you tried removing the /v2.0 from the authority? MSAL might add that.
    – juunas
    Commented Jun 28 at 17:54
  • Yes, I have tried
    – micex
    Commented Jun 29 at 8:23

1 Answer 1

0

Your configuration has

{
  "Domain": "test555.onmicrosoft.com"
}

and then it is used:

var tenant = _configuration["AzureAdB2C:Domain"];
var authority = $"https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{policy}/v2.0";

This means authority ends up being an invalid value:

https://test555.onmicrosoft.com.b2clogin.com/test555.onmicrosoft.com.onmicrosoft.com/B2C_1_SignUpSignIn/v2.0

Notice how the domain has duplicate text in it? You need a config value with just "test555", then it should work.

3
  • I'm getting the same error. At this point my question is The clientId, clientSecret are from my MVC application, the scope is from my API application, is this correct?
    – micex
    Commented Jun 29 at 11:33
  • Yeah, that should be correct.
    – juunas
    Commented Jun 29 at 11:59
  • I added my Azure AD configurations. And I tried your suggestions about var authority but I'm always getting the same error.
    – micex
    Commented Jul 2 at 13:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.