Fiddling Office365 ADFS to work like on-premise exchange

BY IN Networking NO COMMENTS YET , , , ,

Office 365 uses ADFS (Active Directory Federated Services) to log on users.

ADFS isn’t true Single Sign-on, it’s more like SAML token based: The idea is, you visit a service provider (like Office365) and they redirect you to your organisation’s ADFS service to log on. Then you get directed back with an access token. Here at the university, we have two internal ADFS servers, Network Load-Balanced, plus an ADFS proxy for external.

The Microsoft model is that these servers are separated by your split-brain DNS: Anything that looks up, for example, sso.bolton.ac.uk on the internal DNS gets the internal ADFS(s) and anything outside your network looks up the same and gets your ADFS Proxy server. So by default, the internal servers use NTLM authentication so users on your network don’t have to re-enter their credentials.

Problem: Not all devices that point to the internal DNS are domain-joined PCs

I said devices there for a reason: Our wireless users get the internal DNS. As do student halls of residence. So anyone using a wireless laptop that goes to our http://cloudmail.bolton.ac.uk Office365 login URL (a cname that points to outlook.com and gets redirected to our SSO ADFS login page) will be presented with a horrible browser username/password challenge box. Another problem with the default configuration, specific to Office 365, is that staff don’t have mailboxes on Office365. So, trying to access a test student mailbox gives the UserHasNoMailboxException:

nomailbox

NTLM is great, and we want it for domain-joined student PCs. How do we differentiate?

You can change the default authentication method that ADFS uses in the web.config file (usu. c:\inetpub\adfs\ls\web.config) by swapping these lines:

<microsoft.identityServer.web>
 <localAuthenticationTypes>
 <add name="Forms" page="FormsSignIn.aspx" />
 <add name="Integrated" page="auth/integrated/" />
 </localAuthenticationTypes>

This makes forms-based authentication the default. And you can customise the login page by following this guide: http://blogs.technet.com/b/stevenha/archive/2012/11/12/customizing-the-adfs-forms-based-login-page.aspx

That solves the problem of NTLM trying to auto-login all users on our network. But here’s how our exchange environment currently works for students:

  • Users type in http://webmail.bolton.ac.uk and are presented with a login form, whether off-campus or on-campus.
  • Students get a shortcut on their desktop and start menu pointing to http://exchange-server/exchange (or /owa for exchange 2010+). This logs them in with NTLM automatically.

This makes sense for a couple of reasons: You might want to access your email from another user’s computer. Perhaps a few students are working in a group around one PC. Or a student comes to the help desk with an email query. They can go to the webmail URL and enter their username/password. Then click ‘logout’ or close the browser after. At the same time, you would expect clicking a shortcut on your desktop to know who you are and not need your password again.

Can we replicate the behaviour of exchange?

An administrator at Newcastle University had a similar problem. Not all their internal devices are domain-joined, so they came up with the solution to manipulate the user-agent string on their domain-joined browsers. Details here: https://blogs.ncl.ac.uk/isg/?p=296

That would almost work for us, but we don’t just want all domain-joined PCs using NTLM. We want the user (or their shortcut at least) to choose.

How to find another URL

My hope was to use the /adfs/ls/IdpInitiatedSignon.aspx along with a RelayState string to take users to the login page first, then get ADFS to spit them out to Office365. I installed ADFS Update Rollup 2, added the line <useRelayStateForIdpInitiatedSignOn enabled=”true” /> to web.config, and tried to work out the RPID and RelayState strings. I failed. The closest I got was using the LoginToRP querystring. But that still came up with errors; outlook.com wouldn’t accept the SAML token unless the browser had been there first. Details on RelayState can be found in this technet article.

Then I used the SAML tracer plugin for Firefox. (https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) – it allows you to see all the steps in your redirection journey without having to do quick URL-copies or pick through your history. It turns out that the cloudmail.bolton.ac.uk CNAME takes you to

https://www.outlook.com/owa/?targetname=cloudmail.bolton.ac.uk

and then a URL that looks like this:

https://sso.bolton.ac.uk/adfs/ls/?wa=wsignin1.0&wtrealm=urn:federation:MicrosoftOnline&wctx=wa%3Dwsignin1.0%26rpsnv%3D3%26ct%3D1397212618%26rver%3D6.1.6206.0%26wp%3DMBI_KEY%26wreply%3Dhttps:%252F%252Fwww.outlook.com%252Fowa%252F%26id%3D260563%26whr%3Dbolton.ac.uk%26CBCXT%3Dout

once you’ve logged on, ADFS spits you out here:

https://outlook.office365.com/owa/?exsvurl=1&ll-cc=1033&modurl=0&realm=bolton.ac.uk

Well… If you attempt to access the above URL before you log in, you get taken to your SSO page with a querystring thus:

https://sso.bolton.ac.uk/adfs/ls/?wa=wsignin1.0&wtrealm=urn:federation:MicrosoftOnline&wctx=wa%3Dwsignin1.0%26rpsnv%3D3%26ct%3D1397212663%26rver%3D6.1.6206.0%26wp%3DMBI_SSL%26wreply%3Dhttps:%252F%252Foutlook.office365.com:443%252Fowa%252F%253Fexsvurl%253D1%2526ll-cc%253D1033%2526modurl%253D0%2526realm%253Dbolton.ac.uk%26id%3D260563%26whr%3Dbolton.ac.uk%26CBCXT%3Dout

Spot the difference? The first URL contains a URL-encoded “reply=http://www.outlook.com” while the second contains “reply=https://outlook.office365.com”. This makes sense; it reflects the URL we visited before we got redirected. I now have my two URLs, and using similar code to the guys at Newcastle university I can make ADFS use either forms-based auth or NTLM.

The internal ADFS boxes now have the following in their adfs\ls\FormsSignIn.aspx.cs:

 using System;
using System.Web;
using Microsoft.IdentityServer.Web;
using Microsoft.IdentityServer.Web.UI;

/// <summary>
/// Attempts to authenticate the user via HTTP Forms Authentication.
/// </summary>
public partial class FormsSignIn : FormsLoginPage
{
 protected void Page_Load( object sender, EventArgs e )
 {
 int pos = Request.RawUrl.IndexOf('?');
 int len = Request.RawUrl.Length;
 string rawq = Request.RawUrl.Substring(pos + 1, len - pos - 1);

//Convert query string (qs) to a string
 string qs = HttpUtility.ParseQueryString(rawq).ToString();
 if(qs.IndexOf("outlook.office365.com") > -1)
 {
 Response.Redirect("/adfs/ls/auth/integrated/?" + qs, true);
 }
 else
 {
 //Carry on and do Forms Based Authentication
 } 

 

Easy. Now when all students have moved to Office365, we simply change their webmail shortcuts to

https://outlook.office365.com/owa/?exsvurl=1&ll-cc=1033&modurl=0&realm=bolton.ac.uk

Caveats:

Updates to ADFS may break this.

Updates to how Office365 works may break this. The outlook.office365.com URL may cease to function.

But we’re happy – we can use Office365 like we use on-premise exchange without having to see that horrible sad face.

So, what do you think ?