About the Author: ProofID




If you have deployed PingFederate, you can control access to cloud applications through a CIDR adapter selector. Most Office 365 Outlook integrations use active profiles, which is technically accomplished via WS-Trust. Since CIDR adapter selectors are not applicable to WS-Trust connections, a CIDR adapter selector would never get invoked. This blog article will describe how an equivalent architecture can be accomplished for WS-Trust to implement a CIDR selector for Office 365.

First, some background on how Office 365 integrates with PingFederate

When the Outlook client is configured to use Office 365 Exchange Online, the user will be prompted for login credentials upon startup. The Outlook client uses neither Windows Authentication nor the enterprise SSO, as you would expect. The Outlook client uses a local workstation “Credential Store” to store the account and password. The local credentials are securely transmitted to Exchange Online (specifically a single Exchange Online server within the overall Exchange Online cluster). Exchange Online then validates the credentials.

When federation is configured, Exchange Online validates the credentials by sending a Request Security Token (RST) to PingFederate containing a username token (UAT) with the username/password that Outlook passed to Exchange Online. PingFederate validates the credentials against the configured data store and assuming the credentials are valid, responds with a Request Security Token Response (RSTR) containing a signed SAML assertion.

How to restrict Office 365 via PingFederate federation?

Because the RST comes from Exchange Online, PingFederate can be configured to make use of the RST’s X-MS* headers to make issuance decisions. The RST X-MS* headers are described in the Microsoft article Limiting Access to Office 365 Services Based on the Location of the Client. These are the same headers that ADFS would leverage for policy enforcement. When using PingFederate, an SP Connection for Office 365 could be restricted by using “Issuance Criteria” for the Passive (e.g. WS-Federation) and Active (e.g. WS-Trust) portions of the configuration. Since Outlook is considered an active profile, you will need to configure the WS-Trust Issuance Criteria via the PingFederate administration console.

How do I configure PingFederate for Office 365 Exchange Online IP Filtering?

Office 365 has a number of attributes that identify the location and type of a client / client request. Using this information we can build PingFederate Issuance Criteria rules to enable specific security policies, for example no Outlook from outside the network. The attributes we have available to form our logic are:

  • X-MS-Forwarded-Client-IP
  • X-MS-Client-Application
  • X-MS-Client-User-Agent
  • X-MS-Endpoint-Absolute-path

To implement a policy that restricts access to only users within the corporate network (e.g. restrict all external internet users), we will utilize a PingFederate OGNL expression within the Issuance Criteria for the WS-Trust portion of the Office 365 SP Connection. Within PingFederate, OGNL Expressions will need to be enabled (See the PingFederate Administrator Guide Appendix H). For this use case, we will specifically inspect the HTTP Header field X-MS-Forwarded-Client-IP. Below are sample OGNL expressions to implement this use case.

Debug output of the HTTP header names

#log = @org.apache.commons.logging.LogFactory@getLog("com.pingidentity.ognl.logger"),
#log.debug("---[ Office365 Authorization Rule Debugger ]---"),
#objReq = #this.get("context.HttpRequest").getObjectValue(),
#headers = #objReq.getHeaderNames(),
#hdr = #this,
#log.debug(#hdr.toString() + " = " + #objReq.getHeader(#hdr.toString()))
#result = true

Restrict only Outlook to a range of IP addresses:

#permitRequest = false,
#objReq = #this.get("context.HttpRequest").getObjectValue(),
#msApplication = #objReq.getHeader("X-MS-Client-Application") != null ? #objReq.getHeader("X-MS-Client-Application") : "",
#clientIPList = #objReq.getHeader("X-MS-Forwarded-Client-IP") != null ? #objReq.getHeader("X-MS-Forwarded-Client-IP") : ",,",
#clientIP = #clientIPList.toString().split(',')[0],
#subnet1 = new org.apache.commons.net.util.SubnetUtils(""),
#subnet2 = new org.apache.commons.net.util.SubnetUtils(""),
#permitRequest = (#subnet1.getInfo().isInRange(#clientIP) || #subnet2.getInfo().isInRange(#clientIP)) && (#msApplication == "Microsoft.Exchange.RPC") ? true : #permitRequest,
#log = @org.apache.commons.logging.LogFactory@getLog("com.pingidentity.ognl.logger"),
#permitRequest == false ? #log.debug("Office 365 Active Client Access from " + #clientIP + " denied") : #log.debug("Office 365 Active Client Access from " + #clientIP + " accepted"),
#result = #permitRequest

As you can see these expressions for OGNL are fairly complex. If you read my blog posting on how to create a custom java library for PingFederate, you could create a library that would be called from a OGNL expression. The library would implement the logic to evaluate the RST X-MS* headers. Once complete, you may want to check out developer best practices for easily testing Office 365.

Are there any issues that I should be aware about?

There is an issue that sporadically occurs when restricting access to Outlook, regardless of the technology used for federation, for example ADFS, PingFederate, or some other federation server technology.

A problem can occur related to how each Exchange Online server establishes sessions with each user’s Outlook client. When a session is created, the session is only with a single Exchange Online server in Office 365 and not with any other server in the Exchange Online cluster. If Outlook connects to a new Exchange Online Server (the Office 365 infrastructure decides which Exchange Online server used), a new RST will be sent to the federation server (e.g. ADFS, PingFederate, etc.) a new RSTR issued, as well as a new session object will be managed on the new Exchange Online Server. As long as messages are communicating to the same Exchange Online Server, the session will be maintained and re-authentication will not occur. If the Outlook client were to be closed and reopened and hits the same Exchange Online Server, re-authentication may not occur based on when the session expires. However, when a user logs in via the corporate network and then leaves the network and goes to a public network, the user may not be re-authenticated, when they should. This is because Exchange Online may not send a new RST until the old session has expired if the request is processed by an Exchange Online Server maintaining the existing session. Although this condition is not common, it is worth understanding for the overall security posture of the enterprise.

I’ll continue to write about our most common use cases, but if you have any requests don’t hesitate to let me know. Contact us if you have questions about restricting access to Office 365 or need help designing an Identity and Access Management architecture to meet your employee, customer and partner use cases.