Certificate validation failed - asp.net

Actors
-Asp.net site - Client
-Wcf services - Server
Both applications runs on IIS-7.
I want to make integration test between the two applications. The client access the Server through 'https'.
I have created a certificate and assigned it to the server. I also added the certificate to the 'Trusted Root Certification Authorities' to be considered a valid certificate. When I 'hit' the server's services through my browser (IE, chrome...) the certificate appears to be valid. But when my client application tries to access the server then I get the following error:
Could not establish trust relationship for the SSL/TLS secure channel with authority **** --->
The remote certificate is invalid according to the validation procedure.
Is there any way to skip the validation procedure or to make the certificate valid for my client application?
Just to know:
1. I cannot purchase a certificate because I will only use it for testing purposes.
2. I cannot make any changes on any of the application's code (server-client)

I finally managed to figured it out.
The problem was a previous (expired) certificate with the same name that was already added to the 'Trusted Root Certification Authorities'. Every time I was installing my new certificate through the 'Certificate Import Wizard' (or through MMC) the wizard informed me that it was successfully added. However, it was keeping the instance of the previous certificate without overwriting it.

Modify the validation callback to always return true:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, policyErrors) => true;
Or does that violate the 'no changes to code' condition?

How did you install the certificate into your trusted root store?
If you went through a browser to do it, most likely you only added it to the current user. Try adding it through the MMC snap-in for the Local Computer Account instead; this is where we install our self-signed IIS Express certificates and WCF seems happy with them.

Related

Finding expired ssl certificate used by my website in local development

I have a set of web application and projects which I used to test OAuth2 login flows by using Identity Server 4. This is about 2 years old project and I update it regularly to use latest .Net Core or IdentityServer4 packages.
When I tried to open it yesterday, I got the warning message saying my ssl certificate is expired on 21st Dec 2021.
It makes sense and I opened Certificate Management Stores for both Local Machine and Current User. I found the expired certificate and I removed them from both Personal and Trusted Root Certification Authorities.
Then, I executed "dotnet dev-certs https --trust" command to execute a new cert and install it to my stores. The new certificate with expiry date 07/01/2023 is added and I copied to
Trusted Root Certification Authorities too.
I tried to open my Idsrv and Web Application again for testing.
My Web Application is using the newly added certificate correctly.
But my Idsrv4 project is still using the expired certificate which I already deleted. I couldn't find anywhere in the Certificate Store. I used Find feature in MMC Consoles and I found only the new certificate with 2023 Expiry Date.
I cleaned my solution multiple time. Deleted both bin and obj folders. Tried different browsers and the certificate error is still there.
My set up for Idsrv is simple and standard:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.GetUsers())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryClients(Config.GetClients())
.AddProfileService<ProfileService>();
Here is Configure method:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;
app.UseRequestLocalization(localizationOptions);
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Could you please help me how I can force my Identity Server 4 project to use the newly generated certificate? Or where I can find and remove that old expired certificate?
I guess there is a difference when you run kestrel directly, or when you run it through IIS-Express. Try with Kestrel directly?
Otherwise, look at this article that might help you:
How to Change the HTTPS Certificate in IIS Express
I found the root cause of the problem. I'm using Kestrel to run the app and it's due to the Kestrel:Certificates:DevelopmentPassword value in the secrets file.
Because of that setting, it's still linked to the expired certificate which must be somewhere in my machine. Just by deleting this line and my web app starts using the correct ssl certificate.
Updating HTTPS Certificate IIS Express or using Jexus Manager also helps the problem (does not solve completely). But it solves the issue only when you are using IISExpress. If you start your web app with Project setting, IISExpress ssl configs are not used.

Disable client certificate validation in IIS 10 for an Asp.net website but allow app to request incoming client certificate

