Troubleshooting ADFS Azure MFA Adapter
Overview
Recently, I successfully deployed the ADFS Azure MFA adapter in my own ADFS farm following the documentation provided by Microsoft Learn titled “Configure AD FS and Azure AD Multi-Factor Authentication.”
Configure AD FS and Azure AD Multi-Factor Authentication | Microsoft Learn
However, I must admit that the deployment process was not entirely straightforward. Along the way, I encountered various errors that required troubleshooting. Fortunately, I was able to resolve all the issues and, in the process, I gained valuable troubleshooting skills. In this post, I would like to share some troubleshooting guidance based on my experience, with the hope that it will be helpful to others facing similar challenges.
1. Configuration
The configuration process itself is quite straightforward. To create a self-signed certificate, we can use the following command:
$certbase64 = New-AdfsAzureMfaTenantCertificate -TenantID <tenantID>
If we echo the value of $certbase64
, we will see the base64 representation of the certificate in text format.
Later, we need to bind the public key of this self-signed certificate to the Azure Multi-Factor Auth Client using the following command:
New-MsolServicePrincipalCredential -AppPrincipalId 981f26a1-7f43-403b-a875-f8b09b8cd720 -Type asymmetric -Usage verify -Value $certBase64
To check all the certificates bound to this service principal, you can use the following command:
get-MsolServicePrincipalCredential -AppPrincipalId 981f26a1-7f43-403b-a875-f8b09b8cd720
2. Troubleshooting
2.1 System.Net.WebException: The remote server returned an error: (401) Unauthorized
After performing the configuration steps outlined in the documentation, I encountered the following error in the ADFS debug log:
System.Exception: Exception calling SAS. —> System.Net.WebException: The remote server returned an error: (401) Unauthorized. at System.Net.HttpWebRequest.GetResponse() at Microsoft.IdentityServer.Aad.Sas.HttpClientHelper.PostXml
Upon further investigation, I discovered that the issue might be related to missing StrongCrypto for the .NET Framework. To resolve this problem, I followed the steps below:
Step 1: I ran the following command on all ADFS servers to configure the .NET Framework for StrongCrypto:
New-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -name 'SchUseStrongCrypto' -value '1' -PropertyType 'DWord' -Force | Out-Null
Step 2: I rebooted the ADFS servers to ensure that the Strong Crypto configuration took effect. After this, I no longer encountered the 401 error.
By following these steps, I was able to resolve the issue and eliminate the 401 Unauthorized error.
2.2 System.Security.Cryptography.CryptographicException: Keyset does not exist at System.
Unfortunately, I encountered a new issue after following Step 2.1, and I had limited knowledge about how to address it. However, an idea struck me that the problem could be related to the keyset, considering the presence of various AsymmetricSecurityKey and .X509 fields in the error message:
System.Exception: Exception calling SAS. —> System.AggregateException: One or more errors occurred. —> System.Security.Cryptography.CryptographicException: Keyset does not exist at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() at System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPrivateKey(X509Certificate2 certificate) at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.get_PrivateKey() at System.IdentityModel.Tokens.X509AsymmetricSecurityKey.GetAsymmetricAlgorithm(String algorithm, Boolean privateKey) at Microsoft.IdentityServer.Aad.Sas.Adal.Net.Internal.Platform.CryptographyHelper.SignWithCertificate(String message, X509Certificate2 certificate)
Recalling the process of establishing trust between the Web Application Proxy (WAP) and ADFS, I remembered that granting the service account permission to manage the private key of the self-signed certificate was necessary. The error I encountered seemed to be similar to this scenario.
I decided to grant my ADFS service account the permission to manage the private key of the self-signed certificate.
Fortunately, this resolved the “Keyset” issue. However, I encountered another problem once more…
2.3 Microsoft.IdentityServer.Aad.Sas.Adal.Net.AdalServiceException: AADSTS700027: The certificate with identifier used to sign the client assertion is not registered on application.
But I haven’t given up; this is an AADSTS issue, and I’m almost there, on the verge of victory.
During this troubleshooting phase, I utilized Fiddler to capture the behavior of the MFA adapter. I used PsTool to trace the HTTP requests under the context of the adfssvc account.
In my previous post, I shared how to use PsTool for remote application troubleshooting. You can find detailed instructions in the following article:
Execute Processes Remotely with PsExec Tool – Ruian’s Tech Troubleshooting Toolbox (ruianding.com)
Based on the Fiddler trace, I discovered that when authenticating against login.microsoftonline.com, the server returned the following error message:
The key was not found., Thumbprint of key used by client: ‘F435FB87FEFE54A99DEA82FBFF306541A78D01F8’, Please visit the Azure Portal, Graph Explorer or directly use MS Graph to see configured keys for app Id ‘981f26a1-7f43-403b-a875-f8b09b8cd720’
Upon further investigation, I realized that I had accidentally created the self-signed certificate twice. The latest bound certificate had a thumbprint of ’98B5EB6D760630C843403321A3AA0F714351449D’, while my ADFS was using ‘F435FB87FEFE54A99DEA82FBFF306541A78D01F8’. To resolve this, I ran the following command:
New-MsolServicePrincipalCredential -AppPrincipalId 981f26a1-7f43-403b-a875-f8b09b8cd720 -Type asymmetric -Usage verify -Value $certBase64
I bound the public key of ‘F435FB87FEFE54A99DEA82FBFF306541A78D01F8’ to the service principal. Finally, the issue was resolved.
Lastly, I tested sign-in on my ADFS dummy page, and the expected number matching successfully popped up.