Dave Smits
Dave Smits

Reputation: 1889

Integration tests for web api with Azure AD

I am working on a webapi webservice that is proteted by Azure Active Directory. The webservice cumminucates heavily with Office 365 (SharePoint / Yammer) based on the user that is signed in.

To test the web api endpoints I am writing an Console App that let me sign in with my AAD credentials and then calls the endpoints. It works, but looking for something to replace this way of testing the web api. Would be great if it’s more repeatable and that I don’t have to fill in my credentials each time. I was looking for a unit test project but can’t get the Azure AD sign in to work.

Any tips how to make this easier?

Upvotes: 5

Views: 3397

Answers (2)

Nan Yu
Nan Yu

Reputation: 27588

If you don't want to "fill in my credentials each time", one workaround is using the Resource Owner Password Credentials Grant flow. This flow is flexible to gain a token easily. In the Console App, you could directly use user account and password to get the access token for your protected web API . The code below is for your reference :

 static  void Main(string[] args)
    {

        test().Wait();
    }


    public static async Task test()
    {

        using (HttpClient client = new HttpClient())
        {
            var tokenEndpoint = @"https://login.windows.net/a703965c-e057-4bf6-bf74-1d7d82964996/oauth2/token";
            var accept = "application/json";

            client.DefaultRequestHeaders.Add("Accept", accept);
            string postBody = @"resource=https%3A%2F%2Fgraph.microsoft.com%2F  //here could be your own web api 
            &client_id=<client id>
            &grant_type=password
            &[email protected]
            &password=<password>
            &scope=openid";

            using (var response = await client.PostAsync(tokenEndpoint, new StringContent(postBody, Encoding.UTF8, "application/x-www-form-urlencoded")))
            {

                if (response.IsSuccessStatusCode)
                {
                    var jsonresult = JObject.Parse(await response.Content.ReadAsStringAsync());
                    var token = (string)jsonresult["access_token"];
                }
            }
        }
    }

But the problem is that flow will expose the username and password directly in the code, it brings potential attack risk as well and we will always avoid handling the user credential directly. So make sure you just use this flow for testing in a secure environment. You could refer to this article for more details.

Upvotes: 0

juunas
juunas

Reputation: 58898

The easiest way would be to define the test runner as an application in Azure AD and have it call the API with its own client id and secret.

To do that there are a few things you would need to do:

  1. Add appRoles to your API in its manifest in Azure AD. These are application permissions.
  2. Define your test runner, and have it require the necessary application permissions for your API.
  3. In your test runner you should now be able to get an access token with the client id and secret of the test runner, no user authentication required.

Some setup is needed for app permissions on the API side as well, authorization must also look at the role claims.

You can find an example for defining app permissions and also handling them here: http://www.dushyantgill.com/blog/2014/12/10/roles-based-access-control-in-cloud-applications-using-azure-ad/.

More on defining app permissions: https://stackoverflow.com/a/27852592/1658906.

More info on the application manifest in AAD: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-application-manifest.

EDIT: If you must make calls on behalf of the user in the API, then this of course won't work.

In that case, I would suggest creating a user account with the necessary access for the purpose of running the tests. It would be best not to hard-code its credentials, but store them elsewhere.

Upvotes: 2

Related Questions