次の方法で共有


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:

snip_20170317080739

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:

capture20170317103028578

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.

capture20170316102620455

Generate a client Secret by going to Azure Active Directory in the portal.  Search for the Client app:

capture20170316102812597

In Settings choose Keys:

capture20170316102831349

In Keys create a New Key (name it whatever you want) and Save:

capture20170316102907130

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.

capture20170316102930647

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:

capture20170317081758672

     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.