Auto-redirect ADFS 4.0 home realm discovery based on client IP

As I mentioned in my previous post here that I will explain how to auto-redirect the home realm discovery page to an ADFS namespace (claims provider trust) based on client’s IP so here I am.

Let’s say you have many ADFS servers (claims providers trusts) linked to a central ADFS 4.0 server and you want to auto-redirect the user to a linked ADFS server login page based on user’s IP instead of letting the user to choose a respective ADFS server from the list on the home realm discovery page as explained in the below request flow diagram.

You can do so by doing some customization as mentioned below:

  1. Create a database of IP ranges mapped to ADFS namespaces
  2. Develop a Web API which returns the relevant ADFS namespace based on request IP
  3. Add custom code in onload.js file on the central ADFS 4.0 server to call the Web API and do the redirection

It is assumed that all the boxes including Central ADFS, linked ADFS, Web Server, SQL Server are setup. All the nitties and gritties are sorted out in terms of firewall rules, DNS lookups, SSL certificates. If not then you can get help from an infrastructure guy on that.

Lets perform the required action on SQL, Web and ADFS Server.

SQL Server

Perform the following actions on the SQL Server:

  1. Create a new database
  2. Create a new table called Registration as shown below

  1. Insert some records in the table for the linked ADFS server IP range, for example

Start IP: 172.31.117.1, End IP: 172.31.117.254, Redirect Name: http://adfs.adminlab.com/adfs/services/trust

Web Server

Perform the following actions for the Web API development and deployment:

  1. Create a new ASP.NET MVC Web API project using Visual Studio
  2. Create a new class called Redirect.cs as shown below (I would have used the same name as database table name ‘Registration’ but it’s OK for now)

  1. Insert a new Web API controller class called ResolverController.cs as shown below. What we are doing here is getting the request IP address and getting the IP ranges from the database, comparing the request IP address with the IP ranges from the database by converting both to long IP address. If the request IP is in range then returning the redirect object.

  1. Add a connection string in the web.config named DbConnectionString pointing to the database we created above.
  2. Deploy this web API project to the web server IIS
  3. Configure the HTTPS binding as well for this web API project using the SSL certificate
  4. Note down the URL of the web API, something like ‘https://{Web-Server-Web-API-URL}/api/resolver/get’, this will be used in the onload.js

Central ADFS 4.0 Server

Perform the following actions on the central ADFS 4.0 server:

  1. Run the following PowerShell command to export current theme to a location

Export-AdfsWebTheme -Name default -DirectoryPath D:\Themes\Custom

  1. Run the following PowerShell command to create a new custom theme based on current theme

New-AdfsWebTheme -Name custom -SourceName default 

  1. Update onload.js file extracted in step 1 at D:\Themes\Custom\theme\script with following code added at the end of the file. What we are doing here is calling the web API which returns the matched Redirect object with RedirectName as ADFS namespace and setting the HRD.selection as that redirect name.

  1. Run the following PowerShell command to update back the onload.js file in the theme

Set-AdfsWebTheme -TargetName custom -AdditionalFileResource @{Uri=’/adfs/portal/script/onload.js’;path=”D:\Themes\Custom\theme\script\onload.js”} 

  1. Run the following PowerShell command to make the custom theme as your default theme

Set-AdfsWebConfig -ActiveThemeName custom -HRDCookieEnabled $false

Now when you test from your linked ADFS server or a client machine linked to the linked ADFS server (which is linked to a central ADFS server), the auto-redirect kicks in from onload.js and forwards it to web API which gets the client IP and matches it with relevant ADFS where the request came from and redirects the user to the relevant ADFS login page, instead of user selecting the relevant ADFS namespace from the available list on home realm discovery page.

If the relevant match is not found, the default home realm discovery page with list of available ADFS namespaces is shown.

Some advanced ADFS 4.0 branding customization

As you are aware that you can use some of the PowerShell commands to update the logo, banner/illustration images as well as home, privacy and other links of the ADFS 4.0 home realm discovery or sign in page. Below is an example of doing so

Set-AdfsWebTheme -TargetName custom -Logo @{path=”P:\Theme\Logo\logo.png”}

The above command would update the current logo image on the custom theme.

Set-AdfsGlobalWebContent -HomeLink https://{www.YourWebsite.Com}/ -HomeLinkText Home

Above command would update the “Home” link on all pages of your ADFS theme.

How about doing below customization?

 

You can do above customizations by writing custom code in the “onload.js”. The process of exporting the “onload.js” file and importing it back again to ADFS 4.0 theme is explained in my previous post here.

So our requirements are mentioned below:

  1. Change the home realm discovery page sign in label message from “Sign in with one of these accounts” to something else
  2. Change home realm discovery page title
  3. Add “User agreement” and “Code of conduct” links along with some text message on home realm discovery page
  4. Change sing in page title
  5. Change the sign in label message on sign in page from “Sign in with your organizational account” to something else

But just to repeat the some of the required steps to export/import onload.js file, Run the following PowerShell command to export current theme to a location

Export-AdfsWebTheme -Name default -DirectoryPath D:\Themes\Custom

