Restrict iOS apps which can access to Office 365 services (ADFS required)

Merry Christmas everyone!!

Today is Christmas and finally got some time to focus on a new article I wanted to write for a while.

A lot of my Microsoft Intune customers in Japan are asking me the same question over and over again: how can I restrict the applications which can connect to Office 365? and that’s a question with lot of sense. Why? Because in Intune, we offer the MAM capacity for data loss prevention (DLP). As you might know, when you open a corporate document in a MAM enabled app like Microsoft Word, you can't paste the content of that document in a non-managed app.

Those customer are basically asking me if it is possible to restrict access to Office 365 to only Microsoft MAM enabled apps like Microsoft Outlook, Word, Excel, PowerPoint, OneDrive or Intune Managed Browser (check this TechNet link to see all the MAM enabled apps in Intune).

The answer in short is: with only Intune, you can’t but if you have a federated domain with ADFS, then there is a solution (not a perfect one) to the problem.

If you have already used ADFS and its claim rules, you know that you can create conditions based of parameters (claims) that the client presents to ADFS. Within the available claims, there’s only one which can help you identify the application which tries to authenticate to ADFS services: user agent (x-ms-client-user-agent). Btw I have done all my testing with ADFS 3.0 (Windows Server 2012 R2) but it should work the same on ADFS 2.0.

Disclaimer: I’m not an ADFS nor a security expert but I do know that it’s not a perfect solution. User agent can change and are not unique to a software vendor. Even though Microsoft apps are all using the same user agent, other non-Microsoft apps could in the future use the same user agent or even spoof the same user agent to be seen as a Microsoft apps. So if you implement this solution in production, you should know the risk you are taking.

If you want to restrict Office 365 access based on location of the client, you should take a look at the excellent TechNet article describing the ADFS rules needed to implement that.

Coming back to my user agent story, every app has an user agent. For Microsoft apps like Outlook, Word, Excel PowerPoint, OneDrive and Intune Managed Browser on iOS, they are all sharing the same user agent.

Here’s the user agent of Microsoft Outlook/Word/Excel/PowerPoint/OneDrive/Intune Managed Browser on an iOS 8.4.1 device.

Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321

And this is an example of user agent of Safari browser on iOS 8.4.1:

Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4

Last example is the user agent of Chrome browser on iOS 8.4.1:

Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) CriOS/44.0.2403.67 Mobile/12H321 Safari/600.1.4

You can notice the slight differences between those user agents, right? So an easy way to allow MS apps’ user agent to access Office 365 would be the following claim rule (whitelist way):

exists([Type == " https://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent" , Value == "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12H321"])
=> issue(Type = "
https://schemas.microsoft.com/authorization/claims/permit" , Value = "true");

As you might notice, there’s many variable characters and numbers in the above user agent: form factor of the phone (iPhone/iPod/iPad), iOS version, webkit version, iOS build number. And all of these numbers will change when iOS will be updated or when the app itself will be updated.

To ensure that we are not affected by any of these variable in the user agent, I used regex (regular expression) to only match the other characters. Here’s an example of what an ADFS claim rule looks like with regex:

image

exists([Type == " https://schemas.microsoft.com/2012/01/requestcontext/claims/x-ms-client-user-agent" , Value =~ "^Mozilla\/5.0 \((iPhone|iPad|iPod); (CPU|CPU iPhone) (?:OS\s*\d+_\d+(?:_\d+)?\s*)? like Mac OS X\) (?:AppleWebKit\/\d+(?:\.\d+(?:\.\d+)?|\s*\+)?\s*)? \(KHTML, like Gecko\) (?:Mobile\/\w+\s*)?$"])
=> issue(Type = "
https://schemas.microsoft.com/authorization/claims/permit" , Value = "true");

Again I repeat, this is not a perfect solution but it can help limiting potential access to Office 365 from unwanted applications. Implement this at your own risk.

PS: To find the user agent of an app, I recommend setting the default ADFS rule to deny all access in a lab environment. You also need to enable auditing of ADFS access (follow that article to enabled auditing on ADFS). Then when trying to authenticate to ADFS from an app, you will be denied (as expected) and in the security logs of your ADFS server, you will find the user agent of the application!

Additional notes for Android:

It works the same way for Android apps but there’s a difference between Office apps user agent and Intune Managed Browser user agent on this platform.

Microsoft Word for Android user agent:

Mozilla/5.0 (Linux; Android 5.0.1; GT-I9505 Build/LRX22C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/46.0.2490.76 Mobile Safari/537.36 PKeyAuth/1.0

Intune Managed Browser for Android user agent:

Mozilla/5.0 (Linux; Android 5.0.1; GT-I9505 Build/LRX22C; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/46.0.2490.76 Mobile Safari/537.36