How to do integration tests with AzureAD, if 2FA is enabled

Viewed 556

I am trying to set up integration tests in a project, where the application is secured by AzureAd (Microsoft.Identity.Web) and 2FA. Usually the user would log in to the application using a SPA, and would be greeted by the login popup or redirect. While testing controller endpoints, there is no SPA and we are not using the On-behalf-of flow, so I thought I could simply obtain a token the usual way for testing purposes:

[HttpPost]
public async Task<IActionResult> GetTokenAsync([FromBody] TokenRequest model)
{
    
    _client.BaseAddress = new Uri("https://login.microsoftonline.com/");
    var content = new FormUrlEncodedContent(new Dictionary<string, string>
    {
           /* ... */
    }

    var response = await _client.PostAsync($"{_options.TenantId}/oauth2/v2.0/token", content);
    var responseContent = await response.Content.ReadAsStringAsync();
    var token = JsonConvert.DeserializeObject<dynamic>(responseContent);

   return Ok(new TokenResponse { Token = token.id_token });
}

However, due to 2FA being enabled, I am receiving the following error:

{{
  "error": "invalid_grant",
  "error_description": "AADSTS50158: External security challenge not satisfied. User will be redirected to another page or authentication provider to satisfy additional authentication 
  "error_codes": [
    50158
  ],
  "timestamp": "2020-12-04 12:41:10Z",
  "trace_id": "xxxxxxxxxxxxxx",
  "correlation_id": "xxxxxxxxxxxxxxxxxxx",
  "error_uri": "https://login.microsoftonline.com/error?code=50158",
  "suberror": "basic_action",
  "claims": "{ /* ... */}"
}}

A more human-readable-friendly version: https://login.microsoftonline.com/error?code=50158

Here is the relevant part for the authentication configuration:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(o =>
    {
        o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
     .AddMicrosoftIdentityWebApi(this.Configuration)
          .EnableTokenAcquisitionToCallDownstreamApi()
             .AddMicrosoftGraph(this.Configuration.GetSection("DownstreamApi"))
             .AddInMemoryTokenCaches();

    /* ... */
}

Is there a way to satisfy the 2FA requirement during testing or circumvent it, while keeping the basic token mechanism intact?

Update To clear up any possible confusion: I'm targeting automated tests, without human intervention. I know, that I can use a mock authentication scheme with a custom WebApplicationFactory, but I'd go for a less fake approach if possible.

0 Answers
Related