Hi All,
This article is the second part of a series about Multiple Local Authentication Methods with ADFS 2.0. Here is the first part
This article is a brief synthesis of some great article :
Customization of the HomeRealmDiscovery page is a great solution to add custom behavior during passive authentication. For example, adding browser detection, subnet detection, and providing automatic redirect.
Enable the HomeRealmDiscovery
But to enable the HomeRealmDiscovery feature, ADFS must act as a pure relying party STS (RP-STS) (This is when AD FS 2.0 has configured claims providers, but all local authentication methods are disabled in the web.config file. AD FS 2.0 can only direct the user to authenticate with a trusted STS.) or as an Hybrid STS (This is when AD FS 2.0 has configured claims providers, and uses a local authentication method).
If you remember my use case, for the moment, my ADFS is acting as a pure IP-STS. If I want to enable HomeRealmDiscovery and local authentication, I have to transform my IP-STS to an hybrid STS. To do that, I have just created a “fake” claims provider trust.
Now, when I want to sign on my application, I can see this menu where Other is my “fake” claims provider trust :

If I select my Active Directory Identity Provider (adfs.labiam.net), I will be redirected to the default Local Authentication Handler (as seen in the first part).
First part of the customization is to rewrite this menu to show the list of Authentication Methods I want to use. The initialization of the list is done in the Page_init function :
protected void Page_Init( object sender, EventArgs e )
{
PassiveIdentityProvidersDropDownList.DataSource = base.ClaimsProviders;
PassiveIdentityProvidersDropDownList.DataBind();
}
The base.ClaimsProviders return the list of the enabled IdP in ADFS. We can modify this code to list the local authentication types :
protected void Page_Init( object sender, EventArgs e )
{
PassiveIdentityProvidersDropDownList.Items.Add("Integrated");
PassiveIdentityProvidersDropDownList.Items.Add("Certificate");
}
Now, when we click on the button, we must be redirected to the correct URL (see part 1). We can do that in the PassiveSignInButton_Click function.
protected void PassiveSignInButton_Click(object sender, EventArgs e)
{
switch (PassiveIdentityProvidersDropDownList.SelectedItem.Value)
{
case "Integrated":
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/integrated/" + HttpContext.Current.Request.Url.Query);
break;
case "Certificate":
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/sslclient/" + HttpContext.Current.Request.Url.Query);
break;
default:
break;
}
}
Now, we have the following list :

Remember the last choice
During the redirection, some cookies are created. One of those cookies is the MSISIPSelectionPersistent. This cookie is the persistent cookie which is written to the file system on the client that shows who should be the identity provider (IDP) for this client. In my case, it is a problem, because if I am automatically redirected to my AD IdP, I will be prompted by the default Authentication Method (yes, again, see the part 1). We can disable this persistence in the web.config file : change <persistIdentityProviderInformation enabled="true" lifetimeInDays="90"/> into <persistIdentityProviderInformation enabled="false"/>
Ok, great, but now, the user should always choose an authentication method, each time he close his browser. We can create an other cookie, to keep in mind the selected authentication method.
switch (PassiveIdentityProvidersDropDownList.SelectedItem.Value)
{
case "Integrated":
Response.Cookies["MSISPAuthenticationMethod"].Value = "Integrated";
Response.Cookies["MSISPAuthenticationMethod"].Path = "/adfs/ls";
Response.Cookies["MSISPAuthenticationMethod"].Domain = HttpContext.Current.Request.Url.Host;
Response.Cookies["MSISPAuthenticationMethod"].Expires = DateTime.Now.AddDays(8d);
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/integrated/" + HttpContext.Current.Request.Url.Query);
break;
case "Certificate":
Response.Cookies["MSISPAuthenticationMethod"].Value = "Certificate";
Response.Cookies["MSISPAuthenticationMethod"].Path = "/adfs/ls";
Response.Cookies["MSISPAuthenticationMethod"].Domain = HttpContext.Current.Request.Url.Host;
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/sslclient/" + HttpContext.Current.Request.Url.Query);
break;
default:
break;
}
Then we can add the detection of the cookie and automatically redirect the user to the previous authentication handler. In the Page_init, add the following code :
if (Request.Cookies["MSISPAuthenticationMethod"] != null)
{
switch (Request.Cookies["MSISPAuthenticationMethod"].Value)
{
case "Integrated":
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/integrated/" + HttpContext.Current.Request.Url.Query);
break;
case "Certificate":
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/sslclient/" + HttpContext.Current.Request.Url.Query);
break;
}
}
Now, during the first logon, a cookie is created :

Mobile Device Detection
Now, I want to redirect automatically iPhone, iPad and Windows Phone to the sslclient authentication handler.
During the Page_init, I can add the following code :
if (HttpContext.Current.Request.UserAgent.Contains("iPhone") || HttpContext.Current.Request.UserAgent.Contains("Windows Phone") || HttpContext.Current.Request.UserAgent.Contains("iPad") )
{
Response.Redirect("https://" + HttpContext.Current.Request.Url.Host + "/adfs/ls/auth/sslclient/" + HttpContext.Current.Request.Url.Query);
}
Now, when I access my Claims Aware Application through my iPad (I have added 2 user certificates on my iPad to show how it is working) :


I choose the certificate of James Kirk, and I am automatically log on.
My web application prints the claims of my token. We can see that the value of the authenticationmethod is tlsclient

Published by Olivier DETILLEUX