enviroment An ASP.NET Application invokes a WCF Application hosted in IIS using a WCF Client over SSL and authenticates itself with a client certificate. PKI must be created too.
problem Just try it without this documentation... took as 2 1/2 days
solution
(All commands are in
formatted
and shall be executed on cmd.exe)
Preparations
Download OpenSSL (for Win32)
cd c:\openssl\bin
mkdir demoCA
echo 01 > demoCA\serial
create a new and empty file named demoCA\index.txt
Certificate Authority (CA)
mkdir work openssl genrsa -out work\CA\CA.key 1024 openssl req -new -key work\CA\CA.key -days 3650 -out work\CA\CA.csr -subj "/CN=choose.some.name" openssl x509 -req -days 3650 -in work\CA\CA.csr -signkey work\CA\CA.key -out work\CA\CA.crt
Result: CA.key (private key of CA), CA.crt (public key / self-signed certifcate of CA)
Server Certificate for IIS
start IIS-Admin on web server
Properties of WebSites/
Set SSL Port to 443 (e.g.)
-> Directory Security Tab
-> Server Certificate Button
-> Create new certficate
-> Prepare request
IMPORTANT the common name must equal the DNS name used to invoke the WCF service
Result: certreq.txt (Certificate Request)
mkdir work\IIS
Copy certreq.txt to work\IIS
openssl ca -policy policy_anything -cert work\CA\CA.crt -in work\IIS\certreq.txt -keyfile work\CA\CA.key -days 3650 -out work\IIS\iis.cer -outdir work\IIS –batch
Result: IIS.cer (signed server certificate)
start IIS-Admin on web server
Properties of WebSites/
-> Directory Security Tab
-> Server Certificate Button
-> Process pending Request
-> select work\IIS\IIS.cer
Installation of CA on WCF Hosting Server and Client machine (the machine hosting the ASP.NET application)
Start mmc (goto Start\Run: mmc)
Add Snap-In: Certificate\LocalMachine
-> Certficates (LocalMachine) \ Trusted Root Certification Authorities
-> Right click on Certificates \ All Tasks \ Import...
-> Select work\CA\CA.crt
Create client certificates for ASP.NET application
Mkdir work\Client openssl genrsa -out work\client\Client.key 1024 openssl req -new -key work\client\Client.key -out work\client\Client.csr -subj "/CN=Client" openssl x509 -req -days 365 -CA work\CA\CA.crt -CAkey work\CA\CA.key -CAcreateserial -in work\client\Client.csr -out work\client\Client.crt openssl pkcs12 -export -in work\client\Client.crt -inkey work\client\Client.key -out work\client\Client.p12
Start mmc (goto Start\Run: mmc) on ASP.NET hosting machine
Add Snap-In: Certificate\LocalMachine
-> Certficates (LocalMachine) \ Personal
-> Right click on Certificates \ All Tasks \ Import...
-> Select work\client\Client.p12
Configure IIS hosting WCF application to require SSL and Client Certificates
start IIS-Admin on WCF application hosting server
Properties of WebSites/
-> Directory Security Tab
-> Secure Communication / Edit
Select "Require Secure Channel"
Select "Require Client certificates"
Optionally select "Enable certifications trust list" and create a new list holding the CA.crt if you only want to authenticate clients signed by your CA
Configure WCF Client
In your Web.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding" >
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="behavior">
<clientCredentials supportInteractive="false">
<clientCertificate findValue="Client"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
IMPORTANT: Make sure your application does not run under NETWORK SERVICE account. Without tweaking your permissions of the LocalMachine store, you cannot access private keys - which you need when you want to authenticate to the server using client certificates.
Configure WCF Server
In your Web.config
<binding name="basicSec"> <security mode="Transport"> <transport clientCredentialType="Certificate"/> </security> </binding> <serviceBehaviors> <behavior name="returnFaults"> <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors>
Some explaination: although the complete SSL handshake and the authentication is done by IIS, the WCF settings still need to match those of IIS. One reason is that the protocol differs (e.g. http vs. https).
You cannot enable httpGetEnabled and httpsGetEnabled at the same time.
You can using BasicHttpBinding - SSL is just the transport layer.
Some debugging tips
Get SSLDiag for validating you IIS SSL setup
To decrypt SSL traffic using Wireshark:
Start mmc (goto Start\Run: mmc) on WCF application hosting machine
Add Snap-In: Certificate\LocalMachine
-> Certficates (LocalMachine) \ Personal
-> Right click on Certificates \ All Tasks \ Export...
-> Select work\IIS\IIS.pfx
openssl pkcs12 -in vde\iis\iis.pfx -out work\iis\iis.pem –nodes
Start Wireshark
Goto Edit\Preferences\Protocols\SSL: RSA Keys:
Goto Capture \ Options \ Filter: "Port 443"
Happy capturing!
WCF Tracing might be helpful too:
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="All"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "c:\temp\Traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
Darn, wish I had found this earlier, took me a good few hours also.
Do you know how to set this up to work in a development environment. i am loathed to go around everyones pc and set this up. Can you create two endpoints for each service, one for ssl and another for http and somehow use something similar to the #if debug scenario??
Another gotcha that I came across was the need to implement the RemoteCertificateValidationCallback and return true to bypass any errors with local certificates…..or move them into the trusted root certification folder.
Lack of documentation on this is killing me!!!
Thanks in advance
im already follow your stepbystep.(not including wireshark)
now if im accessing my website in my IIS, it wont open
the error is:
“The page must be viewed over a secure channel”
although im already check the “Use SSL 2.0″ and 3.0 on my browser, it happen again and again.
so what do i do?
im already follow your stepbystep.(not including wireshark)
now if im accessing my website in my IIS, it wont open
the error is:
“The page must be viewed over a secure channel”
although im already check the “Use SSL 2.0″ and 3.0 on my browser, it happen again and again.
so what do i do??