Getting Azure AD access token via REST Call

Part of Azure experiment, one of my colleagues started playing with Azure API Management last week. He was interested with what I introduced about the service, including API gateway, API publishing portal to readable policies to manipulate inbound request before back-end hit. He also loved to work with API call via REST because API is a flexible way of touching Azure resources through pure HTTP request, without installing any specific library.

After a few days, he came asking for help because he was unable to authorize request before calling Azure API Management REST API. I pointed him to this reference to make sure he understood that he needed to have authorization to Azure AD before working with any Azure resource and service. I also followed the guidance in the reference but then realized that this article was obsolete and seem to be wrong (in my opinion). Every time when I tried to send a GET  or POST  request with valid structure as well as authorization header, I always got a message telling me the authorization header format was invalid.

From what I tested, including new authentication updates in Azure AD, I personally believe the reference I just mentioned above is obsolete.

To support my colleague, I started looking into the issue and finally found a solution. In this article, I’d like to point out some notes, including references and sample code for you to get started with authenticating Azure AD via OAuth 2.0 with access token before working with any of Azure service’s REST API.

Why do you need to get access token?

First, we need to understand that Azure AD is the core identity & access management system of Microsoft Azure platform. Moreover, it is not the only identity system being used internally in Microsoft. It offers comprehensive identity solution for cloud services. One of the well-known cloud services which is consuming Azure AD is Office 365. If you have ever worked with Office 365 or SharePoint Online, you must know that setting up hybrid identity between your on-premises Active Directory and SharePoint Online require a trust from Azure AD.

When you make a call request to Azure REST API, it asks you to give something it trusts. One of so-called trusts  is access token. Access token is a form or security token that your application can use to access Azure resources (in this case Azure REST API) which are secured by authorization server (aka Azure AD endpoint). This is part of the entirely OAuth architecture which Azure provides. Access token is not the only way to get authorized to Azure AD. For other types of tokens, refer to this article.

Building authentication helper class

It is hard to find an up-to-date article over the Internet to cover getting access token programmatically. You can manually get the access token by browsing number of different URLs to copy an access token. That is a quick way before you can test other services (such as getting Azure Key Vault secret). As a developers, however, that is not something you want because access token is supposed to automatically generated and become an object before you can use it for further API operations.

I spent a few hours to vet through Google to see if anything I could use to get started. Fortunately, I found this article written by David Ebbo which is helpful to look at. In the article, David demonstrated the way to get access token using HttpClient . However, this article was written over 2 years ago. Moreover, the article just worked with Azure Service Management (Azure Classic model) endpoint which has been deprecated today. There are three parts in David’s sample code:

  • AuthenticationHelpers.cs: this class contains method to get access token
  • Program.cs: this class contains your function to perform REST API operation after having access token.
  • LoggingHandler.cs: this class contains function to log calls to web API which he used from this article.

First, you need to declare constant fields which you must not modify. The fields include the following things:

  • Management request URI
  • Authorization endpoint
  • Service Principal payload

Management request URI we need to use is for ARM (Azure Resource Management) endpoint. Previously the ASM model used  but it seems to work for ARM model. The new URI is I cannot seem to find a good resource to indicate the difference between the two (perhaps based on API version).

const string armUri = "";

For the authorization endpoint, the new one is{tenantId}/oauth2/token  which is the v.2 endpoint Microsoft give details here.

const string authEndpoint = "{0}/oauth2/token";

You also need to pass required parameter when calling to the URI. The parameter include resource  you need to get access token. In this case, it is Azure AD’s tenant ID. client_id  is your application ID you can get after registering it in Azure AD. client_secret  is given by Azure AD.

const string requestParam = "resource={0}&client_id={1}&grant_type=client_credentials&client_secret={2}";

Now the declaration looks like

const string armUri = "";
const string authEndpoint = "{0}/oauth2/token";
const string requestParam = "resource={0}&client_id={1}&grant_type=client_credentials&client_secret={2}";

For the rest of the code, I resused from David’s code. The code below formats the payload with three important parameters passed to. It then make a POST request using HttpPost  to get the access token.

