Jaa


ADFS 2016 - Change the Active Directory claim provider display name in the Home Realm Discovery page

In Windows Server 2012 R2 ADFS (well that everybody calls ADFS 3), the display name of the ADFS farm was also the display name of the Active Directory claim provider name in the Home Realm Discovery page.

 Get-AdfsProperties | Select-Object DisplayName
#Output:
#DisplayName
#-----------
#Yoga Corp.

Here what it looked like:

hrd_name_0

And this regardless of the actual name of the claim provider trust for AD:

 Get-AdfsClaimsProviderTrust -Identifier "AD AUTHORITY" | Select-Object Name
#Output:
#Name
#----
#Active Directory

In Windows Server 2016 ADFS (also known as ADFS 4...) this isn't the case anymore. The display name of the farm is no longer the display name of the Active Directory claim provider trust. As a result, the Home Realm Discovery page will look like this:

hrd_name_1

We can see that the display name of my farm is Piaudonn ADFS 2016 and that the display name of my AD claim provider is Active Directory. Some PowerShell to illustrate the difference:

 Get-AdfsProperties | Select-Object DisplayName
#Output:
#DisplayName
#-----------
#Piaudonn ADFS 2016

Get-AdfsClaimsProviderTrust -Identifier "AD AUTHORITY" | Select-Object Name
#Output:
#Name
#----
#Active Directory

So the first reflex we have to change it since it is no longer the display name of the farm, is to change the name of the AD claim provider trust directly:

 Get-AdfsClaimsProviderTrust -Identifier "AD AUTHORITY" | Set-AdfsClaimsProviderTrust -Name "Corp Users"

But here is the output:

 Set-AdfsClaimsProviderTrust : PS0027: No properties except AcceptanceTransformRules and AcceptanceTransformRulesFile
can be modified on the ADAuthority claims provider trust. 

So, here is a workaround.

JavaTrick

We will use the OnLoad.js JavaScript present in all rendered page to dynamically change the display name "Active Directory" into what ever we want. In my case: Corp Users.

  1. Create a custom web theme for you ADFS farm.
    Note that JavaScript customization cannot be done for the default web theme. If you already have a custom web theme, you can skip this and go to step 2.

     New-AdfsWebTheme -Name CorpWebTheme -SourceName Default
    

    If you already have set a logo and an illustration picture in the default theme, because I used the Default as the source, they will automatically be present in the newly created CorpWebTheme.

  2. Export the current OnLoad.js to be able to modify it.
    We create the folder C:\CorpWebTheme and run the following cmdLet:

     Export-AdfsWebTheme -Name CorpWebTheme -DirectoryPath C:\CorpWebTheme
    

    This is what we get in our folder:

     C:\>tree /F C:\CorpWebTheme
    Folder PATH listing
    Volume serial number is 5C78-23B0
    C:\CORPWEBTHEME
    ├───css
    │       style.css
    │       style.rtl.css
    │
    ├───illustration
    │       illustration.png
    │
    ├───images
    │   └───idp
    │           idp.png
    │           localsts.png
    │           otherorganizations.png
    │
    └───script
            onload.js
    

    We can see the onload.js in the script subfolder.

  3. Modify the JavaScript.
    We need to detect what is the identifier of the Active Directory display name in the HTML rendering. I use the developer mode of IE (just pressed F12) and use the DOM selector to identify where in is the string is in the page:
    hrd_name_2
    Not a good news, it seems that the claim provider trust display names do not have a unique identifier and they all have the same class:
    hrd_name_3 And it seems that the Active Directory claim provider trust is always the last one (bottom of the list, at least it my labs, if it is not the case in yours, please let me know). Update: I changed the orignal code since it appears that the Active Directory claim provider trust is not always at the end of the list. Hence, the code is looking for the AD trust before replacing its display name.
    So I open the onload.js and add the following code at the end of it:

     //Check if we are in the HRD page
    if ( document.getElementById("hrdArea") ) {
        var strADCPName = "Corp Users" ;
        //Create an array of all claim provider trust section in the page
        var listAllSpanForIdp = document.getElementsByClassName("idpDescription float") ;
        var inc;
        for (inc = 0; inc < listAllSpanForIdp.length; inc++) {
            if ( listAllSpanForIdp[ inc ].innerHTML == "<span class=\"largeTextNoWrap indentNonCollapsible\">Active Directory</span>" ) {
                //Change the HTML content of the matching section to the value specified in the strADCPName variable
                listAllSpanForIdp[ inc ].innerHTML = "<span class=\"largeTextNoWrap indentNonCollapsible\">"+ strADCPName +"</span>" ;
            }
        }
    }
    

    The code is quite self explanatory, I change the HTML content last occurrence of the class "idpDescription float" and replace it with "Corp Users". I save the file with the same name (we can actually give it the name you want, it does not matter).

  4. Import the modified OnLoad.js script back into the web theme.
    I import the script back into the web theme:

     Set-AdfsWebTheme -TargetName CorpWebTheme -AdditionalFileResource @{Uri="/adfs/portal/script/onload.js";path="C:\CorpWebTheme\script\onload.js"}
    

    Once imported you can delete the CorpWebTheme folder. It is no longer used (you imported your JavaScript directly into the ADFS database). And if the webtheme is not the active one, remember to enable it:

     Set-AdfsWebConfig -ActiveThemeName CorpWebTheme
    

