Recently, while helping a client deploy a wsHttpBinding Windows Communication Foundation web service configured with message security, we encountered the following error: “The profile for the user is a temporary profile.” As is sometimes the case with WCF certificate security issues, the initial error message’s description did not come close to describing the actual problem.
In the exception chain below, the second exception clued me that the problem might have to do with the web service lacking the right to read the service certificate’s private key. We tried giving the web service’s account read rights to the private key by using the Certificate MMC snap-in and via findprivatekey.exe/cals.exe. In both cases, no go—the problem remained.
[CryptographicException: The profile for the user is a temporary profile. ] System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer) +450 System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) +158 System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() +231 System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() +537 System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +78 [ArgumentException: It is likely that certificate 'E=someone@example, CN=Some Name, OU=Some OU, O=Some Company, L=Some Location, S=Some State, C=US' may not have a private key that is capable of key exchange or the process may not have access rights for the private key. Please see inner exception for detail.] System.ServiceModel.Security.SecurityUtils.EnsureCertificateCanDoKeyExchange(X509Certificate2 certificate) +16621133 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateLocalSecurityTokenProvider(RecipientServiceModelSecurityTokenRequirement recipientRequirement) +94 System.ServiceModel.Security.ServiceCredentialsSecurityTokenManager.CreateSecurityTokenProvider(SecurityTokenRequirement requirement) +50 System.ServiceModel.Security.SymmetricSecurityProtocolFactory.OnOpen(TimeSpan timeout) +180 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789 System.ServiceModel.Security.SecurityListenerSettingsLifetimeManager.Open(TimeSpan timeout) +81 System.ServiceModel.Channels.SecurityChannelListener`1.OnOpen(TimeSpan timeout) +398 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789 System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpen(TimeSpan timeout) +283 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789 System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout) +126 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) +789 System.ServiceModel.HostingManager.ActivateService(String normalizedVirtualPath) +255 System.ServiceModel.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath) +1172 [ServiceActivationException: The service '/service.svc' cannot be activated due to an exception during compilation. The exception message is: It is likely that certificate 'E=someone@example, CN=Some Name, OU=Some OU, O=Some Company, L=Some Location, S=Some State, C=US' may not have a private key that is capable of key exchange or the process may not have access rights for the private key. Please see inner exception for detail..] System.Runtime.AsyncResult.End(IAsyncResult result) +901424 System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result) +178638 System.Web.AsyncEventExecutionStep.OnAsyncEventCompletion(IAsyncResult ar) +107
Then it occurred to me that there might be a problem with how the certificate was installed on the server. The certificate had been installed by double-clicking on the certificate file. By default, this process places the certificate in the current user’s certificate store. As the certificate was for a service, it needed to be moved into the machine store so it had been dragged into the correct store (in MMC).
FindPrivateKey.exe revealed that the private key file was still located under the installing user’s user profile directory. Dragging the certificate between stores in MMC didn’t move the private key to the machine store’s directory.
Ah! The solution was simple: install the certificate directly into the machine store. In MMC, we deleted the certificate then imported it directly into the machine store. After giving the WCF service’s account read rights to the private key, the error was resolved!