Configuring the Azure Active Directory Application Proxy to Secure Access to On-Premise Web Applications
Giving external access to on-premise applications has typically required opening various "holes" in an organization's firewall. This practice has always made me shiver - even when using the web application proxy sever roles included with Windows Server OS's. Now, I am absolutely in love with the Azure Active Directory's (Azure AD) Application Proxy which is super-easy to configure, secure and, certainly for web apps, avoids ever having to punch holes in firewalls again.
In this article I describe how I configured an on-premise web application for external access using the Azure AD Application Proxy utility, in combination with various DNS zone rules both external and internal.
First off, I would strongly encourage you read up on Microsoft's introduction to the Application Proxy, along with how the Connectors work. With that, though, I will provide some snippets from those articles which rapidly communication the power of the Azure AD Application Proxy.
You can install connectors inside of your corporate network or on a virtual machine that runs in the cloud. Connectors can run within a demilitarized zone (DMZ), but it's not necessary because all traffic is outbound so your network stays secure.
It's easy to see the power in those two sentences alone. Figure 1, below, illustrates how this is achieved.
Below is a list of the services and on-premise resources I am working with and should be considered pre-requisites for this tutorial:
- I created a Virtual Machine running Windows Server 2012 R2 to host the Connector service. Note that 2012 R2 is the minimum OS compatible with the Azure AD Application Proxy
- This VM is on the corporate network, joined to the standard domain and is able to reach the domain controllers
- I have an existing Azure subscription and have Azure Active Directory synced with my on-premise Active Directory via Azure AD Connect
- I have a UPN suffix configured on my Active Directory Forest that matches my external domain's UPN. I.e. my internal AD domain suffix is contoso.local, but becuase my email address is firstname.lastname@example.org and I have added the contoso.com as an alternate suffix, I can authenticate with either. This is required for Azure AD Connect to work, as it will use this suffix to match my local AD user with my Office 365 user within my Azure AD tenet.
- The applications I want to expose and secure are served from various ports - not just 80 or 443.
- I have a wildcard SSL certificate on my primary organizational domain - for example *.contoso.com. This allows me to create multiple subdomains which makes it really easy for users to remember URLs to their business applications.
- I will assume that the wildcard SSL certificate is installed correctly per the application itself. This is not technically required for this, but is recommended.
I'm keeping this article simple and hopefully practical. Here are the requirements for what I'm setting out to achieve in the following steps.
- I have a third-party, on-premise web application that serves itself up on port 32907. I'm sure I could change this port by altering a bunch of config files, but I don't want to. It makes support with the third-party more difficult, and I don't want to spend time troubleshooting a config change
- The application uses forms-based authentication - i.e. not Windows.
- I need to make this easy for the users to access. This requires them not having to specifcy a port in the URL such as https://application.contoso.com:32907.
- It needs to be accessible in the same way internally and externally to the organziation - i.e. a seamless experience. I don't want an internal URL and a different external URL.
- It needs to be secure. My overarching rule is that all web applications are to be delivered via SSL encryption whether internally or externally delivered.
- No firewall rules are to be added/changed to accomodate this.
The remainder of this article details the steps required to complete the configuration following the requirements of these business rules.
1. Install the Azure AD Application Proxy Service
This is simple, and will turn the server you install this on into a "Connector" which will be registered with your organization's Azure AD. It's a simple install, and there is no GUI interface to work with afterwards.
1.1 Required Outbound Ports & URLs
Before starting, it is important to ensure that the server the Connector is going to run on meets the following connectivity requirements. Microsoft does a great job documenting these requirements here, but essentially all that is required is an outbound connection from the server your new Connector is running on to the internet on ports 80 and 443. Table 1, below, details what each is used for.
In addition, the following URLs need to be accessible from the server(s) the Connector(s) is running on:
1.2 Installing the Connector
To download and install the connector, log in to portal.azure.com and sign in with your credentials. From the left-hand menu select Azure Active Directory, and then Application Proxy from the popped-out blade. See Figure 2, below.
Again, you should read Microsoft's documentation on the connectors, but note that they do not need to be in a DMZ given all connections are outbound, and they need access to your on-premise Active Directory. I have mine installed on a domain-joined server which is what I would recommend.
Once it's installed, you will see it as a registered server within a "Connector Group". By this point, the Connector (the client) is authenticated with Azure (the server) via a client/server certificate to avoid any username/password combinations going back and forth.
1.3 A Note on Connector Groups...
Microsoft recommends having multiple connectors for redundancy, and the connector groups are an additional layer you can add to your architecture depending on your needs. Outside of redundancy, the Connector Groups play their biggest role in throughput and latency management, whereby applications can be assigned to specific connector groups allowing you to manage the applications' throughput requirements. At my organization's level, two connectors for redundancy is all I require.
2. Configuring an On-Premise Application
Now, for the fun part. We're going to expose an on-premise application to the internet, and overlay Azure AD authentication. I'm overlaying the authentication, because I don't like the way this particular application provides some non-critical information prior to authenticating.
2.1 Create an Internal DNS Rule
In your domain controller, create an 'A' record for the application within the forward lookup zone of the UPN suffix that matches your external domain and let this propogate
For the purposes of this article, let's say it's application.contoso.com. This would mean that to internally reach our application on port 32907, we would need to browse to https://application.contoso.com:32907.
2.2 Create an App Registration in Azure AD
Go to portal.azure.com and starting at the left-hand menu, navigate to Azure Active Directory -> App Registrations and select + New application registration.
On the Create pop-out blade, enter the Name of the application, leave the Application type as Web app / API and then enter the Sign-on URL that matches the DNS A record you created earlier - i.e. https://application.contoso.com. See Figure 3, below.
You should see something similar to Figure 4, below.
You have effectively created a new Enterprise Application in your Azure AD tenet. You will see Enterpise Applications as a menu item within the Azure Active Directory meny.
2.3 Configure the Application Proxy Properties for the New Enterprise Application
Navigate back to Azure Active Directory -> Enterprise Applications and select the Application application that you created in the previous step. Note that you may need to search for the application in order to find it.
Navigate to Application Proxy and do the following:
- In the Internal Url field, enter the internal URL that you created in step 2.1, above, including the port number (32907). In this case, https://application.contoso.com:32907/. The Azure App Proxy is going to redirect requests coming in on port 443 to port 32907, and will append any query strings in the request header.
- In the External Url section, you need to make sure it matches what we created in step 2.1. Note that is doesn't have to, I'm doing it for simplicity.
- In the Pre Authentication section, leave it set to Azure Active Directory. This is becuase I want the Azure pre-auth, but setting it to pass-through will avoid any pre authentication at all.
- Depending on how you have configured your Connector Groups (see Section 1.3 above), select the Connector Group you want to assign to the application. I have left it as default.
- I left all Additional Settings as the defaults, but these may require changing depending on your application's needs.
Save the settings and you should be left with something like Figure 5, below.
The final step here is to upload your SSL certificate and ensure it's selected. Click on the Certificate panel to either select or upload your certificate. To upload it, you'll need a .pfx version of your certificate with (hopefully) a password. See Figure 6, below.
Note that the certificate needs match the domain you selected in the External URL above.
2.4 Add CNAME Record to External DNS Zone
You'll notice at the bottom of the Application proxy blade that it instructs you to create a specific CNAME record in your external DNS zone. This will redirect requests made to your friendly external URL to the Application Proxy where the configuration you just set up will take care of it from there. See Figure 6 for an example of this.
2.5 Configure the Application Properties
Now that the heavy lifting is done, we have some final settings to configure.
Navigate to the Properties blade of the application. We'll run through each of the properties below:
- The Name field is already filled out, but feel free to change it.
- The Homepage Url field cannot be changed here.
- If you like ,you can upload a Logo. I always do this. It adds a touch of flair and illustrates organization in the environment as a whole, and makes things nice to work with.
- Note the User access Url. Users can access all Azure AD enabled applications by visiting https://myapps.microsoft.com and signing in. This field provides you with the specific URL for this particular application, but it's not strictly required for anything.
- The Application Id and Object ID become important in specific cases. For instance, configuring a Dynamics NAV service tier to authenticate using Azure AD requires a specific URL be constructed including the application Id. For the purposes of this demonstration, we won't be making use of these values.
- User assignment required means whether you want to control access to the application to specific users or groups within your Azure AD tenet. In my case, I am choosing Yes. Below I will demonstrate how to assign users.
- Visible to users allows you to choose whether the application displays in the users' https://myapps.microsoft.com portal.
Figure 7, below, illustrates how this might look to you, and the settings that I have used for the purposes of this article.
2.6 Add Authorised Users to the Application
Finally, because we've set User access required to Yes in the Enteprise Application Properties (see Section 2.5, above), we will need to assign the users that we want to have access to the application.
To do this, navigate to Users and groups and click + Add user, then work through the prompts to find and add the users you want to add. Note that only these users will see the application in their MyApps portal (and only because we set Visible to users to Yes above.
Now all that's left to do is to test the application. Use your cell phone to create a hotspot to connect from external locations and test everything out.
In this article you have hopefully learned how to use the Azure AD Application Proxy service to serve up on-premise web applications externally, with an added layer of security via Azure AD authentication. If you have any questions at all please just leave a comment and I'll get back to you as soon as I can.