public static async Task<string> AcquireTokenBySPN(string tenantId, string clientId, string clientSecret)
    var payload = String.Format(requestParam,

    var body = await HttpPost(tenantId, payload);
    return body.access_token;

This is not enough to fully make a request to work. The full HTTP POST request also needs to indicate Content-Type header which is application/x-www-form-urlencoded . That is why we need the following code snippet

var address = String.Format(authEndpoint, tenantId);
var content = new StringContent(payload, Encoding.UTF8, "application/x-www-form-urlencoded");

Below is the sample POST request to request an access token

// Sample POST to request access token
// Reference from Microsoft Guidance

POST /{tenant}/oauth2/v2.0/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded

&client_secret=JqQX2PNo9bpM0uEihUPzyrh    // NOTE: Only required for web apps

David’s code also adds more methods to trace the return to make sure the request is successful with status code “200”.

using (var response = await client.PostAsync(address, content))
    if (!response.IsSuccessStatusCode)
        Console.WriteLine("Status:  {0}", response.StatusCode);
        Console.WriteLine("Content: {0}", await response.Content.ReadAsStringAsync());
    return await response.Content.ReadAsAsync<dynamic>();

There are a couple of notes if you use the code in a fresh development environment:

Getting & Setting Azure environment variable

In previous section, you declared three fields tenantId , client_id  and client_secret  you might wonder where to get these things. This section, I’d like to walk you through steps to get these things via PowerShell.

First, you need to login to Azure AD using Login-AzureRmAccount . You are asked to give the credential when using this cmdlet. After, connect to your Azure AD. If you use Microsoft Account (aka MSA), go to read the below to make sure you don’t connect to Azure AD which your account is being managed.

There are two main cmdlets you can use to perform app registration in Azure AD.

  • New-AzureRmADApplication
  • New-AzureRmADServicePrincipal
  • New-AzureADApplicationPasswordCredential

Run the following PowerShell to create a new app and register it into Azure AD. The “term” app doesn’t really mean “app” in App Store or any app in your mobile phone. It represents a client which needs to be authorized in Azure AD.

#Reaching to correct Azure AD and Subscription
$subscriptionName = "Enterprise Subscription"
$tenantID = (Get-AzureRmSubscription -SubscriptionName "Enterprise Subscription").TenantId
$subscriptionId = (Get-AzureRmSubscription -SubscriptionName "Enterprise Subscription").Id

#Setting up new App
$appName = "WebApiAuth"
$homePage = ""
$idUri = "http://webapi01"
$secretName = "webkey01"

#Creating an azure app AD and register it to azure AD
$appAAD = New-AzureRmADApplication -DisplayName $appName -HomePage $homePage -IdentifierUris $idUri

#Creating a secret key
$secretValue = New-AzureADApplicationPasswordCredential -CustomKeyIdentifier $secretName -ObjectId $appAAD.ObjectId -EndDate (Get-Date).AddYears(2)

#Creating new Azure AD Service Principal
$servicePrincipalObj = New-AzureRmADServicePrincipal -ApplicationId $appAAD.ApplicationId

$role = New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName $azureAdApplication.ApplicationId.Guid

Write-Output "Subscription ID:" $subscriptionId | Add-Content D:\appinfo.txt
Write-Output "Tenant ID:" $tenantID | Add-Content D:\appinfo.txt
Write-Output "Application ID:" $appAAD.ApplicationId.Guid | Add-Content D:\appinfo.txt
Write-Output "Secret": $secretValue.Value | Add-Content D:\appinfo.txt

Now you need to grab client secret by open Azure AD Portal > App registrations. Choose the new app you just created and verify if output in PowerShell matches the info under app blade.

Until now, you have all the fields you need for the authenticationhelper class.

Storing Azure App configuration setting

Basically you can declare and assign value for tenantId , client_id  and client_secret  directly into the field. For example

string tenantId = "03987803-0fc0-4003-bz94-cdfhacfb2226";
string clientId = "a82eb468-e8zc-4733-89c9-c0li91a04ee1";
string clientSecret = "EU+l/XzwyDaE60mFNCzcn58m60VRwrrdOsyhnQaGVMc=";

However, this way is not a recommended best practice for security. Moreover, environment configuration should be controlled separately. Ideally, configuration should be stored in app.config  file. In David’s sample core, he used System.Configuration.ConfigurationManager  to manage external configuration. However, since we work with Azure, I’d like to introduce a new package named Windows.Azure.ConfigurationManager  which is used to load configuration.

Open App.config file and paste configuration information inside <configuration>  element.

   <add key="AzureSubscriptionId" value="e90d0136-d456-4212-a21b-b4790owf8a35" />
   <add key="AzureTenantId" value="03900103-0fc0-4103-bd94-hjkfbefb2226" />
   <add key="AzureClientId" value="0f1637ac-0693-4d9c-ba75-631b9258439f" />
   <add key="AzureClientSecret" value="BYpG1zgbu2LKtM9ZeYFzOPNIs3tFUloWhqS5/krZaZs=" />

At this time, I’ve completed the configuration setup for my team and ready for requesting access token with given value.

Making a sample request call to API Management 

This section is additional to testing Azure REST API after you get access token and complete your HTTP request body (including authorization header). Let’s declare and add more things to Program.cs . Below is my declaration for resource group name, location and my API Management service. Note that this is API Management service, not Azure REST API. My purpose is to use REST to retrieve information of my API Management service named s15digital.

const string resourceGroup = "sp16-rg";
const string location = "southeastasia";
const string apiName = "s15digital";

Now I need to load configuration from App.config file. Because I use WindowsAzure.ConfigurationManager assembly so I need to modify David’s sample code. Note that GetSetting()  method is used with bracket () instead of square bracket [].

static string Subscription = CloudConfigurationManager.GetSetting("AzureSubscriptionId");

You then need to load other configuration settings, initizlize a new HttpClient object and append its request body.

static async Task MainAsync()
    string tenantId = CloudConfigurationManager.GetSetting("AzureTenantId");
    string clientId = CloudConfigurationManager.GetSetting("AzureClientId");
    string clientSecret = CloudConfigurationManager.GetSetting("AzureClientSecret");

    string token = await AuthenticationHelpers.AcquireTokenBySPN(tenantId, clientId, clientSecret);

    using (var client = new HttpClient())
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
        client.BaseAddress = new Uri("");
        await getAPIinfo(client);

Do note that the full authorization header must have the structure (“Authorization”, “Bearer ” + token)

Now let’s define getAPIinfo  method which includes the full query string and HTTP GET method with GetAsync()

static async Task getAPIList(HttpClient client)
    JArray results = new JArray();
    string url = $"/subscriptions/{Subscription}/resourceGroups/{resourceGroup}/providers/Microsoft.ApiManagement/service/{apiName}/apis?api-version=2017-03-01";
    while (!String.IsNullOrEmpty(url))
        using (var response = await client.GetAsync(url))
            var json = await response.Content.ReadAsAsync<dynamic>();
            url = json.nextLink;

Not that the structure I declared in url  string. If you follow my article until now and run the program, you will always get the 403 (Forbidden) error.

Trace information output can be managed if you use LoggingHandler  function from David’s sample code. And also make sure you pass parameters when initializing HttpClient  object.

using (var client = new HttpClient(new LoggingHandler(new HttpClientHandler())))

Why do we get this error? This error doesn’t mean you have no access to Azure Management API. Instead, it tells you that you have no authorization to the target API Management service, namely s15digital. In this case, you need to give the service principal a role by using the following PowerShell (followed by the previous PowerShell to register an application).

$rgName = "sp16-rg"
$appId = $appAAD.ApplicationId
$apiName = "s15digital"
$scope = "/subscriptions/$subscriptionId/resourceGroups/$rgName/providers/Microsoft.ApiManagement/service/s15digital"

New-AzureRmRoleAssignment -ObjectId $appId  -Scope $scope -RoleDefinitionName Read

After running the script above, you can check via Access control (IAM) of the target API.

Let’s run the program again and verify the output. The JSON output is my API Management service I created in Azure API Management. By default, it contains default Echo API.

You can get access token and test with RESTClient extension in Firefox browser



Getting access token requires several steps to set up and get required information. The access token is as important as if it is compromised I could do something to retrieve your Azure service information.  This article just showed you how to initialize HttpClient  object to call Azure Management API via REST. I’d like to give my appreciation, thank and the credibility to David’s article and his sample code on GitHub.

Once again, if your application needs to have access to Azure resources before any operation you’d make,it needs to be authorized by Azure AD because identity & access of Azure resources are controlled and managed by Azure AD. Once you get access token, you can include it in authorization header when making a HTTP request again the target Azure API services. In my article, I demonstrated how to retrieve my Azure API Management service with GET method.

This entry was posted in Identity & Access Control and tagged , . Bookmark the permalink.

1 Response to Getting Azure AD access token via REST Call

  1. Pingback: Some fun with Azure Key Vault REST API and HttpClient – Part 1 | All about security on Microsoft Azure

Leave a Reply

Your email address will not be published.