I have an Asp.net API website which does custom client certificate validation. When hosting this website on IIS 10, I get the following from failed request logs when I call my API.
A certificate chain processed, but terminated in a root certificate
which is not trusted by the trust provider.
My web.config has
<configuration>
<system.webServer>
<access sslFlags="Ssl, SslRequireCert" />
</system.webServer>
and in applicationHost.config I have
<section name="access" overrideModeDefault="Allow" />
What am I missing here? How do I configure IIS to just pass through the certificate and not validate it ?
The reason I want to do this is because, this is a test environment and I want to trust all clients who calls my API with their self-signed certificates. I will internal do the validation of the certificate inside my API.
Note: I hosted the same website on Azure AppService and set "Incoming client certificates" to ON. It worked like a charm. So, what is the difference when I host it on my machine IIS ?
We use Client Certificates to validate hardware devices connecting to our API. For context, our devices are provisioned with an SSL cert at manufacture, and that cert is self signed by us. When a device out in the wild attempts to connect to our API, we handle the client certificate validation within the .NET API application itself.
This requires the following IIS SSL settings, and also a manual step to rebind the SSL binding (which we do for a very specific technical limitation).
So firstly, within the web.config file we have this config:
<security>
<access sslFlags="Ssl" />
</security>
If we add the SslNegotiateCert or SslRequireCert sslFlags, then IIS attempts to validate the client certificate before our application code is even called. So we set only the Ssl flag.
Secondly, in the SSL settings of the IIS site we set:
Require SSL [x]
Client Certificate:
[x] Ignore
[ ] Accept
[ ] Require
So essentially we aren't asking IIS to negotiate the client certificates on our behalf.
The final configuration change we make is to Enable "Negotiate Client Certificate" on the SSL binding. By default, when you create an SSL binding in IIS the "Negotiate Client Certificate" property is set to false.
From my understanding this means that IIS will not negotiate client certificates on the initial TLS negotiation. What would happen is when client certificates are required, a TLS renegotiation is triggered, and the server would request a client certificate from the client.
In our case, our devices pass the client certificate on the initial request, and will not handle a TLS renegotiation. So, by Enabling "Negotiate Client Certificate" then client certificates can be passed in the initial request.
So rebind the SSL binding takes some command line magic to find the current binding, delete it, and readd the binding this time with "Negotiate Client Certificate" enabled.
Step 1 - Find your SSL binding:
Run the following command in a CMD terminal:
netsh http show sslcert > sslcerts.txt
This will push all details of your current SSL bindings into sslcerts.txt
The file will looks like the following:
SSL Certificate bindings:
Hostname:port : yourhostname:443
Certificate Hash : your_certificate_hash
Application ID : {your_applicationID_Guid}
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 : Disabled
Note, your sslcerts.txt file will contain many instances of these bindings. You need to find the correct one for the application/site you are working with.
Note also the above output shows "Negotiate Client Certificate : Disabled"
Step 2 - Delete the current binding
Run the following command to delete the current binding
netsh http delete sslcert hostnameport=yourhostname:443
This will delete the SSL binding for the site.
Step 3 - Rebind the SSL with "Negotiate Client Certificate" enabled
Run the following command at the CMD prompt:
netsh http add sslcert hostnameport=yourhostname:443 certhash=your_certificate_hash appid={your_applicationID_Guid} certstorename=MY verifyclientcertrevocation=Enable VerifyRevocationWithCachedClientCertOnly=Disable UsageCheck=Enable clientcertnegotiation=Enable
Note here you are filling in the properties of the binding from the details you retrieved in sslcerts.txt, except you are setting clientcertnegotiation=Enable
Now we have an IIS Application which will negotiate for a client certificate up front, but it will not validate it, and allow us to validate it in code.
We then use an AuthorizationFilterAttribute to grab the client certificate and validate it based on our rules.
public class ValidateDeviceClientCertificateAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
X509Certificate2 cert = actionContext.Request.GetClientCertificate();
// Validation rules here i.e. check Hash of the signing cert, does it match your accepted value?
}
}
In our validation we have a known Intermediate CA that we use to sign our device certificates, so we check to ensure that the client certificate was signed by that Intermediate Cert, or at least one of our device signing intermediate certificates.

IIS 7 Error "A specified logon session does not exist. It may already have been terminated." when using https

