Azure App Services authentication to a foreign Azure Active Directory

Overview

You have some code you have created in your subscription and a customer wants to authenticate and use your application.  You are not connected to any other Azure Active Directory authentication.  This is bit of a contrived example but will give you some insight in to how Azure App Services authentication works.

Setup

Create a new Azure App Service Web in your Subscription.  Ensure it is working fine and deploy it (do not specify any authentication yet).  In my case the app is called ‘jsandersauthtoanotherazuread’ and the full URL is https://jsandersauthtoanotherazuread.azurewebsites.net/.

The name of the Azure AD tenant I want to do the auth for my app is jsandersrocks.onmicrosoft.com

The steps will then be:

  • Give the URL to the Azure AD tenant admin of jsandersrocks so the callback URL can be assigned and the app created
  • jsandersrocks Creates an Azure App Services in there tenant and give you the issuer, and application ID information
  • You use this to configure your app for authentication

Walkthrough

When the app authenticates it will have a generated callback url that is of the format:  https://jsandersauthtoanotherazuread.azurewebsites.net/.auth/login/aad/callback .  I need to give this callback URL to the Azure AD tenant owner.

Tenant Directory owner tasks:

The owner of the Tenant Directory creates a dummy app (with any name) and sets the login url to the callback url above.  The name will be the name that is shown when you login (see below).  Choose wisely! The Sign-on URL should be the call back url above:

capture20170609141746403

Then copies the generated app id to give to you from the properties of this new app:  512bf2b6-8a54-4c0b-9c8e-31350b16f606

capture20170609141840401

and give you the issuer Directory ID from the Properties tab of the Active Directory page: 3151db49-e251-45a6-9f58-2e90469383de.  You will use this to build the issuer ID.

capture20170609142035808

Your tasks:

Turn on App Service Authentication for your app:

capture20170609142306286

Configure the Azure Active Directory Authentication by clicking on the Advanced button and use the information the Tenant Directory owner gave you.  The app ID is used for the Client ID field and the Issuer Url is constructed from the Directory ID of the form:  https://sts.windows.net/DIRECTORYIDHERE

capture20170609142606120

Be sure to save your changes.

Test the auth to ensure it works - https://jsandersauthtoanotherazuread.azurewebsites.net/.auth/login/aad

capture20170609150131908capture20170609143626284

 

Errors

If you have trouble, the sign in page will tell you what the issue is.  For example, if the callback URL in the Tenant Directory was not correct (I initially used http instead of https) you get an error like this:

Sign In

Sorry, but we’re having trouble signing you in.

We received a bad request.

- Additional technical information:

Correlation ID: cfe9995f-bae7-4fe2-a7d8-24649b92493c

Timestamp: 2017-06-09 18:29:44Z

AADSTS50011: The reply address 'https://jsandersauthtoanotherazuread.azurewebsites.net/.auth/login/aad/callback' does not match the reply addresses configured for the application: '512bf2b6-8a54-4c0b-9c8e-31350b16f606'. More details: not specified

Additional Tasks

Now that I am logged in, I will add a login button (if not logged in) and display the logged in user information.  You can do this in global.asax, page level or in an on_authenticated method.

Login button

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="LoginButton.Default" %>

<!DOCTYPE html>

<html xmlns="https://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Button ID="Button1" runat="server" Text="Button" />
            <asp:Label ID="Label1" runat="server" Text="Not Logged In"></asp:Label>
        </div>
    </form>
</body>
</html>

code:

 public partial class Default : System.Web.UI.Page
   {
       protected void Page_Load(object sender, EventArgs e)
       {
           // if authenticated...
           if (this.User.Identity.IsAuthenticated)
           {

               Button1.Visible = false;
               Label1.Text = this.User.Identity.Name;
           }
           else {
               Button1.Visible = true;
               Label1.Text = "Not Authenticated";

           }
       }
           protected void Button1_Click(object sender, EventArgs e)
       {
           Response.Clear();
           Response.Redirect("/.auth/login/aad?post_login_redirect_url=/");
           Response.Flush();
       }
   }

Starting an in-private or incognito browser session, when I first hit the page I am not authenticated but when I hit the button I go through the auth sequence and display the email address:

capture20170609150603934

 

Conclusion

This just scratches the surface of what you can do.  The point is, Azure App Services authentication can take the heavy lifting of authentication off or your plate and you can do some powerful things.  This showed that as long as you configure the application with the correct issuer and app ID, it is able to validate and trust the token from a provider you do not have access to (with some cooperation from the sender).

If you want to do fancy things like authenticate to many different Azure AD tenants then you do need to utilize ADAL but that is beyond the scope of this post.

Drop me a note if you found this useful!

More references

The Bible of auth for me: https://www.microsoftpressstore.com/store/modern-authentication-with-azure-active-directory-for-9780735696945

Overview of auth scenarios: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios

App Roles: https://blogs.msdn.microsoft.com/waws/2017/03/09/azure-app-service-authentication-app-roles/

App Groups: https://blogs.msdn.microsoft.com/waws/2017/03/13/azure-app-service-authentication-aad-groups/