Home Realm Discovery In WIF And ADFS 2.0 By Query String
Update 2011-09-29: For a recent project at work I actually had to look at my own blog post to see how I solved this and it turned out to be wrong (I guess I didn’t use the RTW at the time, because I do remember it was working back then).
You don’t actually need any of the stuff in the HomeRealmDiscovery class, so just delete whatever is in there (just leave the class definition). For your aspx file, the only thing you need is the div with your message, and that should be all.
If you’re using asp.net in your RP, the event in global.asax.cs don’t actually have to be hooked up in Application_Start either. Just leave the RedirectingTo… method in there and asp.net will pick that up based on module convention (since the WSFederationAuthenticationModule is registered in your application, by convention asp.net looks in global.asax for WSFederationAuthenticationModule_[eventName]).
When working with passive federation you quickly run into Home Realm Discovery (HRD) (I couldn’t help notice that the short name became HRD which reads HARD :-) ). Anyways, HRD is about which identity provider (IP-STS) should authenticate the user and how to properly redirect the user to their home IP-STS. One example where HRD comes into play is when an organization have multiple partners that authenticate using their own internal STS. An example of that is illustrated in Figure1 below:
Figure 1
The Default Behavior
Using ADFS 2.0 as RP-STS you will by default be presented with this screen when you have trusts to one or more IP-STS’s:
Figure 2
Home Realm Query String
You probably do not want to reveal all of your federated partners like this. A better solution is to add a query string to the application URL where you specify the home realm, like this:
https://someWebApp/?whr=[Home Realm URI)
If the home realm (IP-STS) is ADFS 2.0, and using the URLs from Figure1 above, the URL would be:
https://rp.mydomain.com/?whr=https://ip-sts.partner1domain.com/adfs/services/trust
Let WIF Know About WHR
In order for your RP-STS to receive the whr parameter and automatically redirect the user to his home realm, you need to plug into the WIF pipeline of your application. You can do this very easily by editing your Global.asax.cs and listen to the RedirectingToIdentityProvider event like this:
using Microsoft.IdentityModel.Web;...protected void Application_Start(object sender, EventArgs e){FederatedAuthentication.WSFederationAuthenticationModule.RedirectingToIdentityProvider += new EventHandler(WSFederationAuthenticationModule_RedirectingToIdentityProvider); }void WSFederationAuthenticationModule_RedirectingToIdentityProvider(object sender, RedirectingToIdentityProviderEventArgs e){e.SignInRequestMessage.HomeRealm = Request["whr"];}
Remove The Manual Home Realm Selection From ADFS
The next thing you probably want to do is prevent the RP-STS of displaying its home realm selection page. I didn’t find clear guidance of how to do this, but I found a solution that works. In the ADFS web folder of the RP-STS (C:\inetpub\adfs\ls\) you can edit the HomeRealmDiscovery.aspx and HomeRealmDiscovery.aspx.cs to display a message to the user and remove the dropdown for selecting home realm.
In HomeRealmDiscovery.aspx I removed the <div class="GroupXXLargeMargin"> section and changed the message “The site that you are accessing…” to something more informative. In the HomeRealmDiscovery.aspx.cs page I commented out everything related to the PassiveIdentityProvidersDropDownList control.
<%@ Page Language="C#" MasterPageFile="~/MasterPages/MasterPage.master" AutoEventWireup="true"CodeFile="HomeRealmDiscovery.aspx.cs"ValidateRequest="false"Inherits="HomeRealmDiscovery" Title="Sign In"%><%@ Register TagPrefix="adfs" Namespace="Microsoft.IdentityServer.Web.UI" assembly="Microsoft.IdentityServer" %><%@ OutputCache Location="None" %><asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"><script type="text/javascript" src="FederationPassiveJScript.js">script><div class="GroupXLargeMargin">The site that you are accessing requires Home Realm Discovery to sign in. Please contact your system administrator for further details.div><asp:Panel ID="CardSignInPanel" Visible="False" runat="server" CssClass="GroupXXLargeMargin">Or, <a href="#" onclick="InfocardLink_onclick( document.infoCardObject );">signina> with an Information Card.<adfs:InformationCardControl ID="InformationCard" runat="server">adfs:InformationCardControl><script>AddOnload( LoadCardPanel );script>asp:Panel>asp:Content>
HomeRealmDiscovery.aspx
//------------------------------------------------------------// Copyright (c) Microsoft Corporation. All rights reserved.//------------------------------------------------------------using System;using Microsoft.IdentityServer.Web.Configuration;using Microsoft.IdentityServer.Web.UI;////// This page enables home realm discovery if this STS is configured to trust multiple claims providers.////// If the persistIdentityProviderInformation setting is enabled and the user has previously/// selected a claims provider, that claims provider will be used automatically.///public partial class HomeRealmDiscovery : Microsoft.IdentityServer.Web.UI.HomeRealmDiscoveryPage{protected void Page_Init( object sender, EventArgs e ){//PassiveIdentityProvidersDropDownList.DataSource = base.ClaimsProviders;//PassiveIdentityProvidersDropDownList.DataBind();if( IsIssuedTokenViaSelectorEnabled() ){InformationCard.TokenSubmitted += TokenSubmitted;CardSignInPanel.Visible = true;}}private bool IsIssuedTokenViaSelectorEnabled(){foreach( AuthenticationTypeElement authenticationType in FederationPassiveConfigurationSection.Current.AuthenticationTypes ){if( authenticationType.Name == "IssuedTokenViaSelector" ){return true;}}return false;}protected void TokenSubmitted( object sender, InformationCardControl.TokenSubmittedEventArgs e ){SignIn( e.Token );}//protected void PassiveSignInButton_Click( object sender, EventArgs e )//{// SelectHomeRealm( PassiveIdentityProvidersDropDownList.SelectedItem.Value );//}}
HomeRealmDiscovery.aspx.cs
You then get a page like this if no whr is provided:
Anything I can do about that URL?
If you don’t want your users to relate to the rather cryptic URL needed to support HRD there are several ways to make it a bit more user friendly. I will give a few suggestions here, but there are probably other (and maybe better) solutions than I can come up with right now.
- Provide a shortcut on your users desktop or similar and have them use this to access the application
- Detect by IP range and redirect to proper IP-STS
- Provide a nice URL redirect either from the Relying Party (application) or IIS. E.g. https://someWebApp/YourCompany/ redirects to https://rp.mydomain.com/?whr=https://sts.yourCompany.lan/adfs/services/trust
One thing to note if you have the default settings in the web.config file for your RP-STS, specifically the