I am trying to create Client Certificates Authentication for my asp.net Website.
In order to create client certificates, I need to create a Certificate Authority first:
makecert.exe -r -n “CN=My Personal CA” -pe -sv MyPersonalCA.pvk -a
sha1 -len 2048 -b 01/01/2013 -e 01/01/2023 -cy authority
MyPersonalCA.cer
Then, I have to import it to IIS 7, but since it accepts the .pfx format, i convert it first
pvk2pfx.exe -pvk MyPersonalCA.pvk -spc MyPersonalCA.cer -pfx MyPersonalCA.pfx
After importing MyPersonalCA.pfx, I try to add the https site binding to my Web Site and choose the above as SSL Certificate, but I get the following error:
Any suggestions?
I ran across this same issue, but fixed it a different way. I believe the account I was using changed from the time I initially attempted to set up the certificate to the time where I returned to finish the work, thus creating the issue. What the issue is, I don't know, but I suspect it has to do with some sort of hash from the current user and that is inconsistent in some scenarios as the user is modified or recreated, etc.
To fix it, I ripped out of both IIS and the Certificates snap-in (for Current User and Local Computer) all references of the certificate in question:
Next, I imported the *.pfx file into the certs snap-in in MMC, placing it in the Local Computer\Personal node:
Right-click the Certificates node under Personal (under Local Computer as the root)
All Tasks -> Import
Go through the Wizard to import your *.pfx
From that point, I was able to return to IIS and find it in the Server Certificates. Finally, I went to my site, edited the bindings and selected the correct certificate. It worked because the user was consistent throughout the process.
To the point mentioned in another answer, you shouldn't have to resort to marking it as exportable as that's a major security issue. You're effectively allowing anyone who can get to the box with a similar set of permissions to take your cert with them and import it anywhere else. Obviously that's not optimal.
Security warning: what the checkbox really means is that the certificate can be read by users that shouldn't be able to read it. Such as the user running the IIS worker process. In production use the other answer instead.
Happened to me too, and was fixed by ensuring that "Allow this certificate to be exported" is checked when you import it:
(thanks to this post!)
This must be some kind of IIS bug, but I found the solution.
1- Export MyPersonalCA.pfx from IIS.
2- Convert it to .pem:
openssl pkcs12 -in MyPersonalCA.pfx -out MyPersonalCA.pem -nodes
3- Convert it back to .pfx:
openssl pkcs12 -export -in MyPersonalCA.pem -inkey MyPersonalCA.pem -out MyPersonalCA.pfx
4- Import it back to IIS.
We had the same issue due to incorrectly importing the certificate into the Current User Personal certificate store. Removing it from the Current User Personal store and importing it into the Local Machine Personal certificate store solved the problem.
Nobody probably cares about this anymore, but I just faced this issue with my IIS 7 website binding. The way I fixed it was going to the Certificate Authority and finding the certificate issued to the server with the issue. I verified the user account that requested the certificate. I Then logged into the IIS server using RDP with that account. I was able to rebind the https protocol using that account only. No exports, reissuing, or extension changing hacks were needed.
Instead of importing the cert from IIS, do it from MMC.
Then goto IIS for binding.
In our case this problem occurred because we have installed the certificate in a Virtual Machine and made an image of it for further use.
When creating another VM from the image previously created the certificate sends the message.
To avoid this be sure to install the certificate on every new VM installed.
According to the MSDN blog post, this can happen when the current user account doesn't have permission to access the private key file which is under the folder "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys". Apparently this can be resolved by granting the user account / user group Full Access permission to the above folder.
I've come across the same issue, and was able to resolve it by simply re-importing the .pfx file with the Allow this certificate ti be exported checkbox selected.
However, this method imposes a security risk - as any user who has
access to your IIS server will be able to export your certificate with
the private key.
In my case, only I have access to my IIS server - therefore it was not a huge risk.
I got this error due to wrong openssl command-line during export PKCS #12 certificate. -certfile key was wrong. I exported certificate again and it was imported successfully.
We found another cause for this. If you are scripting the certificate install using PowerShell and used the Import-PfxCertificate command. This will import the certificate. However, the certificate imported cannot be bound to a website in IIS with the same error as this question mentions. You can list certificates using this command and see why:
certutil -store My
This lists the certificates in your Personal store and you will see this property:
Provider = Microsoft Software Key Storage Provider
This storage provider is a newer CNG provider and is not supported by IIS or .NET. You cannot access the key. Therefore you should use certutil.exe to install certificates in your scripts. Importing using the Certificate Manager MMC snap-in or IIS also works but for scripting, use certutil as follows:
certutil -f -p password -importpfx My .\cert.pfx NoExport
See this article for more information: https://windowsserver.uservoice.com/forums/295065-security-and-assurance/suggestions/18436141-import-pfxcertificate-needs-to-support-legacy-priv
Guys after trying almost every single solution to no avail i ended up finding my solution to '“A specified logon session does not exist. It may already have been terminated.” when using https" below
Verify your pfx cert is healthy with correct private key
Run certutil and locate the certs 'unique Container name' - i used certutil -v -store my
3.Navigate to C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys and locate the system file that corresponds to your Container name found above
Check permissions and ensure 'system' has full control to file.
Once applied i then checked IIS and was able to apply to https without error
I had the same issue. Solved by removing the certificate from de personal store (somebody put in it) and from the webhosting. All done through the IIS manager. Then I added again to the webhosting store (with everything checked) and I can use HTTPS again...
In my case it was because the World Wide Publishing Service user didn't have permissions to the certificate. After installing the certificate, access the certificates module in MMC and right-click the certificate with the issue. Select "Manage Private Keys..." from the "All Tasks" menu and add the above user. This was SYSTEM user in my case.
I was getting a this error when trying to bind localhost pfx cert for my development machine.
Before i tried any of this above, tried something simpler first.
Closed any localhost dev site i had openned.
Stopped my IIS server and closed the manager
run the manager as Admin
Added all my https bindings, no errors or issues this time.
restarted iis
Everything seems to work after that.
I was getting same error whilst binding the certificate, but fixed after deleting the certificate and importing again through mmc console.
In my case, it has been fixed by using certutil -repairstore command. I was getting following error, when trying to add certificate to Web Binding on IIS using powershell:
A specified logon session does not exist. It may already have been terminated.
I fixed it by running:
certutil.exe -repairstore $CertificateStoreName $CertThumbPrint
where CertificateStoreName is store name, and CertThumbPrint is the thumbprint of imported certificate.
I recieved this error message when trying to use the following powershell command:
(Get-WebBinding -Port 443 -Name
"WebsiteName").AddSslCertificate("<CertificateThumbprint>", "My")
The solution for me was to go into certificate manager and give IIS_IUSRS user permission to see the certificate.
These are the steps I followed:
Move the certificate into [Personal > Certificates]
Right click [All Tasks > Manage Private Keys]
Add the IIS_IUSRS user (which is located on the local computer not in your domain if you're attached to one)
Give read permission
I managed to fix this problem by importing the SSL certificate PFX file using Windows Certificate Manager.
http://windows.microsoft.com/en-us/windows-vista/view-or-manage-your-certificates
I just had this issue today and feel compelled to post my solution in the hope that you will lose less hair than I've just done.
After trying the solutions above, we had to re-issue the SSL certificate from the SSL provider (RapidSSL issuing as a reseller for GeoTrust).
There was no cost with this process, just the five minute wait while the confirmation emails (admin#) arrived, and we gained access again.
Once we had the response, we used IIS > Server Certificates to install it. We did not need the MMC snap-in.
https://knowledge.rapidssl.com/support/ssl-certificate-support/index?page=content&id=SO5757
We kept a remote desktop window to the server open throughout, to avoid any issues with differing login accounts/sessions, etc. I do believe it is an IIS bug as another expert believes, as we only have one RDC account. What is most infuriating is that the very same certificate has been working perfectly for two months before suddenly "breaking".
In my case I imported a newer version of a certificate (PFX for IIS) from StartSSL just recently and forgot to remove the old one, which somehow caused this error (now two certs sort of the same). I removed both of them, imported the proper one, and now it works.
I was able to fix this problem by removing the then importing it by double clicking the certificate.
For me, the fix was to delete the cert from IIS and re-import it, but into the "personal" certificate store instead of "web hosting"
According to the below, this is fine, at least for my own circumstances.
What's the difference between the Personal and Web Hosting certificate store?
Also, should it make any difference, I imported the certificate via the wizard after double clicking on it on the local machine, instead of via the IIS import method. After this the certificate was available in IIS automatically.
Here's what worked for me:
Step 1: Open up a Run window and type "mmc"
Step 2: Click File > Add/Remove Snap In
Step 3: Add > Certificates, Click OK
Step 4: Choose "Computer Account", then "Local Computer" and proceed.
Step 5: Hit OK
Step 6: Right click the Certificates folder on: Console Root > Certificates (Local Computer) > Personal > Certificates
Step 7: Select All Tasks > Import (Please note that the "Local Machine" is selected on the next window)
Step 8: Browse your .pfx file
Step 9: Then go to the IIS and create https binding
Try :
Go into IIS and delete "VSTS Dev Router" web site and "VSTS Dev Router Pool" application pool.
Run “certlm.msc” and open Personal/Certificates
Delete any cert named “*.vsts.me” and "vsts.me"
Re-deploy

SSL Certificate will not save

I am trying to install an SSL Certificate (from GoDaddy.com) onto IIS 7. I can add the certificate following the directions found here and it shows up in my list of Server Certificates but once I leave the Server Certificates page and return to it, the certificate no longer shows up in the list.
This certificate is also used on an Apache box to authenticate our website (I am using IIS for a WCF Service API). The certificate is assigned to *.mydomain.com so I thought I could use it for the Apache website server (www.mydomain.com) as well as my API (services.mydomain.com). Am I incorrect in this assumption? Do I need to do something different then the instructions I referenced above to install?
Brian,
I assume you just grabbed the .cer file and imported this onto your IIS box. Sadly this is not possible as your certificate will not contain a private key so it won't be an option in IIS.
The GlobalSign instruction you referenced are fine but that is if you created the CSR on the IIS server itself.
What you will have to do is to create a PFX from from your .key and .cer files from the Apache server and then you can import this PFX onto your IIS Server followed by assigning it for use.
So use this to create your PFX file;
https://support.globalsign.com/customer/portal/articles/1229676-back-up-certificate---apache-openssl
Followed by;
https://support.globalsign.com/customer/portal/articles/1217281
As for everyone else if you just have a .CER file you and did not create the request you need a private key. So create a new CSR and request a reissue from your relevant CA.
The fact you cannot assign a certificate in IIS is because you do not have a private key that corresponds to the certificate.
You have two options:
If you have access to the old machine you first created the certificate just go to that and export ".pfx" file from the certificate, then in the new machine you could easily import it and Done.
If you don't have access to the old machine, so you must reissue the SSL certificate with the help of the seller company.
Hope this help.
See how godaddy response for this case:
https://sg.godaddy.com/community/SSL-And-Security/completing-certificate-request-disappears-from-server/td-p/36299
But it doesn't work.
I tried in my way :
- Use https://www.sslshopper.com/ssl-converter.html to convert my CRT file to PFX file.
- Then go to the IIS -> Server certificates -> Import -> Choose the generated PFX file in previous step.
It worked with me.

Calling Remote Web Service -- "The request failed with HTTP status 401: Unauthorized"

I am calling a remote service and authenticating using a certificate. When testing with a Console App, everything works fine. When calling from an ASP.NET Website (.NET 4.0, IIS7) I receive a response code of 401 -- Unauthorized.
I am adding the certificate using code such as:
var client = new TheGeneratedProxy();
client.ClientCertificates.Add(new X509Certificate("D:\cert.pfx", "myPassword"));
(NOTE: I have also loaded the .pfx into the local Certificate Store using IE. The certificate is loaded into my "Personal" store -- so I suspect this to be the problem, since the Website will be running under a different account.)
I think the problem is that your IIS user (Network Service / ASPNET) doesn't have access to the certificate. In order to grant Network Service to access the certificate in the store, download the following tool: winhttpcertcfg (http://www.microsoft.com/downloads/details.aspx?familyid=c42e27ac-3409-40e9-8667-c748e422833f&displaylang=en)
Now open command prompt and type:
winhttpcertcfg –g –c LOCAL_MACHINE\My –s ORGNAME –a "Network Service"
Please note that "Network Service" can be substituted with any other account. I.e. if you you have configured a custom user for your app pool, you should put this user as the value for the -a parameter.
ORGNAME should be substituted with the Organisation name you specified during the creation of your cert.

Resources