Accessing Azure App Services using Azure AD Bearer token
Overview
Here are some simplified instructions on how to setup and use Azure Active Directory authentication for a client Azure App Services application and code that will allow a client application to use a Bearer Token to access a different target app. In this scenario there are two web apps. The client app is the app that has code to call to the target app. Anyone can reach the client app without authentication and the client app then uses a Bearer token to access the target app which requires Active Directory Authentication. This assumes you have already created both apps in the Azure Portal
Review
Simply put, the OAuth Bearer Token simply identifies the app that is calling an Azure Active Directory registered application. The calling application requests a Token from AD by providing some information to include the Client Secret and Application ID of the app that will be calling the target app (the app that will use the token) as well as the Application ID of the application you wish to call. The client secret is the key that you want to protect and keep ‘secret’.
Walkthrough
Register the target app you are calling from the client app in Azure AD and get the Application ID. No client secret required.
My target app is https://jsandersapicall.azurewebsites.net. Simply click on the application in the Azure Portal and enable Azure AD authentication (express) and save.
Copy the Client ID (which is also know as the Application ID). After the app is updated go back into the Azure Active Authentication and click on the Advanced button. This will allow you to copy the Application ID:
Next Require the app to ‘Log in with Azure Active Directory’ and save. This will ensure only calls that are authenticated can get to this server:
Register the client app in Azure AD and get the Application ID, and generate a Client Secret Key
My client app is https://WebApplication420170316082455.azurewebsites.net (the one calling the protected target app). Simply click on the client app in the portal and enable Azure AD authentication (express) and save.
You now need to go to the application registered in Azure AD and get the Client ID and generate a Client Secret. Copy the Client ID and Client Secret of this client app to use later like you did in the previous step.
Generate a client Secret by going to Azure Active Directory in the portal. Search for the Client app:
In Settings choose Keys:
In Keys create a New Key (name it whatever you want) and Save:
Important. When you save you need to copy the Value for later as you cannot come back and get it. This is the Client Secret.
Note: You can always generate a new secret if you forget or lose it.
Create code to get a Bearer token from Azure AD and use this token to call the Target app
Now you simply need to use the values from above to request a token and then make a request to the target app from the client app using that token in the Authorization header.
Here is some sample code. First the ServicePrinciple class is used to build and get the token. I am using the latest ADAL library we provide (Microsoft.IdentityModel.Clients.ActiveDirectory ver 3.13.8:
public static class ServicePrincipal
{
/// <summary>
/// The variables below are standard Azure AD terms from our various samples
/// We set these in the Azure Portal for this app for security and to make it easy to change (you can reuse this code in other apps this way)
/// You can name each of these what you want as long as you keep all of this straight
/// </summary>
static string authority = ConfigurationManager.AppSettings["ida:Authority"]; // the AD Authority used for login. For example: https://login.microsoftonline.com/myadnamehere.onmicrosoft.com
static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; // the Application ID of this app. This is a guid you can get from the Advanced Settings of your Auth setup in the portal
static string clientSecret = ConfigurationManager.AppSettings["ida:ClientSecret"]; // the key you generate in Azure Active Directory for this application
static string resource = ConfigurationManager.AppSettings["ida:Resource"]; // the Application ID of the app you are going to call. This is a guid you can get from the Advanced Settings of your Auth setup for the targetapp in the portal
/// <summary>
/// wrapper that passes the above variables
/// </summary>
/// <returns></returns>
static public async Task<AuthenticationResult> GetS2SAccessTokenForProdMSAAsync()
{
return await GetS2SAccessToken(authority, resource, clientId, clientSecret);
}
static async Task<AuthenticationResult> GetS2SAccessToken(string authority, string resource, string clientId, string clientSecret)
{
var clientCredential = new ClientCredential(clientId, clientSecret);
AuthenticationContext context = new AuthenticationContext(authority, false);
AuthenticationResult authenticationResult = await context.AcquireTokenAsync(
resource, // the resource (app) we are going to access with the token
clientCredential); // the client credentials
return authenticationResult;
}
}
And then using this class my code to fetch data from the Target resource:
protected async void Page_Load(object sender, EventArgs e)
{
// Normally you would use a single Global HttpClient per MS guidance
// but for demo purposes... Just create one inline
HttpClient client = new HttpClient();
// This is an Aspx page so clearing anything already written in the buffer
Response.Clear();
try
{
// get the token
var token = await ServicePrincipal.GetS2SAccessTokenForProdMSAAsync();
// set the auth header with the aquired Bearer token
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer",token.AccessToken);
// make the call to the resource requiring auth!
var resp = await client.GetAsync("https://jsandersapicall.azurewebsites.net/");
// do something with the response
Response.Write(resp.StatusCode.ToString());
}
catch (Exception ex)
{
// important to log the exception if any because it will tell you what went wrong
Response.Write(ex.Message);
}
// write page out
Response.Flush();
}
Conclusion
This is a very compact sample that can be used as a checklist. It eliminated a lot of the information in our documentation here: Service principal authentication for API Apps in Azure App Service
Drop me a note if you found this useful!
Comments
- Anonymous
October 30, 2017
The code:static string resource = ConfigurationManager.AppSettings["ida:Resource"]; // the Application ID of the app you are going to call. This is a guid you can get from the Advanced Settings of your Auth setup for the targetapp in the portalis wrong. The resource should store "App ID URL" rather than "Application ID". - Anonymous
December 19, 2017
Simple and easy to follow. Very useful! - Anonymous
March 08, 2018
After getting the token, When I request the Azure Resource, I am getting the "Sign in to your Account" Page instead of the content. Is there anyway I can pass the Client credentials in the HTTP client?- Anonymous
March 20, 2018
Yes! Here is the article where you can see how to pass it:https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-overviewUsers who interact with your application through a web browser will have a cookie set so that they can remain authenticated as they browse your application. For other client types, such as mobile, a JSON web token (JWT), which should be presented in the X-ZUMO-AUTH header, will be issued to the client. The Mobile Apps client SDKs will handle this for you. Alternatively, an Azure Active Directory identity token or access token may be directly included in the Authorization header as a bearer token.
- Anonymous