DEV Community

Cover image for Getting an Azure OAuth2 token with a Service Principal
tswiftma
tswiftma

Posted on

Getting an Azure OAuth2 token with a Service Principal

Trying to call the Azure REST APIs requires an OAuth2 token. This seems simple right? Ha ha unfortunately it's not.

There are a number of authentication methods to get a token using the AzureDefaultCredential class. Out of these "fall through" authentication options for local development I couldn't get the VisualStudioCredential option to work for me. This is the option to use your user credentials from Visual Studio. Seems like my company has some sort of difference between my local AD login and my Azure login. I was able to use the Azure CLI login for local development by logging in via command line but that doesn't help me when the tests are running in Azure Devops. Tests running in Azure Devops can also use the ManagedIdentityCredential to get a token but I hadn't gotten to that stage yet and I still needed to get an Azure OAuth2 token for local development.

So I chose to try using an Azure Service Principal because it can be used when developing locally. This requires setting up an App Registration in Azure AD. This Azure article is very good on how to setup the App Registration. Note that setting up the App Registration and assigning the Service Principal to your Application Role requires sufficient permissions. In my case I was a Subscription Owner.

Note that while setting up your App Registration you need to save the AzureSubscriptionId, ClientId, and ClientSecret(value) to use when requesting the OAuth2 token. Here's a method to get the token:

public async Task<string> GetAzureOAuthToken()
        {
            var requestUrl = AuthEndpoint + "/" + AzureSubscriptionId + "/oauth2/token";
            var client = CreateHttpClient();
            var values = new List<KeyValuePair<string, string>>();
            values.Add(new KeyValuePair<string, string>("client_id", ClientId));
            values.Add(new KeyValuePair<string, string>("client_secret", ClientSecret));
            values.Add(new KeyValuePair<string, string>("grant_type", GrantType));
            values.Add(new KeyValuePair<string, string>("resource", Resource));

            var requestBody = new FormUrlEncodedContent(values);
            var response = await client.PostAsync(requestUrl, requestBody);
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);

            string responseStr = await response.Content.ReadAsStringAsync();
            var content = JsonConvert.DeserializeObject<AzureADTokenResponse>(responseStr);

            return content.access_token;
        }
Enter fullscreen mode Exit fullscreen mode

Other parameters needed for the above code:

AuthEndpoint = "https://login.microsoftonline.com"
grant_type = "client_credentials"
resource = "https://management.core.windows.net"

The object AzureADTokenResponse in the code above is a C# class I created to deserialize the response from the request. Below is the code for this class.

public class AzureADTokenResponse
    {
        public string? token_type { get; set; }

        public string? expires_in { get; set; }

        public string? ext_expires_in { get; set; }

        public string? expires_on { get; set; }

        public string? not_before { get; set; }

        public string? resource { get; set; }

        public string? access_token { get; set; }
    }
Enter fullscreen mode Exit fullscreen mode

Now if you deserialize the response without errors than grabbing the token is easy:

return content.access_token;

Ok you've got your Azure OAuth2 token. Now you have to try and use it to call Azure REST APIs. I'll have another post on how to call Azure Logic App APIs soon :)

Top comments (0)