ADFS Service Communications Certificate : Update/Renew


If you are looking to update/renew the ADFS service communications certificate then this is a replacement post for an older one….

Remember that ADFS servers are domain joined whereas ADFS WAP servers are in a workgroup, so for automation you will require separate commands or scripting.

You need to import the new new SSL certificate on all ADFS servers, this includes ADFS and ADFS WAP – as all the servers use the certificate for the SSL bindings of the service ADFS, you will need to get your PFX file which will contain the private and public key, this will come from your external certificate authority.

Copy and Install Certificate to ADFS Federation Servers

Once you have you PFX file in a folder this script will enable you to copy it the remote servers the install the certificate to the "Personal" store under the computer account content all remotely using a script, which will save some of the heavy lifting, obviously change the variables here and other sections in bold:

# Variables
$sourcePath = "C:\NewPFX\ADFS_2025.pfx"  # Local path to the certificate file
$servers = @("adfssrv1.bear.local", 
"adfssrv2.bear.local", "adfssrv3.bear.local")  # List of remote servers
$pfxPassword = "
)Lgi}xXmCyT8KX1jymfkff#ZoLN+MVW^t3eBR,6aPx9="  # PFX file password

foreach ($server in $servers) {
    try {
        $destinationPath = "\\$server\C$\Temp\adfs2025.pfx"  # Remote path where the file will be copied

# Step 1: Copy the certificate file to the remote computer
        Copy-Item -Path $sourcePath -Destination $destinationPath -Force

# Step 2: Create a PowerShell session on the remote computer
        $session = New-PSSession -ComputerName $server

# Step 3: Import the certificate on the remote computer
        Invoke-Command -Session $session -ScriptBlock {
            param ($certPath, $password)
            try {
                $securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
                $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
                $cert.Import($certPath, $securePassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)
                if ($cert -eq $null) {
                    throw "Failed to import certificate."
                }
               $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
                $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
                $store.Add($cert)
                $store.Close()

                Write-Output "Certificate imported and added successfully."
            } catch {
                Write-Error "An error occurred: $_"
            }
        } -ArgumentList $destinationPath, $pfxPassword

# Step 4: Clean up by removing the certificate file from the remote computer

        Remove-Item -Path $destinationPath -Force

# Close the session

      Remove-PSSession -Session $session
 } catch {
        Write-Error "An error occurred on server ${server}: $_"
    }
}

Copy and Install Certificate to ADFS (Web Application Proxy) WAP Servers

We now need to copy the same certificates to the WAP server, now these are in a workgroup so its a local account only and you need to ensure that WinRM is enabled and allowed via the firewall else this script will not work.

# Variables
$sourcePath = "C:\NewPFX\ADFS_2025.pfx"  # Local path to the certificate file
$servers = @("adfssrv-wap1.bear.local", 
"adfssrv-wap2.bear.local", "adfssrv-wap3.bear.local")  # List of remote servers
$pfxPassword = ")Lgi}xXmCyT8KX1jymfkff#ZoLN+MVW^t3eBR,6aPx9="  # PFX file password
$credential = Get-Credential  # Prompt for credentials

foreach ($server in $servers) {
    try {
        $destinationPath = "\\$server\C$\Temp\adfs2025.pfx"  # Remote path where the file will be copied

        # Step 1: Copy the certificate file to the remote computer
        Copy-Item -Path $sourcePath -Destination $destinationPath -Force -Credential $credential

        # Step 2: Create a PowerShell session on the remote computer
        $session = New-PSSession -ComputerName $server -Credential $credential

        # Step 3: Import the certificate on the remote computer
        Invoke-Command -Session $session -ScriptBlock {
            param ($certPath, $password)
            try {
                $securePassword = ConvertTo-SecureString -String $password -AsPlainText -Force
                $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
                $cert.Import($certPath, $securePassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::PersistKeySet)

                if ($cert -eq $null) {
                    throw "Failed to import certificate."
                }

                $store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My", [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine)
                $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
                $store.Add($cert)
                $store.Close()

                Write-Output "Certificate imported and added successfully."
            } catch {
                Write-Error "An error occurred: $_"
            }
        } -ArgumentList $destinationPath, $pfxPassword

        # Step 4: Clean up by removing the certificate file from the remote computer
        Remove-Item -Path $destinationPath -Force -Credential $credential

        # Close the session
        Remove-PSSession -Session $session

    } catch {
        Write-Error "An error occurred on server ${server}: $_"
    }
}