Run the following PowerShell command to create a new custom theme based on current theme

New-AdfsWebTheme -Name custom -SourceName default

Update onload.js file extracted at D:\Themes\Custom\theme\script with following code snippets added at the end of the file:

Run the following PowerShell command to update back the onload.js file to the theme

Set-AdfsWebTheme -TargetName custom -AdditionalFileResource @{Uri=’/adfs/portal/script/onload.js’;path=”D:\Themes\Custom\theme\script\onload.js”}

Run the following PowerShell command to make the custom theme as your default theme

Set-AdfsWebConfig -ActiveThemeName custom -HRDCookieEnabled $false

You must be thinking that we have missed point no. 6, 7 and 8. No, we haven’t. We don’t need to update anything in the onload.js, this can be achieved by some PowerShell commands mentioned below:

Requirement no. 6 and 7 (combined) can be done by below PowerShell command

Set-AdfsGlobalWebContent -SignInPageDescriptionText “View the {Your Company Name} <A href='{User Agreement URL}’ target=’_blank’>User Agreement</A> and <A href='{Code of Conduct URL}’ target=’_blank’>Code of Conduct</A>. </br></br>Forgotten your password? Please click <A href='{Staff password change URL}’ target=’_blank’>staff</A> or <A href='{Student password change URL}’ target=’_blank’>student</A> to reset your password.”

Requirement no. 8: Run the following PowerShell commands to set the Home, Privacy and HelpDesk link texts

Set-AdfsGlobalWebContent -HomeLink {Your company URL} -HomeLinkText Home

Set-AdfsGlobalWebContent -PrivacyLink {Your company privacy policy URL} -PrivacyLinkText Privacy

Set-AdfsGlobalWebContent -HelpDeskLink {Your company disclaimer URL} -HelpDeskLinkText Disclaimer

In the next article I will explain you, how to auto-redirect the home realm discovery to an ADFS namespace (claims provider trust) based on client’s IP.

Display dropdown selection list on AD FS 4.0 Home Realm Discovery page

On AD FS 2.0 or 3.0 home realm discovery page, there was an option to select the AD FS namespace from a dropdown list. But in AD FS 4.0 it has been changed to HTML DIVs and sometimes it can be annoying if you have many (100s) of claims provider trusts available to choose from. So there is a customization required to change the HTML DIVs selection to a dropdown list selection.

Before doing the customizations, the HRD page selection section looks like:

In AD FS 4.0 this customization can be done in an “onload.js” file available in the AD FS theme. We can follow the below steps to achieve this:

  1. Export the current AD FS theme to a location.
  2. Create a custom theme based on the current theme.
  3. Modify the “onload.js” file with required customizations.
  4. Import the “onload.js” file back to the custom theme.
  5. Make the custom theme as the default theme.

Let’s perform these above steps one by one.

Run the following PowerShell command to export current theme to a location

Export-AdfsWebTheme -Name default -DirectoryPath D:\Themes\Custom

Run the following PowerShell command to create a new custom theme based on current theme

New-AdfsWebTheme -Name custom -SourceName default

Update onload.js file extracted in step 1 at D:\Themes\Custom\theme\script with following code added at the end of the file:

Run the following PowerShell command to update back the onload.js file in the theme

Set-AdfsWebTheme -TargetName custom -AdditionalFileResource @{Uri=’/adfs/portal/script/onload.js’;path=”D:\Themes\Custom\theme\script\onload.js”}

Run the following PowerShell command to make the custom theme as your default theme

Set-AdfsWebConfig -ActiveThemeName custom -HRDCookieEnabled $false

Now the HRD page selection section would look like

You may have noticed that we have moved the Active Directory on top of the list.

Explaining the approach…

  1. Define a function SetHRD that would be used to set the HRD.selection to the value of the selected option from the dropdown list.
  2. Then define the loadScript function to load the JQuery. This function takes up the JQuery source URL and a callback function. It then appends the script at the end of the head element in the HTML.
  3. Then call the loadscript function with the default URL of the JQuery source available in AD FS 4.0 and a callback function.
  4. In the callback function check if there is an HRD area element available on the page.
  5. If it’s available then define the select element with onchange event set to call SetHRD method already defined and pass on the selected option.
  6. Adding a default option as “Choose Your AD FS”.
  7. Then select the DIV containing onclick attribute with “AD Authority” in the text (the default Active Directory option to be as the 1st selection option in the dropdown list). If you do an inspect element (press F12 in Chrome and navigate to the element) on that HTML DIV you will see a call to the HRD.selection function with respective AD FS namespace/Claim Provider Trust, in this case it would be “AD Authority” for Active Directory.
  8. Extract the HRD Selection value out of the onclick attribute of the selected DIV.
  9. Append the option to the string with the extracted value and text.
  10. Loop through all the DIVs containing ADFS namespaces, extract the values and text
  11. Append them to the string to make the select element options.
  12. In the end hide all the DIVs containing the AD FS namespaces having CSS Class idp and insert the newly constructed string for the dropdown list right after the openingMessage element.

Hope this helps…