Deep linking your way out of home realm discovery
Here there’s a very quick post about an often debated topic, home realm discovery.
When your web application trusts multiple identity providers, the first task you have when processing a request is figuring out from where the user is coming from. If the user is coming from your partner Adatum, he’ll have to authenticate with the Adatum (IP) STS before being able to access your application; if he comes from Contoso, he’ll have to authenticate with the Contoso STS before being able to authenticate with your application. The Contoso STS and the Adatum STS clearly live at different addresses, which means that you’ll typically need to feature some logic (often residing on your federation provider STS) to determine from where your user is coming from before starting the classic WS-Fed redirection dance. CardSpace provides a very neat solution to this, but it is not always readily available. The result is that everybody comes out with some different solution, which often involves the user to interact with a UI. For example the MFG will prompt you for a live id, and once it will sense that you entered an account belonging to a federated partner it will offer you to redirect to your IP STS. Others may offer a simple drop down which enumerates the federated partners, and ask you to pick your own (not especially handy if you want to keep your list of partners/customers private).
While those mechanisms are necessary, some times your users may get fed up to always have to handle UI tasks instead of enjoying smooth, heated-knife-though-butter SSO.
Well, here there’s a trick that we used in the internal version of FabrikamShipping for easing that pain: basically, we include in a deep link all the hops that a user from Adatum would go though when going through the authentication experience. As a result, adatum users will click on a link that points directly to the Adatum ADFS2 and already contains all the info for performing the redirects to the R-STS of the app and to the app itself. If you know about WS-Fed you may in principle build the link from scratch, but since I am notoriously lazy (and bad at remembering syntactic sugar) I prefer the following trick: I go through the authentication experience, and once I reach the authentication pages of the intended IP I save the URI currently displayed in the address bar.
Let’s get one pretty complicated example: this is the deep link we used for showing SSO via ADFS2+MFG to CRM Online. (disclaimer, this was made with versions that are older from the ones you may have available now: you may have to re-build, this is just for giving you an idea).
Now, isn’t that quite a mouthful! Let’s improve it a bit by url-decoding:
Sliightly better. Now, should we try to parse this guy? Sorry, no time; maybe some other time. Let’s just get a very rough look at how this may be broken down:
|https://www.adatumcorporation.com/ FederationPassive/auth/integrated/IntegratedSignIn.aspx?||this is the URI of your IP. In fact, it points directly to the endpoint you are interested into (in this case the integrated security one, which should not promt the user when accessed from the intranet)|
|wa=wsignin1.0 &wtrealm=uri:WindowsLiveID &wctx=LoginOptions=2 &wa=wsignin1.0 &rpsnv=10 &rver=4.5.2130.0 &wp=MBI_SSL &wreply=||those are parameters of the request. You’ll notice here some familiar WS-federation parameters (wa, wtrealm, wtcx,wp, wreply) but also some liveid specific ones (rpsnv). In this case the federation relationship we are riding is between our ADFS2 and the MFG, in fact the wtrealm points to windows live id (which acts as the federation provider/resource STS here)|
|https://signin.crm.dynamics.com/Portal/signin/signin.aspx?mscrmurl=https://signin.crm.dynamics.com/portal/notification/notification.aspx?organizationid=9a3db539-849c-4a52-bdd1-460cd6e81fac &skipnotification=false &target=https://adatumcorporation.crm.dynamics.com/loader.aspx &lc=1033&id=252280||The content of the wreply is the actual RP, which in turn it includes its own login mumbo-jumbo|
Details aside, the effect of using this URL is that Adatum users will experience smooth SSO to CRM online despite of the multiple STS layers between them and the application. Neat! Note that if everybody in the chain did their homework, there should be no way to craft malicious URLs: if every issuer validates the audience to which it is requested to generate a token for, the risk of redirect attacks is mitigated. This should also be a wake-up call for the ones who rely just on UI tricks for managing HRD: this method can be used to request tokens from an arbitrary issuer, regardless of if it appears in the dropdown or not, hence validating everything is really key.
Unexpected bonus: this approach may come in handy also for less complicated cases. For example if your ADFS2 exposes more than one endpoint and you want to pre-select one, all you need to do is embedding it in the URL (something like https://www.adatumcorporation.com/FederationPassive/auth/integrated/IntegratedSignIn.aspx?wa=wsignin1.0&wtrealm=https://www.fabrikamshipping.com/FabrikamShipping/Default.asmx).
Now, the usual disclaimers. This method is not a solution to home realm discovery, rather it is a “shortcut” that piggybacks on existing home real discovery solutions which must be in place for this to work. Furthermore, this has to be arranged by every partner and relies completely on the fact that the users will access the application through the specially crafter URL as opposed to direct links. It is not guaranteed to work in all cases, and I am sharing it with you just because I think it is neat: for official guidance on how to use WIF, ADFS2, etc please always refer to the federated identity team blog.
That said, this really worked well for our content: thanks to “Office” Donovan who, despite having left us for the IW crowd, still has what it takes and gave me a refresher on this!