Apply permissions to the ADFS Federation servers new Certificate

Next we need to add “adfssrv” and “drs” to SSL certificate to allow, the old method to do that was using this approach:
  1. With the new certificate is selected
  2. Right click choose All Tasks
  3. Select Manage Private keys
  4. If the the “adfssrv” and “drs” are missing so click the Add
  5. Change to local server and enter this : NT SERVICE\adfssrv
  6. Choose Read only
  7. Change to local server and enter this : NT SERVICE\adfssrvNT SERVICE\drs
  8. Choose Read only
That was very "manual" so I thought that could be scripted for sure so lets get that completed which will need to be run locally on each server using the script below:

Certificate Thumbprint Required

If you wish to script this you require the thumbprint for the SSL certificate, so first we need to list all the certificates on the computer with this:

Get-ChildItem Cert:\LocalMachine\My | ft

This will return something like this:



That will give you all the certificates with the data we need missing, so lets change it for this command:

Get-ChildItem Cert:\LocalMachine\My | fl Subject,NotAfter,Thumbprint

This will then show you data we can use and target the correct certificate, here are can see the old certificate and the new certificate with the expiry date of next year.


The data we need is the Thumbprint in the green box, this will used in the next section.

Add adfsrv and drs to the private key via scripting on the ADFS federation server

Note : You will need to update the thumbprint in bold with your actual thumbprint ensure you keep the quotes either end of the thumbprint.

# Define the certificate thumbprint and the accounts
$certThumbprint = "certificate-thumbprint"
$accounts = @("NT SERVICE\adfssrv", "NT SERVICE\drs")

# Load the certificate from the LocalMachine store
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq $certThumbprint }

if ($null -eq $cert) {
    Write-Host "Certificate not found."
    exit
}

# Get the private key file
$privateKeyPath = "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\$($cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName)"

if (-not (Test-Path $privateKeyPath)) {
    Write-Host "Private key file not found."
    exit
}

# Define the function to add read permission
function Add-ReadPermission {
    param (
        [string]$Path,
        [string]$Account
    )
    
    # Get the ACL for the private key file
    $acl = Get-Acl -Path $Path
    
    # Create a new access rule
    $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        $Account,
        [System.Security.AccessControl.FileSystemRights]::Read,
        [System.Security.AccessControl.AccessControlType]::Allow
    )
    
    # Add the access rule to the ACL
    $acl.AddAccessRule($accessRule)
    
    # Set the updated ACL back to the file
    Set-Acl -Path $Path -AclObject $acl
}

# Add read permissions for each account
foreach ($account in $accounts) {
    Add-ReadPermission -Path $privateKeyPath -Account $account
    Write-Host "Read-only permission added for $account."
}

Set new Service Communication certificate on ADFS Federation Server

Now we need to set that new certificate on the federation server which can be done via the GUI but here we will user Powershell:

If you wish to check the current certificate you can use this command to confirm:

Get-AdfsCertificate

This is the default command, but that will give you a rather unhelpful list of attributes you’re not interested in, in this particular, we only care about the certificate type and the thumbprint, So let’s amend that command to filter and show only those values:

Get-AdfsCertificate | fl CertificateType, Thumbprint

You should notice that because you haven’t updated it yet this thumbprint will not match the new certificate, the thumbprint you will see here is your existing certificate that’s about to expire or require renewal.

CertificateType : Service-Communications
Thumbprint      : 898f84a98a33522469a77e59c01db2667b19e633 < Old Thumbprint

