CryptographicException when loading certificate for client side TLS authentication - iis

While attempting a https request from our web application (which runs on IIS, using .NET Framework 4.6.1) with TLS client certificate based authentication, we get the following error when loading the client certificate:
System.Security.Cryptography.CryptographicException: The requested operation cannot be completed. The computer must be trusted for delegation and the current user account must be configured to allow delegation.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Utils.LoadCertFromFile(String fileName, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password)
This happens both when loading it from file and loading it from byte array. I already tried to import the p12 file in the local machine certificate, and granting rights to the app pool user on which the web app is running, but this did not fix the issue.
The server runs on Windows Server 2012 R2 and uses active directory for user management. The web app is running on the builtin ApplicationPoolIdentity.

Related

AAD-Integrated Authentication with Azure Active Directory fails

We have an ADFS setup completed on one of our Azure virtual machine, and we have one Sql managed Instance created in azure portal.
We have federated our domain and successfully connected with 'Sql managed Instance' via AAD-Integrated authentication from SSMS.
Our problem is that when we try to connect this Sql managed Instance from our IIS application with AAD-Integrated authentication method
(string ConnectionString = #"Data Source=XXXXXXXXX; Authentication=Active Directory Integrated; Initial Catalog=testdb;")
, we get the following error on screen:
Message - > One or more errors occurred. Inner Exception -> System.AggregateException: One or more errors occurred. ---> AdalException: MSIS7069: The specified request failed. at ADALNativeWrapper.ADALGetAccessToken(String username, IntPtr password, String stsURL, String servicePrincipalName, ValueType correlationId, String clientId, Boolean* fWindowsIntegrated, Int64& fileTime) at System.Data.SqlClient.ActiveDirectoryNativeAuthenticationProvider.<>c__DisplayClass2_0.b__0() at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute() --- End of inner exception stack trace --- at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Data.SqlClient.SqlInternalConnectionTds.<>c__DisplayClass134_1.b__0() at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute() ---> (Inner Exception #0) AdalException: MSIS7069: The specified request failed. at ADALNativeWrapper.ADALGetAccessToken(String username, IntPtr password, String stsURL, String servicePrincipalName, ValueType correlationId, String clientId, Boolean* fWindowsIntegrated, Int64& fileTime) at System.Data.SqlClient.ActiveDirectoryNativeAuthenticationProvider.<>c__DisplayClass2_0.b__0() at System.Threading.Tasks.Task`1.InnerInvoke() at System.Threading.Tasks.Task.Execute()<---
Also we checked into ADFS logged issues and got the following error logged as follows:
Log Name: AD FS/Admin
Source: AD FS
Date: 7/29/2021 12:26:45 PM
Event ID: 111
Task Category: None
Level: Error
Keywords: AD FS
User: Domain\testuser
Computer: Name of our adfs server(Not mentioned the exact name due to sensitive data)
Description:
The Federation Service encountered an error while processing the WS-Trust request.
Request type: http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
Additional Data
Exception details:
Microsoft.IdentityServer.Service.SecurityTokenService.ADAccountValidationException: MSIS3173: Active Directory account validation failed. ---> Microsoft.IdentityServer.ClaimsPolicy.Engine.AttributeStore.Ldap.AttributeStoreDSGetDCFailedException: Exception of type 'Microsoft.IdentityServer.ClaimsPolicy.Engine.AttributeStore.Ldap.AttributeStoreDSGetDCFailedException' was thrown.
Are we missing anything in the whole process?
Edit1:
I have one confusion regarding federated domain. The domain which we are using in our client machine, has to be primary domain in our Azure active directory OR can it be just in custom domain list in Azure active directory?
Edit2:
Finally, we were successful in connecting to our IIS application via AAD-Integrated authentication. We just changed our application pool's identity from ApplicationPoolIdentity(default option) to our domain user and voila, it worked like a charm. Hope somebody can get benefited from this.

SAML binding: Error getting X509Certificate2.PrivateKey on Azure

The ITFoxtec Identity SAML 2.0 library contains a function to bind the request that extracts private key from signing certificate.
if(certificate is Saml2X509Certificate)
{
return (certificate as Saml2X509Certificate).GetRSAPrivateKey();
}
else
{
return certificate.GetRSAPrivateKey();
}
It works on local machine but on azure, it is giving the following error.
System.Security.Cryptography.CryptographicException: Invalid provider type specified.
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 ITfoxtec.Identity.Saml2.X509Certificate2Extensions.GetSamlRSAPrivateKey(X509Certificate2 certificate)
at ITfoxtec.Identity.Saml2.Saml2Binding1.BindInternal(Saml2Request saml2RequestResponse)
at ITfoxtec.Identity.Saml2.Saml2RedirectBinding.BindInternal(Saml2Request saml2RequestResponse, String messageName)
at ITfoxtec.Identity.Saml2.Saml2Binding1.Bind(Saml2Request saml2Request) .
Not sure whether it is saml library issue or azure configuration issue since it works on local machine.
I am using the certificate provided in the test webapp example. So, it doesn't look corrupted.
Does anyone know the reason behind this?
If you are using an Azure App Service, maybe the problem is that you need to make the SSL/TLS certificates private key accessible for your web application.
Adding an app setting named WEBSITE_LOAD_CERTIFICATES with its value set to the thumbprint of the certificate will make it accessible to your web application.

SharePoint 2013 Forms Based Authentication is Slow– Why does SetPrincipalAndWriteSessionToken take 20 seconds or more?

We have a SharePoint implementation in which our web application is using Forms Based Authentication(FBA).
There are 2 servers in the farm. A web front end server that resides in a DMZ and a SQL server within the corporate network. A firewall separates them.
We are using SQL Authentication.
We need to force the user to change their password after the first successful login. Therefore we created a custom signin form for FBA based on the following article.
(https://sharepoint.stackexchange.com/questions/42541/how-to-create-a-custom-fba-login-page-that-forces-user-to-change-password-and-vi).
The code in question is:
private void SignInUser()
{
SecurityToken token = SPSecurityContext.SecurityTokenForFormsAuthentication
(new Uri(SPContext.Current.Web.Url),
GetMembershipProvider(SPContext.Current.Site),
GetRoleProvider(SPContext.Current.Site),
_userName,
_password, SPFormsAuthenticationOption.None);
SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;
fam.SetPrincipalAndWriteSessionToken(token, SPSessionTokenWriteType.WriteSessionCookie);
SPUtility.Redirect(System.Web.Security.FormsAuthentication.DefaultUrl,
SPRedirectFlags.UseSource, this.Context);
}
public static string GetMembershipProvider(SPSite site)
{
// get membership provider of whichever zone in the web app fba isenabled
SPIisSettings settings = GetFbaIisSettings(site);
if (settings == null) return null;
return settings.FormsClaimsAuthenticationProvider.MembershipProvider;
}
public static string GetMembershipProvider(SPSite site)
{
// get membership provider of whichever zone in the web app is fba enabled
SPIisSettings settings = GetFbaIisSettings(site);
if (settings == null) return null;
return settings.FormsClaimsAuthenticationProvider.MembershipProvider;
}
The code which takes the time is:
fam.SetPrincipalAndWriteSessionToken(token, SPSessionTokenWriteType.WriteSessionCookie);
From my understanding this line of code does the following:
Invokes the OnSessionSecurityTokenCreated method to raise the
SessionSecurityTokenCreated event
Invokes the AuthenticateSessionSecurityToken method on SPFederationAuthenticationModule.Current to set the thread principal and then write the session cookie.
Some other points to note are:
This 20 second login time also occurs for the default sharepoint fba page (/_forms/default.aspx)
It does not occur on a standalone dev machine.
For me this would indicate the bottleneck is network related.
Any help would be much appreciated.
I managed to shave about 13 seconds off the login process by resolving the following ULS log entry.
3/30/2016 11:08:53.71 w3wp.exe (0x2448) 0x1148 SharePoint Foundation Topology 8321 Critical A certificate validation operation took 23141.9482 milliseconds and has exceeded the execution time threshold. If this continues to occur, it may represent a configuration issue. Please see http://go.microsoft.com/fwlink/?LinkId=246987 for more details. bc926d9d-52af-f0fb-b2ae-236a27cd54f1
So, SharePoint uses certificates to sign security tokens that are issued by the Security Token Service (STS). Like all certificates, the validity of the STS certificate has to be verified periodically to make sure that the certificate has not been revoked. By default, the root certificate in the chain is not added to the Trusted Root Certificate Authorities store of the SharePoint servers. Because of this, the certificate revocation list (CRL) check for the certificate is performed over the Internet which is not possible on our WFE server.
I resolved this by exporting the root cert, on the WFE server, using
$rootCert = (Get-SPCertificateAuthority).RootCertificate
$rootCert.Export("Cert") | Set-Content C:\SharePointRootAuthority.cer -Encoding byte
And then importing the cert into the Trusted Root Certification Authorities store using the certificates mmc snapin.

Will a Windows Store app always disallow a self-signed certificate even if explicitly trusted?

I've seen both this and this — same problem, different question.
I'm trying to connect my Windows 8.1 Store app to an ASP.NET Web API web service, secured over HTTPS using a self-signed certificate. It's a proof-of-concept application that will end up on < 5 different machines and seen only internally, so I was planning to just install the certificate as trusted on each of the target machines.
When I try this on my development setup, both HttpClient APIs fail to establish the trust relationship when calling the service.
Windows.Web.Http.HttpClient exception: "The certificate authority is invalid or incorrect"
System.Net.Http.HttpClient exception: "The remote certificate is invalid according to the validation procedure."
My self-signed certificate (public-key-only .cer version) is installed in both the "User" and "Local Machine" Trusted Root Certification Authorities on the client. I'm really surprised that this isn't enough to get WinRT to trust it. Is there something I'm missing, or is there just no way to set up the trust relationship for a self-signed SSL certificate that will make HttpClient happy?
Details on my setup:
ASP.NET Web API
Azure web role running in Azure emulator
Cert issuer: 127.0.0.1
Cert subject: 127.0.0.1
Cert key: 2048-bit
Windows 8.1 Store application
Certificate (.cer file with public key only) installed in User\Trusted Root Certification Authorities
Certificate (.cer file with public key only) installed in Local Machine\Trusted Root Certification Authorities
Certificate (.cer file with public key only) added to Windows Store app manifest under "CA"
I am not asking for a workaround to configure HttpClient to accept self-signed or invalid certificates in general — I just want to configure a trust relationship with THIS one. Is this possible?
You should be able to find out what is the problem with the certificate by doing a request like this:
// using Windows.Web.Http;
private async void Foo()
{
HttpRequestMessage request = null;
try
{
request = new HttpRequestMessage(
HttpMethod.Get,
new Uri("https://localhost"));
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.SendRequestAsync(request);
}
catch (Exception ex)
{
// Something like: 'Untrusted, InvalidName, RevocationFailure'
Debug.WriteLine(String.Join(
", ",
request.TransportInformation.ServerCertificateErrors));
}
}
Using a HttpBaseProtocolFilter you can ignore certificate errors:
// using Windows.Web.Http;
// using Windows.Web.Http.Filters;
// using Windows.Security.Cryptography.Certificates;;
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.InvalidName);
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.RevocationFailure);
HttpClient client = new HttpClient(filter);
HttpResponseMessage response = await client.SendRequestAsync(request);
The piece I was missing turned out to be that the certificate wasn't in the list of of IIS Server Certificates on my local machine!
Opening IIS Manager and checking out the Server Certificates section, I did find a 127.0.0.1 SSL certificate already set up by the Azure emulator:
CN = 127.0.0.1
O = TESTING ONLY
OU = Windows Azure DevFabric
However, my own self-signed certificate that I made outside of IIS, also with CN=127.0.0.1, was not in the list. I imported it, and now my Windows Store app's HttpClient connects happily (certificate warnings went away in Chrome and IE as well!)
If anyone can firm up the technical details on this, please comment — this fix feels a bit magical and I'm not sure I can pinpoint precisely why this worked. Possibly some confusion on my part between the two certs for 127.0.0.1, even though the thumbprint I had configured in my Azure project was always the one I was intending to use?

HttpRequest with Certificate fails in Azure Web-role

On my deployed azure web-role I try to send a request (GET) to a Web-Server that authorizes the request by the provided certificate of the requesting client.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
var filepath = Path.GetTempPath();
string certpath = Path.Combine(filepath, "somecert.cer");
Trc.Information(string.Format("Certificate at {0} will be used", certpath));
X509Certificate cert = X509Certificate.CreateFromCertFile(certpath);
WebRequest request = WebRequest.Create(endPoint);
((HttpWebRequest)request).ProtocolVersion = HttpVersion.Version10;
((HttpWebRequest)request).IfModifiedSince = DateTime.Now;
((HttpWebRequest)request).AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
((HttpWebRequest)request).ClientCertificates.Add(cert);
The above code works perfectly in the azure-emulator but not when it is deployed. Then the call to GetResponse fails always.
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.GetResponse()
at XYZ.Import.DataImport.OpenResponseStream(String endPoint)
I read through many of the existing discussion threads where using SecurityProtocolType.Ssl3 solved the problem but it does not in my case. Are there further debugging options considering that it is running on azure?
Update1
I tried all debugging steps that were suggested by Alexey. They are really helpfull but quite hard to execute properly on azure.
Here is with what I came up with after at least two hours.
I used the System.Net settings supplied by this post [1].
At first the output was not present in the expected folder. The file system settings on the folder need to be tweaked. Therefore the NT AUTHORITY\NETWORK SERVICE account should be allowed on the target folder.
After that the file didn't show up as expected because there seems to be a problem when only a app.config is supplied. See this thread [2]. So I provided a app.config a [ProjectAssembly].dll.config and a web.config with the content from the post [1].
To test if the Problem is related to User rights I tested with elevated rights and without like shown in post [3].
In advance I changed the Test-Project to execute in two modes. The first mode tries to load the public part in the *.cer file like shown in the code above.
The other version uses the private certificate that is loaded with this command
X509Certificate cert = new X509Certificate2(certpath, "MYPASSWORD", X509KeyStorageFlags.MachineKeySet);
As a result I gained the following insights.
When using the public part (.cer) it only works when the rights are elevated and the private cert is imported into the machine store
When using the private (.pfx) it only works if the private cert is imported into the machine store
The second setup with (.pfx) runs even without elevated rights
While debugging the CAPI2 log only had informations that had no direct relevance. The System.Net diagnostics from point one above contained this.
System.Net Information: 0 : [1756] SecureChannel#50346327 - Cannot find the certificate in either the LocalMachine store or the CurrentUser store.
[snip]
System.Net Error: 0 : [1756] Exception in HttpWebRequest#36963566:: - The request was aborted: Could not create SSL/TLS secure channel..
System.Net Error: 0 : [1756] Exception in HttpWebRequest#36963566::GetResponse - The request was aborted: Could not create SSL/TLS secure channel..
From this output and the changing situation when the elevated rights are used I would deduce that I should look further into the rights of the running web-role in combination with the certificate store.
[1] http://msdn.microsoft.com/de-de/library/ty48b824(v=vs.110).aspx
[2] Combined Azure web role and worker role project not seeing app.config when deployed
[3] http://blogs.msdn.com/b/farida/archive/2012/05/01/run-the-azure-worker-role-in-elevated-mode-to-register-httplistener.aspx
Remove SecurityProtocolType.Ssl3
Turn on CAPI2 log and check it for errors (on your local machine).
If there isn't error, then check location of CA and intermediate certificates.
Turn on system.net diagnostics and check this log for errors.
In this article describes how to find and turn on CAPI2 eventlog.
Hope this help.

Resources