Integration Testing ASP.NET Core 2.1 with AzureAD Authentication

After setting up AzureAD with an ASP.NET Core 2.1 web application we found some of our integration tests started failing because they weren’t able to authenticate and view the app.  AddAzureAD defaults to prompting the user to login with their AzureAD credentials.  In the context of an integration test, we don’t usually have an interactive session.

Instead we can call AzureAD to get an access_token and use it as a bearer token header on the web app request to authenticate.  In this blog post, I’ll share the steps we took to enable these integration tests.

Setup AzureAD

First we created an integration test user and added it to the enterprise application in AzureAD:

image

Next we found the client/tenant ids for the application registration:

image

We also added a new client secret for the application registration:

image

Not sure if this was actually necessary or not but at one point we were seeing errors  about the resource not being set correctly and setting the identifierUris seemed to help.

image

Lastly we need the OAuth2 endpoint:

image

AddAzureAD and AddAzureADBearer in Startup

In the Startup.cs class we have to add and configure both AzureAD and AzureADBearer middleware.

public IServiceProvider ConfigureServices(IServiceCollection services)
{
  …

    services.AddAuthentication()
             .AddAzureAD(options => Configuration.Bind(“AzureAd”, options))
             .AddAzureADBearer(options => Configuration.Bind(“AzureAd”, options))
             ;
     services.AddAuthorization(options =>
     {
         var defaultPolicyBuilder = new AuthorizationPolicyBuilder(AzureADDefaults.BearerAuthenticationScheme, AzureADDefaults.AuthenticationScheme);
         defaultPolicyBuilder.RequireAuthenticatedUser();
         options.DefaultPolicy = defaultPolicyBuilder.Build();
     });

   …

    return services.BuildServiceProvider();
}

public void Configure(IApplicationBuilder app)
{
     app.UseHsts();

    app.UseCookiePolicy();
     app.UseAuthentication();
}

First we add the middleware then we configure a default authorization policy that attempts to authenticate via the bearer token then via the interactive username/password flow.

Testing

In the integration test we have to obtain an access token from AzureAD via a HTTP call and then pass the token to the secure web page as a bearer authentication header.

// Get access token from AzureAD
var tenantId = “[TODO-get tenantId from AzureAD]”;
var clientId = “[TODO-get clientId from AzureAD]”;
var form = new MultipartFormDataContent {
     {new StringContent(clientId), “client_id” },
     {new StringContent(“password”), “grant_type” },
     {new StringContent(“itest@acme.com”), “username” },
     {new StringContent(“[TODO-get password from AzureAD]”), “password” },
     {new StringContent(clientId), “resource” },
     {new StringContent(“openid”), “scope” },
     {new StringContent(“TODO-get secret from AzureAD”), “client_secret” },
};
var accessTokenResult = await this.Client.PostAsync($”https://login.microsoftonline.com/{tenantId}/oauth2/token”, form);
var accessToken = JObject.Parse(await accessTokenResult.Content.ReadAsStringAsync());
// Add access token to http client
this.Client.DefaultRequestHeaders.Add(“Authorization”, $”{accessToken[“token_type”]} {accessToken[“access_token”]}”);

You can also test the token retrieval in Postman if you prefer:

image

Note – By default, the access token is good for 60 minutes.  So if your authentication starts failing 60 min after you start you probably just need a new token.  Obviously in a test this probably won’t be a problem but while troubleshooting the workflow I hit this a couple of times and it took me a minute to figure out why it suddenly started failing.

And that’s it.  Hope someone else finds this useful.   If so or you have further questions/insights, please leave a comment below.

Happy Authenticating!

2 thoughts on “Integration Testing ASP.NET Core 2.1 with AzureAD Authentication”

Leave a Reply