CertificateType : Token-Decrypting
Thumbprint      : FB1056DD195CA0C04D35EBF3BA7B552C3D313B0A

CertificateType : Token-Signing
Thumbprint      : 0C4A9DE1D83FCD251835AAA05296D4EB3E0D6083


Update the service communications certificate (which applies to all federation servers)

This will set the new certificate as the active service communication certificate, this will invalidate the current thumbprint and replace it with the new thumbprint we’ve obtained earlier.

Remember:  when you’ve issue this command, the WAP servers will no longer be able to authenticate because they’re using the wrong certificate, so it’s a good idea to be in a position where you can issue the command you need to the WAP servers

Set-AdfsCertificate -CertificateType Service-Communications -Thumbprint "<new_thumbprint>"

Then check again with this command:

Get-AdfsCertificate | fl CertificateType, Thumbprint

You should not notice that the thumbprint next to service communications matches the one from earlier because you’ve just updated it.

CertificateType : Service-Communications
Thumbprint      : xxxx

CertificateType : Token-Decrypting
Thumbprint      : FB1056DD195CA0C04D35EBF3BA7B552C3D313B0A

CertificateType : Token-Signing
Thumbprint      : 0C4A9DE1D83FCD251835AAA05296D4EB3E0D6083

ADFS Server : Update ADFS SSL Certificate

Run this to get the current data:

Get-AdfsSslCertificate

localhost                             443        ‎<old_thumbprint_here>
adfs.severntrent.co.uk        443      ‎‎   <old_thumbprint_here>
adfs.severntrent.co.uk        49443    ‎‎<old_thumbprint_here>

We now need to set the new thumbprint: 

Set-AdfsSslCertificate -Thumbprint "<new_thumbprint>"

Then we need to check the command to make sure the new certificate thumbprint is present:

Get-AdfsSslCertificate

localhost                             443        ‎<new_thumbprint_here>
adfs.severntrent.co.uk        443      ‎‎   <new_thumbprint_here>
adfs.severntrent.co.uk        49443    ‎‎<new_thumbprint_here>

Restart ADFS Federation Service

Once the command to update the Service Communications certificate has been issued you will need to restart the service on all servers that have this role installed, which you can do with this command:

Get-Service -ComputerName <server> -Name <service-name> | Restart-Service 

In this example that command would be: 

Get-Service -ComputerName adfssrv1.bear.local -Name adfssrv | Restart-Service 
Get-Service -ComputerName adfssrv2.bear.local -Name adfssrv | Restart-Service 
Get-Service -ComputerName adfssrv3.bear.local -Name adfssrv | Restart-Service 

Update the application proxy certificate (which applies to each server individually)

Note : You need to run the "Windows Powershell" not the "Windows Powershell x86" - the modules for ADFS WAP are NOT available in the x32 version, you also need to run as Administrator (yes, even if you are one already)

Run this to get the current state of the server:

Get-WebApplicationProxySslCertificate

This will return the current data:

HostName                           PortNumber  CertificateHash
--------                           ----------  ---------------
adfs.bear.me                443        <old_thumbprint_here>
ernterpriseRegistration.bear...     443   <old_thumbprint_here>
adfs.bear.me               49443     <old_thumbprint_here>

Then we need to set the new thumbprint : 

Set-WebApplicationProxySslCertificate -Thumbprint "<new_thumbprint>"

Then we need to check the update was successful with this:

Get-WebApplicationProxySslCertificate

HostName                           PortNumber  CertificateHash
--------                           ----------  ---------------
adfs.bear.me                443        <new_thumbprint_here>
ernterpriseRegistration.bear...     443   <new_thumbprint_here>
adfs.bear.me               49443     <new_thumbprint_here>

Restart ADFS WAP Services

Now you have updated the thumbprint restart the service with this command (you may or may not require the second command)

Restart-Service adfssrv
Restart-Service appproxysvc
Previous Post Next Post

نموذج الاتصال