I am developing a WCF DataService that's self-hosted inside a Windows Console Application. I want to activate my service over Https (i.e. SSL) instead of Http. How can I do that?
Thanks
First Creating a CA Certificate on Windows (use Visual Studio Command Prompt):
makecert -sv SignRoot.pvk -cy authority -r signroot.cer -a sha1 -n "CN=Dev Certification Authority" -ss my -sr localmachine
Now put the certificate in the "Trusted Root Certification Authority" in Windows Key Store. That can be done through MMC. To do that: Run... -> Type "mmc" -> enter -> choose the "Certificates" console -> Find your created certificate in the Personal store and move it to the Trusted Certificate Authority store.
Now we create an exchange certificate signed by the CA certificate:
makecert -iv SignRoot.pvk -ic signroot.cer -cy end -pe -n CN="localhost" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
NOTE: The EKU OID is for Server Authentication
NOTE: the CN (Common Name) should be identical to the name by which the service will be called.
Now we add an Https endpoint to the data service. That can either be
1- Through the web.config file of the service, in which we'll have to enter a service endpoint:
<endpoint address="https://localhost:8888/" binding="basicHttpsBinding" contract="System.Data.Services.IRequestHandler"></endpoint>
2- Or with adding an endpoint programmatically using the "AddServiceEndpoint" of the DataServiceHost object:
host.AddServiceEndpoint(
new ServiceEndpoint(ContractDescription.GetContract(typeof(TestODataService.DemoDataService)))
{
Address = new EndpointAddress("https://localhost:8888/"),
Binding = new WebHttpBinding(WebHttpSecurityMode.Transport),
Contract = ContractDescription.GetContract(typeof(IRequestHandler)),
}
);
NOTE: The binding in the second method is necessarily WebHttpBinding with Transport security. While in the web.config method, it can be either basicHttpsBinding, or a webBinding with bindingConfiguration that enable transport security.
Now we bind the exchange certificate with the port of the service. In order for the WCF web server to respond to clients with the exchange certificate, we need to bind the certificate to the address of the service, using the netsh command:
netsh http add sslcert ipport=0.0.0.0:8000 certhash=0000000000003ed9cd0c315bbb6dc1c08da5e6 appid={00112233-4455-6677-8899-AABBCCDDEEFF}
NOTE: the certhash is the thumbprint of the exchange certificate, and the appid is the GUID of the hosting application found in the AssemblyInfo.cs of the project. The ip 0.0.0.0 binds to all ip address, and the port is the port of the service. This command is required to be used only once for each address.
NOTE: Some mobile devices may not be able to verify the identity of the service when called using the ip address of the service, even if the exchange certificate have the CN set to the ip address of the service. In this case the CN of the certificate should be a domain name.
NOTE: in order for the mobile device to trust the exchange certificate of the service, the CA certificate should be installed on the mobile in the Trusted CA Certificate store.
NOTE: Some browsers (e.g. Chrome) will object that the certificate is issued for localhost which is a name only used in your local network. This will not occur if you set the CN to a domain name.
Reference: http://www.codeproject.com/Articles/24027/SSL-with-Self-hosted-WCF-Service
Related
As a part of the POC, I followed the article https://www.ais.com/how-to-configure-point-to-site-vpn-connection-using-azure-certificate-authentication/ and configured Point-to-Site.
In summary: I have created the Root & Client Certificate and configured the Virtual Gateway
Here we are generating the root certificate
$cert = New-SelfSignedCertificate -Type Custom -KeySpec Signature -Subject "CN=VPNRoot" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\CurrentUser\My" -KeyUsageProperty Sign -KeyUsage CertSign
Here we are generating the client certificate from the root certificate
New-SelfSignedCertificate -Type Custom -DnsName VPNCert -KeySpec Signature -Subject "CN=VPNCert" -KeyExportPolicy Exportable -HashAlgorithm sha256 -KeyLength 2048 -CertStoreLocation "Cert:\CurrentUser\My" -Signer $cert -TextExtension #("2.5.29.37={text}1.3.6.1.5.5.7.3.2")
Now that it works, my goal is to replace the certificates ("Root" and "Client") with production ready certificates.
From the Certificate Authority, what kind of certificates should be requested?
Note: Our Azure Tenant is something like xyznp.onmicrosoft.com
Note that In Azure Point to Site, you can use a root certificate that was generated using an Enterprise solution, or you can generate a self-signed certificate.
Refer : About Azure Point-to-Site VPN connections - Azure VPN Gateway
When you are using the enterprise solution certificate chain in the root certificate, you should acquire the .cer file for the root certificate that want to use.
And generate a client certificate with the common name value format name#yourdomain.com. In your case it should be in the format xyznp#onmicrosoft.com
Refer : Connect to a VNet using P2S VPN & certificate authentication: portal - Azure VPN Gateway
NOTE : Verify the authentication order on the client certificate if you used a certificate that was issued by an Enterprise CA solution and but having trouble for authenticating.
By double-clicking the client certificate, choosing the Details tab, and then selecting Enhanced Key Usage, you can verify the authentication list order like below.
Make sure Client Authentication is listed first. If it isn't, create a client certificate based on the user template with Client Authentication listed as the first item.
Refer: Connect to a VNet using P2S VPN & certificate authentication: portal - Azure VPN Gateway
I wish to bind a self signed certificate to a port for developing my self hosted wcf application, but I always fail.
Steps I've done:
created the root certificate:
makecert.exe -a SHA256 -n "CN=DemoCA" -r -sv TempDemoCA.pvk TempDemoCA.cer
created the client cert:
makecert.exe -a SHA256 -sk Demo -iv TempDemoCA.pvk -n "CN=DemoTempCert" -ic TempDemoCA.cer DemoTemp.cer -sr currentuser -ss My -sky exchange
imported the root cert with mmc.exe(as Administrator) into local computer certificates
imported the client cert with mmc.exe into local computer certificates
added the private key to the client cert, because it didn't have the key icon:
certutil -repairstore my "MyKeyHash"
Added a firewall entry:
netsh http add urlacl url=https://+:9003/ user=domain\user listen=yes
tried to bind the certificate to the port(as admin):
netsh http add sslcert ipport=0.0.0.0:9003 certhash=MyCertHash appid={NewGuid} clientcertnegotiation=enable
But step 7 failed with error 1312.
SSL Certificate add failed, Error 1312
A specified logon session does not exist. It may already have been terminated.
All I found out by googling, doesn't solve my problem, e.g.:
- import via mmc and not certmgr.msc
- create a new certificate
- KB Hotfix
Interesting fact: binding the existing "localhost" client certificate to a port works fine.
What am I doing wrong?
Thanks in advance.
The solution was that the common name has to be the same as the used domain of the service. In my case localhost did the trick.
I'm getting the error mentioned in this question:
The X.509 certificate CN=Farm chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust.
What I don't understand why I'm getting this error as the certificate I use for my request to the WCF service is added as shown below:
client.ClientCredentials.Peer.PeerAuthentication.CertificateValidationMode =
X509CertificateValidationMode.ChainTrust;
client.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySerialNumber,
"MyCertificatesSerialNumber" );
The certificate itself is a self-signed certificate in the store shown above. When I click on it to show the certification path, no errors are shown (the root certificate is also a self-signed certificate). The root certificate was manually imported into the trusted root certification authorities.
From the error message I would have expected that there was an error in the certification chain with one of my certificates, but there isn't. Any ideas?
Update
I'm using Internet Explorer 9 as my browser to access the webservice. Programmatically I'm using a C# console application.
I had exactly the same problem - my own trusted root CA which signed another certificate. No errors were shown in the certificate store.
It turned out that having a trusted root CA and a certificate is not sufficient! You also need a certificate revocation list! Take a look at this MSDN Link.
So simply create such a .crl and add it also to the trusted root certificate authorities and everything works fine!
makecert -crl -n "CN=CARoot" -r -sv CARoot.pvk CARoot.crl
or simply turn of the revocation list check:
...RevocationMode = X509RevocationMode.NoCheck;
I had this problem - this is what I'd suggest:
On the server, make sure that the root cert is located on the "local computer" side of the computer, not "Current User". The other thing is that the SSL cert needs to be derived from the root cert. I eventually got it all to work using a script that included these lines:
rem creates root authority file and cert in localmachine\root and gives it the right to sign certs
makecert.exe -a sha1 -n CN=RootCert RootCertName -sr LocalMachine -ss Root -sky signature -pe -r -sk MyNewKey -cy authority
rem creates ssl cert, puts it in the currentuser\Personal store, signing it based on the root cert
makecert.exe -n cn=HostURL SSLCertName -is root -ic RootCertName -sky exchange -pe -sv SSLCertPrivateKeyName -eku 1.3.6.1.5.5.7.3.1
It's complicated, tedious stuff. You just have to keep at it.
I faced a similar issue while trying to connect to a self hosted WCF service using net.tcp binding. I already had the self signed root CA certificate installed in the CurrentUser certificate store, client was using a certificate signed by the root CA cert.
Installing the root CA certificate in LocalComputer certificate store fixed the error "A certificate chain could not be built to a trusted root authority". My WCF Server process runs using current user account hence this step was not obvious.
The next error was "The revocation function was unable to check revocation for the certificate"
To fix this, I created an empty Certificate Revocation List for the root CA cert and then installed the CRL in the LocalComputer certificate store. (Please check this link for details : https://msdn.microsoft.com/en-us/library/ff648732.aspx)
I also set the revocation check mode to Offline for both server and client certificates.
defaultCredentials.ServiceCertificate.Authentication.RevocationMode = X509RevocationMode.Offline;
defaultCredentials.ServiceCertificate.Authentication.CertificateValidationMode =
X509CertificateValidationMode.ChainTrust;
Now I don't have to turn off certificate validation or use different validation mode for development (In my case production code will also use self signed certificates for the time being)
I have been having this issue for about 2 weeks. I have done a lot of research and tried different ways but no joy. I have a development website on my computer (Windows 7 Pro) with sql server 2008 r2 and using IIS 7.5. There is an actual development server running the database and Webserver but because of my location I cannot use the main development site. I issued a self signed Trusted Root Certificate:
makecert -r -pe -n "CN=ROOT AUTHORITY" -ss my -sr CurrentUser -a sha1 -sky signature -cy authority -sv ca.pvk ca.cer
Then I install that into the trusted root on the local computer. After that I created a certificate for IIS to use.
makecert -pe -n "CN=example.website.name.com" -a sha1 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -ic ca.cer -iv ca.pvk -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12 -sv server.pvk server.cer
Then I create the .pfx file for IIS
pvk2pfx -pvk server.pvk -spc server.cer -pfx server.pfx
After I do the above. I import the certificate into IIS and then I bind the website to the SSL certificate (server.pfx)
After all that is done, I go on the website https://example.website.name.com and I get 403.7 forbidden.
Can somebody please help me out with this issue?
take a look at some of these pitfalls...
Server Issue #1 - The client cert passed in has 1 or more certification paths that do NOT exist on the server. Open the cert go to certification path (tab) and make sure each of the root authorities are in the SERVERS trusted root certificate authorities. Note, you DO NOT need to install the cert on the server just the root authorities public keys under Certificates (Local Computer) \ Trusted Root Certification Authorities.
Server Issues #2 (previously mentioned solution) - In IIS, for the site, make sure the SSL Settings are set to Accept OR Require (never ignore). The benefit of using Require is that the IIS logs will show you are 403 7 error where as Accept will just get your the IsPresent == false but with a 200 http code.
Client Issue #1 - Same as server issue #1, got to trust those authorities!
Client Issue #2 - You have the trusted root authorites but NOT the private key for the cert itself. Make sure you install the pfx (private key) into the cert store not the public key (.cer). You can also see if you have the private key by double clicking the cert in the cert store and on the general tab you should see a message saying as much.
Client Issue #3 - You put the cert in the wrong place. Probably best to place your cert in Certificates (Local Computer) \ Personal \ Certificates, rather than (current user). This will make the cert available to process accounts that are running your code and actually need access to it.
Client Issue #4 - Right mouse click the cert (in the store not a .cer file) --> All Tasks --> Manage Private Keys... and make sure the process account running your code has "Read" permission. A quick test of this (but not recommended for production use) is to add "Everyone" as read to see if this is your issue
I have a WCF web service running in IIS 7 using a self-signed certificate (it's a proof of concept to make sure this is the route I want to go). It's required to use SSL.
Is it possible to use the WCF Test Client to debug this service without needing a non-self-signed certificate?
When I try I get this error:
Error: Cannot obtain Metadata from
https:///Service1.svc
If this is a Windows (R) Communication
Foundation service to which you have
access, please check that you have
enabled metadata publishing at the
specified address. For help enabling
metadata publishing, please refer to
the MSDN documentation at
http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata
Exchange Error URI:
https:///Service1.svc
Metadata contains a reference that
cannot be resolved:
'https:///Service1.svc'.
Could not establish trust relationship
for the SSL/TLS secure channel with
authority ''. The
underlying connection was closed:
Could not establish trust relationship
for the SSL/TLS secure channel. The
remote certificate is invalid
according to the validation
procedure.HTTP GET Error URI:
https:///Service1.svc
There was an error downloading
'https:///Service1.svc'.
The underlying connection was closed:
Could not establish trust relationship
for the SSL/TLS secure channel. The
remote certificate is invalid
according to the validation procedure.
EDIT: This question is specifically about using the WCF Test Client to test a web service already secured via SSL using a self-signed certificate. The server is already set up to accept any certificate provided, it's the WCF Test Client I don't see a way to do this for.
You can create a non self-signed certificate in development area and then use this certificate in IIS for applying the SSL. The steps are:
Create self-signed certificate
makecert -r -pe -n "CN=My Root Authority" -a sha1 -sky signature
-ss CA -sr CurrentUser
-cy authority
-sv CA.pvk CA.cer
Create a non self-signed certificate for SSL which signed by this root certificate and then create pfx-file from that
makecert -pe -n "CN=servername" -a sha1 -sky exchange
-eku 1.3.6.1.5.5.7.3.1 -ic CA.cer -iv CA.pvk
-sp "Microsoft RSA SChannel Cryptographic Provider"
-sy 12 -sv server.pvk server.cer
pvk2pfx -pvk server.pvk -spc server.cer -pfx server.pfx
now you just need to import the server.pfx into the IIS and setup the web site binding to use this certificate and also install the CA.cer in Local Computer \ Trusted Root Certification Authorities store in both server and client by doing this WCF client would work with the service through HTTPS without any problem.
you should be able to do this if you replace the WCF Test Client with WCFStorm Lite Edition. It's free and is quite a bit more flexible than MS's test client... for example, it'll let you specify a user name & password if you're doing username authentication.
The answer from this question helped in my case. Be sure to use exact machine name as certificate expects. For exampe machine/service.svc may not work, while machine.domain/service.svc - works.
To answer your question... here is how you force your WCF test client to accept a self-signed certificate...
using (ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client())
{
System.Net.Security.RemoteCertificateValidationCallback callBack = (sender, certificate, chain, sslPolicyErrors) => true;
ServicePointManager.ServerCertificateValidationCallback += callBack;
Console.WriteLine(proxy.GetData(35));
ServicePointManager.ServerCertificateValidationCallback -= callBack;
}
Yes it is possible.
Just download the generated WSDL from the service (https://localhost/Service1.svc?singleWsdl) and supply the path to this file when adding a service in the WCF Test Client.
You can supply your own method to validate the certificate.
Try this:
ServicePointManager.ServerCertificateValidationCallback +=
new System.Net.Security.RemoteCertificateValidationCallback(EasyCertCheck);
The call back:
bool EasyCertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}