Securing and restricting access to Office 365 with custom AD FS claimrules

We’ve been working hard with one of our clients to secure access to Office 365 workloads such as Exchange Online. In this specific article we will share our experience how to restrict access to Exchange Online to specific networks and for specific protocols.

This client was using MobileIron for securing mobile devices and wanted to integrate this MDM solution with Office 365.

The tricky part of securing access to Exchange Online with MobileIron is the fact that MobileIron Sentry servers require dedicated IP adresses to Exchange. As you can imagine, the always changing Office 365 Cloud – with all it’s IP Addresses – will make it hard to follow this requirement. Thus we had to use a different technology, outside of MobileIron for restricting access to Office 365.

We chose to implement custom claimrules in AD FS, the enviroment we built this solution for on was an AD FS 2016 farm. In this new version of AD FS there are several changes on how to create custom claim rule, by default AD FS 2016 uses Access Control Policies and with these policies it was not possible to create such custom claim rules. So before we begin, we will start with explaining how torevert back to making use of the old school way of creating claim rules

  1. Log on the one of your AD FS servers
  2. Fire up PowerShell and run these commands
    1. $ADFSRpt = Get-AdfsRelyingPartyTrust -Name “Microsoft Office 365 Identity Platform”
    2. Set-AdfsRelyingPartyTrust -TargetRelyingParty $ADFSRpt -AccessControlPolicyName $null
    3. Set-AdfsRelyingPartyTrust -TargetRelyingParty $ADFSRpt -IssuanceAuthorizationRules $null
    4. Set-AdfsRelyingPartyTrust -TargetRelyingParty $ADFSRpt -IssuanceAuthorizationRules ‘@RuleName = “TEMP RULE” exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”%5D) => issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”,Value = “true”);’
  3. Open the AD FS Management Console
  4. Navigate to “Relying Party Trusts” and select the Office 365 relying party trust.
  5. Click on “Edit Access Control Policy” in the right menu to find the old menu for configuring “Issuance Authorization Rules”
  6. Remove the “TEMP RULE’ but DO NOT close the window
    Issuance AuthorizationRules

Now here the cool part comes, which is actually restricting specific traffic and protocols to specific networks, for instance SMTP or EWS traffic.

Restricting ActiveSync Protocol

  1. Add new rule
  2. Insert the following custom claim
  3. This claim contains the dedicated IP Adress from the MobileIron Sentry server from which we do accept ActiveSync traffic to Office 365. All other IP adressess are denied.

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”%5D)
&& exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application”, Value == “Microsoft.Exchange.ActiveSync”])
&& NOT exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip”, Value =~ “\b82\.125\.45\.23\b”])
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”, Value = “true”);

Restricting IMAP Protocol

  1. Add new rule
  2. Insert the following custom claim
  3. This claim contains the dedicated IP Adress from the MobileIron Sentry server from which we do accept IMAP traffic to Office 365. All other IP adressess are denied.

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”%5D)
&& exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application”, Value == “Microsoft.Exchange.Imap”])
&& NOT exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip”, Value =~ “\b82\.125\.45\.23\b”])
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”, Value = “true”);

Restricting SMTP Protocol

  1. Add new rule
  2. Insert the following custom claim
  3. This claim contains the dedicated IP Adress from the MobileIron Sentry server from which we do accept SMTP traffic to Office 365. All other IP adressess are denied.

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”%5D)
&& exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application”, Value == “Microsoft.Exchange.SMTP”])
&& NOT exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip”, Value =~ “\b82\.125\.45\.23\b”])
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”, Value = “true”);

Restricting POP Protocol

  1. Add new rule
  2. Insert the following custom claim
  3. This claim contains the dedicated IP Adress from the MobileIron Sentry server from which we do accept POP traffic to Office 365. All other IP adressess are denied.

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”%5D)
&& exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application”, Value == “Microsoft.Exchange.Pop”])
&& NOT exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip”, Value =~ “\b82\.125\.45\.23\b”])
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”, Value = “true”);

Restricting EWS Protocol

  1. Add new rule
  2. Insert the following custom claim
  3. This claim contains the public IP Adress range from the on-premises network from which we do accept EWS traffic to Office 365. All other IP adressess are denied. For this claimrule we also require the hybrid Exchange servers to send EWS traffic to Office 365 for delivering rich-coexistence functionality to all users. This example allows traffic from the range of 82.125.45.1 – 82.125.45.14.

exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-proxy”%5D
&& exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-application”, Value == “Microsoft.Exchange.SMTP”])
&& NOT exists([Type == “http://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-forwarded-client-ip”, Value =~ “\b82\.125\.45\.([1-9]|1[0-4])\b”])
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/deny”, Value = “true”);

Now the current rule configuration should look like this:

Issuance AuthorizationRules2

The last rule to be added is a standard rule “Permit Access to All Users” and be sure this rule is at the bottom of the list with the “Permit” action.

Now all desired Exchange protocols are restricted to anywhere besides the MobileIron Sentry server or either the on-premises network range for some EWS traffic to support free/busy and other hybrid traffic to Exchange on-premises. However the new Outlook for iOS and Android app doesn’t use these traditional Exchange protocols. This new nifty app uses the Graph API for fetching e-mail and other resources.

To restrict access from unknown clients to Exchang Online with the use of the Outlook for iOS or Android app we chose to make use of Conditional Access for Azure Active Directory. And restrict access from any other networks then the public IP address from the Sentry server. To make use of this feature an Azure Active Directory Premium P1 license is required though!

A last fun fact to end this blogpost with is the fact that the documentation provided by Microsoft on TechNet is incorrect. The technet documentation on Limiting Access to Office 365 Services Based on the Location of the Client lists an incorrect HTTP Header for Imap traffic Microsoft.Exchange.PopImap. After a lot of searching and troubleshooting with Microsoft our eye fell on a little detail in the ADFS trace logs which caused the initial claimrule for Imap to fail. We found out that HTTP Headers for Imap traffic use the value Microsoft.Exchange.Imap and not Microsoft.Exchange.PopImap as described in the article!! Below here you can find the event registered in the AD FS Trace Logs from a IMAP client:

Following request context headers present:

X-MS-Client-Application: Microsoft.Exchange.Imap
X-MS-Client-User-Agent: –
client-request-id: 6338b8c2-c283-4c93-2c00-0080000000c6
X-MS-Endpoint-Absolute-Path: /adfs/services/trust/2005/usernamemixed
X-MS-Forwarded-Client-IP: xxx.xxx.xxx.xxx, xxx.xxx.xxx.xxx
X-MS-Proxy: WAP
X-MS-ADFS-Proxy-Client-IP: xxx.xxx.xxx.xxx

Big shout-out to my fellow friend and teammember Kevin Raap for working together on the claimrules, and finding out the flaw in Microsoft Technet documentation.

One thought on “Securing and restricting access to Office 365 with custom AD FS claimrules

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s