And here is the final result:

hrd_name_4

Let me know how it goes in the comments section!

Comments

  • Anonymous
    December 02, 2016
    Thanks Pierre, this is a very big help! Any recommendations for moving the entry back up to the top of the list as well which was the default in Windows 2012 R2 and earlier?
  • Anonymous
    December 02, 2016
    Hi, thanks for this post. I just started to solve the same issue, but in my environment, "Active Directory" is placed as the first option, so script is changing the last CPT. What is worst, with multiple CPTs, there is "+" sign in redirect ...&RedirectToIdentityProvider=AD+AUTHORITY which causing "page can't be displayed". When URI is updated to "AD%20AUTHORITY", it works.
  • Anonymous
    May 18, 2017
    HI Thanks for this information, really useful. Can you share some pointer on how we can reorder iDP providers per our need/design. Being Infra Admin have limited knowledge on JS. :)
  • Anonymous
    May 22, 2017
    I Used below code to move Active Directory to Top, everything working fine.// begin 2016-01-17 customizations// HRD Page changed after upgrading to FBL of 2016//Check if we are in the HRD pageif ( document.getElementById("hrdArea") ) { //debugger var strADCPName = "Corp Users" ; //Create an array of all claim provider trust section in the page var listAllSpanForIdp = document.getElementsByClassName("idpDescription float") ; // if(listAllSpanForIdp.length==4){ var parent = document.createElement("div"); document.getElementById("bySelection").append(parent); parent.append(listAllSpanForIdp[0].parentNode); parent.append(listAllSpanForIdp[1].parentNode); parent.append(listAllSpanForIdp[0].parentNode); }else if(listAllSpanForIdp.length==3){ var parent = document.createElement("div"); document.getElementById("bySelection").append(parent); parent.append(listAllSpanForIdp[0].parentNode); parent.append(listAllSpanForIdp[1].parentNode); } var inc; for (inc = 0; inc < listAllSpanForIdp.length; inc++) { if ( listAllSpanForIdp[ inc ].innerHTML == "Active Directory" ) { //Change the HTML content of the matching section to the value specified in the strADCPName variable listAllSpanForIdp[ inc ].innerHTML = ""+ strADCPName +"" ; //document.getElementById("bySelection").prepend(listAllSpanForIdp[inc].parentNode); } }}
    • Anonymous
      May 31, 2017
      Hi,Regarding the reordering, why are you looking for a length of 4 or 3? What is so special about the 3 or 4 length?The list of IdPs in general is dynamic as you may add or remove an IdP. The code should take that into accountIn addition, per RP trust you can also specify a list of IdP that are allowed to use that Rp trust and that list is a subset of the overall list of IdPs. Again, the code should take that into account.It should not matter how long the IdP list isIs it possible to make this dynamic where the logic is something like:* if more than 1 IdP is listed and the AD IdP is included, then move that IdP to the top.