Replacing the ADFS certificate can be a painful process.
I have learned it the hard way, that's why i thought; let make a thread for this on my blog, for future reference and to help others out.
Let's go!
Import certificates
First import the certificates on your ADFS server(s) and import hem also on your WAP servers (if you have any).
Notice: you must also import all the certificates in the chain (intermediates; see green checkmarks) except for the ROOT certificate (unless you haven't' in your computer store; but usually all globally trusted root CA's are in your computer certificate store.
To easily import the service communication certificate; use the following cmdlet:
Import-PfxCertificate -FilePath C:\certs\mycert.pfx -CertStoreLocation 'cert:\localmachine\my' -Password $(Read-Host "PFX File Password -AsSecureString)
Step one; open the certificate and click on Install Certificate
Then select the Local Machine as store location
Let the wizard automatically choose the store based on the type of certificate
And complete everything as a whole
The prompt after clicking Finish :)
Repeat the above steps for all certificates that are needed
1. the ADFS certificate
2. needed intermediates that the ADFS certificate rely on
Set permissions
After everything is imported correctly; you must set the correct permissions for the service account that is used by ADFS.
You can verify it, by looking in services.msc for the ADFS service, it is probably running under a specific user. That uses must have access to the private key.
Open Windows+R and type mmc and press enter.
After that, add the certificates snap-in
Choose Certificates and click Add
Select Computer account
Open folder Personal\Certificates and right-click on the certificate that should be used. Select All Tasks\Manage Private Keys
Set the permissions accordingly the picture below for your service account that ADFS wil use.
Replacing the certificates on the ADFS server(s).
Get hold of the current SSL thumbprint AND the SSL thumbprint of your new certificate.
Open Powershell with Elevated permissions and use the cmd-let:
dir cert:\localmachine\my
Check and make a note what the current certificate thumbprint that is in use and what the new certificate thumbprint is; that way we can make sure that we aren't replacing it with the same one that is installed right now :)
With the following cmd-let you can see what the current certificate is, that is used by ADFS:
Get-AdfsSslCertificate
Also check what the thumbprint is that is bonded via HTTP.sys; look for the Certificate Hash.
Here is the output
PS H:\> Get-AdfsSslCertificate HostName PortNumber CertificateHash -------- ---------- --------------- sts.domain.com 443 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 localhost 443 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 sts.domain.com 49443 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 PS H:\> dir cert:\localmachine\my Directory: Microsoft.PowerShell.Security\Certificate::localmachine\my Thumbprint Subject ---------- ------- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CN=SERVER, CN=6bXXXXXX-1234-XXXXXXXX-XXXXXXXXXXXX, OU=Microsoft ADFS Agent XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CN=SERVER, CN=6bXXXXXX-1234-XXXXXXXX-XXXXXXXXXXXX, OU=Microsoft ADFS Agent 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 CN=sts.domain.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 CN=sts.domain.com, <output omitted> PS H:\> netsh http show sslcert SSL Certificate bindings: ------------------------- Hostname:port : sts.domain.com l:443 Certificate Hash : 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : AdfsTrustedDevices DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled Hostname:port : localhost:443 Certificate Hash : 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : AdfsTrustedDevices DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled Hostname:port : sts.domain.com :49443 Certificate Hash : 400323XXXXMY_OLD_THUMBPRINTXXXXX4D07B5C0 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : (null) DS Mapper Usage : Disabled Negotiate Client Certificate : Enabled PS H:\>
Now we know what are starting point is and what thumbprints are used.
First update the service communication certificate for the ADFS running the following command and verify:
Set-AdfsCertificate -CertificateType Service-Communications -Thumbprint 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Get-AdfsCertificate
Then restart the ADFS service:
Restart-Service ADFSSRV
Then update the new SSL cert bindings to ADFS configuration and verify:
Set-AdfsSslCertificate -Thumbprint 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Get-AdfsSslCertificate
Again; restart the ADFS service (just to be sure)
Restart-Service ADFSSRV
Check if the certificates are in place and properly bounded:
PS H:\> netsh http show sslcert SSL Certificate bindings: ------------------------- Hostname:port : sts.domain.com:443 Certificate Hash : 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : AdfsTrustedDevices DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled Hostname:port : localhost:443 Certificate Hash : 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : AdfsTrustedDevices DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled Hostname:port : sts.domain.com:49443 Certificate Hash : 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : (null) DS Mapper Usage : Disabled Negotiate Client Certificate : Enabled PS H:\>
Watchout for the default binding!
I experienced out of first hand, that it is possible that the new certificate is not bound on the HTTP.sys level after updating the certificate within ADFS.
This is mostly the case when you're working with a OSI Layer 7 Load balancer for example a Citrix NetScaler. Citrix doesn't support SNI binding to its back-end connections, only to its front-end facing connections; this was the case prior NS 11.1 build 54.
Since the release of NS 11.1 build 54, Citrix NetScaler supports SNI binding to its back-end connections, but i must make a annotation to this.
Citrix published this new feature in it's relase notes, but didn't mention this is only possible if you are NOT working with servicegroups or SSL profiles.
So check if the Certificate Hash is correct on the 0.0.0.0:443 or localhost:443; if not the case, use the following commands.
The AppID is the same for every ADFS server/instance for every ADFS server; you will notice that the AppID issued in my command is exactly the same as yours.
netsh http delete sslcert ipport=0.0.0.0:443 netsh http add sslcert ipport=0.0.0.0:443 certhash=<YOUR_NEW_THUMBPRINT> appid={5d89a20c-beab-4389-9447-324788eb944a} certstorename=MY sslctlstorename=AdfsTrustedDevices
or
netsh http delete sslcert ipport=localhost:443 netsh http add sslcert ipport=localhost:443 certhash=<YOUR_NEW_THUMBPRINT> appid={5d89a20c-beab-4389-9447-324788eb944a} certstorename=MY sslctlstorename=AdfsTrustedDevices
Notice: do this on every ADFS server in your farm (and yes; life is a b*tch)
When done; grab yourself a fresh cup coffee
Afterwards; go the next chapter.
Replacing the certificates on the WAP servers.
Go to the ADFS Proxy servers (WAP).
Do the same on your WAP server, concerning the import certificates.
Then issue the following commands:
Get-WebApplicationProxySslCertificate
Then do:
Set-WebApplicationProxySslCertificate -Thumbprint 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904
Check the result:
Double check the port bindings are correct; the Certificate Hash must be the same as your new thumbprint
PS C:\Users\Administrator> netsh http show sslcert SSL Certificate bindings: ------------------------- Hostname:port : sts.domain.com:443 Certificate Hash : 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : AdfsTrustedDevices DS Mapper Usage : Disabled Negotiate Client Certificate : Disabled Hostname:port : sts.domain.com:49443 Certificate Hash : 100XXXXXXXMY_NEW_THUMBPRINTXXXXXXXXXX904 Application ID : {5d89a20c-beab-4389-9447-324788eb944a} Certificate Store Name : MY Verify Client Certificate Revocation : Enabled Verify Revocation Using Cached Client Certificate Only : Disabled Usage Check : Enabled Revocation Freshness Time : 0 URL Retrieval Timeout : 0 Ctl Identifier : (null) Ctl Store Name : (null) DS Mapper Usage : Disabled Negotiate Client Certificate : Enabled
Incase you see a default binding (probably the case if you are using an mature load balancer), you must also replace it there.
The AppID is the same for every ADFS server/instance for every ADFS server; you will notice that the AppID issued in my command is exactly the same as yours.
netsh http delete sslcert ipport=0.0.0.0:443 netsh http add sslcert ipport=0.0.0.0:443 certhash=<YOUR_NEW_THUMBPRINT> appid=100ad0af0b9505bdd4bac9d23de187255082a904 certstorename=MY
And finally; restart the ADFS service
Restart-Service ADFSSRV
So, how do I test the functionality of the ADFS?
The ADFS uses the IIS to host his own end points. There is also a simple Login-page that every user can use:
'https://sts.domain.com_or_other_FQDN/adfs/ls/IdpInitiatedSignon.aspx'
Afterwards a simple „Login-Page“ appears – after one click on „login“ you should see something 'you are signed in'
That's it! were done here. Thank you for reading!