Just a quick post on something I ran into while playing around with AD FS on Windows Server 2016 technical preview 5 (TP5).
Configuration
- Azure MFA has been configured and enabled as a MFA provider in the global authentication policy
- You may have optionally enabled this as a specific authentication method for the extranet.
Symptoms
You enter your UPN and press tab to enter the corresponding code from the Azure Authenticator app. But you are not given a chance to enter the code and you get the standard error page with a correlation ID etc.
AD FS event log reports an event like so with the stack as indicated.
Here is a link to a text file with event details.
Log Name: AD FS/Admin
Source: AD FS
Date: 5/17/2016 4:48:48 PM
Event ID: 364
Task Category: None
Level: Error
Keywords: AD FS
User: contoso\adfssvc$
Computer: mwgvm2.contoso.com
Description:
Encountered error during federation passive request.
Additional Data
Protocol Name:
wsfed
Relying Party:
https://contoso.onmicrosoft.com/WebApplication1
Exception details:
System.Exception: Exception calling SAS. —> System.Security.Cryptography.CryptographicException: Keyset does not exist
at Microsoft.IdentityServer.Aad.Sas.Adal.Net.AuthenticationContext.RunAsyncTask[T](Task`1 task)
at Microsoft.IdentityServer.Aad.Sas.RealSasProvider.ModifyHttpRequest(HttpWebRequest request)
at Microsoft.IdentityServer.Aad.Sas.HttpClientHelper.PostXml[TRequest,TResponse](String url, TRequest request, Action`1 httpRequestModifier)
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.ProcessUsernameOathCodePin(IAuthenticationContext authContext, IProofData proofData, Claim[]& outgoingClaims)
— End of inner exception stack trace —
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.ProcessUsernameOathCodePin(IAuthenticationContext authContext, IProofData proofData, Claim[]& outgoingClaims)
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, Claim[]& outgoingClaims)
at Microsoft.IdentityServer.Web.Authentication.External.ExternalAuthenticationHandlerBase.TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, Claim[]& adapterClaims)
at Microsoft.IdentityServer.Web.Authentication.Azure.AzurePrimaryAuthenticationHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.Authentication.AuthenticationOptionsHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
System.Security.Cryptography.CryptographicException: Keyset does not exist
at Microsoft.IdentityServer.Aad.Sas.Adal.Net.AuthenticationContext.RunAsyncTask[T](Task`1 task)
at Microsoft.IdentityServer.Aad.Sas.RealSasProvider.ModifyHttpRequest(HttpWebRequest request)
at Microsoft.IdentityServer.Aad.Sas.HttpClientHelper.PostXml[TRequest,TResponse](String url, TRequest request, Action`1 httpRequestModifier)
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.ProcessUsernameOathCodePin(IAuthenticationContext authContext, IProofData proofData, Claim[]& outgoingClaims)
Event Xml:
<Event xmlns=”http://schemas.microsoft.com/win/2004/08/events/event”>
<System>
<Provider Name=”AD FS” Guid=”{2FFB687A-1571-4ACE-8550-47AB5CCAE2BC}” />
<EventID>364</EventID>
<Version>0</Version>
<Level>2</Level>
<Task>0</Task>
<Opcode>0</Opcode>
<Keywords>0x8000000000000001</Keywords>
<TimeCreated SystemTime=”2016-05-17T16:48:48.786392500Z” />
<EventRecordID>260</EventRecordID>
<Correlation ActivityID=”{00000000-0000-0000-2400-0080000000CC}” />
<Execution ProcessID=”10012″ ThreadID=”10216″ />
<Channel>AD FS/Admin</Channel>
<Computer>mwgvm2.contoso.com</Computer>
<Security UserID=”S-1-5-21-875482985-643924731-3949700923-1103″ />
</System>
<UserData>
<Event xmlns=”http://schemas.microsoft.com/ActiveDirectoryFederationServices/2.0/Events”>
<EventData>
<Data>wsfed</Data>
<Data>https://contoso.onmicrosoft.com/WebApplication1</Data>
<Data>System.Exception: Exception calling SAS. —> System.Security.Cryptography.CryptographicException: Keyset does not exist
at Microsoft.IdentityServer.Aad.Sas.Adal.Net.AuthenticationContext.RunAsyncTask[T](Task`1 task)
at Microsoft.IdentityServer.Aad.Sas.RealSasProvider.ModifyHttpRequest(HttpWebRequest request)
at Microsoft.IdentityServer.Aad.Sas.HttpClientHelper.PostXml[TRequest,TResponse](String url, TRequest request, Action`1 httpRequestModifier)
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.ProcessUsernameOathCodePin(IAuthenticationContext authContext, IProofData proofData, Claim[]& outgoingClaims)
— End of inner exception stack trace —
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.ProcessUsernameOathCodePin(IAuthenticationContext authContext, IProofData proofData, Claim[]& outgoingClaims)
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, Claim[]& outgoingClaims)
at Microsoft.IdentityServer.Web.Authentication.External.ExternalAuthenticationHandlerBase.TryEndAuthentication(IAuthenticationContext authContext, IProofData proofData, HttpListenerRequest request, Claim[]& adapterClaims)
at Microsoft.IdentityServer.Web.Authentication.Azure.AzurePrimaryAuthenticationHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.Authentication.AuthenticationOptionsHandler.Process(ProtocolContext context)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
System.Security.Cryptography.CryptographicException: Keyset does not exist
at Microsoft.IdentityServer.Aad.Sas.Adal.Net.AuthenticationContext.RunAsyncTask[T](Task`1 task)
at Microsoft.IdentityServer.Aad.Sas.RealSasProvider.ModifyHttpRequest(HttpWebRequest request)
at Microsoft.IdentityServer.Aad.Sas.HttpClientHelper.PostXml[TRequest,TResponse](String url, TRequest request, Action`1 httpRequestModifier)
at Microsoft.IdentityServer.Adapter.AzureMfa.PrimaryAuthenticationAdapter.ProcessUsernameOathCodePin(IAuthenticationContext authContext, IProofData proofData, Claim[]& outgoingClaims)
</Data>
</EventData>
</Event>
</UserData>
</Event>
Cause
The AD FS service account has no access to the private key corresponding to the cert used to communicate with Azure MFA service.
Resolution
- Use procmon from sysinternals to track file activity to paths beginning with “C:\ProgramData\Application Data\microsoft\crypto\RSA\MachineKeys”. You may choose to filter the procmon so you only see the activity of interest.
- note the “access denied” result returned for files accessed by the adfssrv service process (Microsoft.IdentityServer.ServiceHost.exe).
- Grant read-only permissions to the “NT SERVICE\adfssrv” service SID.