The default wsHttpBinding is perfect for intranet application scenario, if all users are login throug a LDAP server. Client side already authenticated the user, on server side, services only need to grap the client user windows login (with domain).
In UserName auth mode, this becomes a blank string, to get user id inputted in some kind of login page, call:
UserName auth mode should be used for internet scenario, WCF uses the X509 certificate to protect the message transfered over plain HTTP. Service side need to generate the certificate by running: (in C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin )
makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=MyServerCert -sky exchange –pe
Then configure certificate in web.config:
<behavior name="customUserName"> <serviceDebug includeExceptionDetailInFaults="true"/> <serviceMetadata httpGetEnabled="true"/> <serviceCredentials> <serviceCertificate findValue="MyServerCert" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" /> </serviceCredentials> </behavior>
Got “keyset does not exist” error then, had to give read permission to the account to server the www service, either ASPNET or NETWORK SERVICE. Make sure you get the right key file, I couldn’t make cacls work with folder.
cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\your-key-file" /E /G "ASPNET":R cacls.exe "C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys\your-key-file" /E /G "NETWORK SERVICE":R
Client side has 5 options to choose as the WSHttpbinding behavior:
<behavior name="PeerTrustClient"> <clientCredentials> <serviceCertificate> <authentication certificateValidationMode="PeerTrust" /> </serviceCertificate> </clientCredentials> </behavior> <!-- None, ChainTrust, or Custom-->
Skip the certificate check, client doesn't care if the host is the REAL service provider. Some hackers could resolve chient's address and redirect the call to a malicious service.
Certificate (exported private key?) installed in the client\'s Trusted People store. Maybe double click the certificate file can do the job.
Certificate issued by a root authority (can get a trial one from Thawte). I haven\'t figure this out yet, \'Windows does not have enough information to verify this certificate\'. Downloaded and installed the Thawte test CA root certificate, same problem.
Switched to SSL Web Server Certificate, the default was SGC Supercert, which needs a Thawte Test Intermediate CA I couldn't find anywhere. The SSL Web Server certificate at least looks OK, with the Thawte Test Root CA installed, no error or warning appear in mmc.exe view.
But my WCF service still reports: 'System.IdentityModel.Tokens.SecurityTokenValidationException: The X.509 certificate CN=... chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. An internal certificate chaining error has occurred'.
Switched back to SGC test certificate from thawte, re-do the same thing, this time the "not enough information " warning magically went away! And WCF services feedback a slightly different error:
'The certificate that was used has a trust chain that cannot be verified, The revocation function was unable to check revocation because the revocation server was offline'.
Checked the MS help, it seems I am very close now, very likely it's a test certificate issue. It might be fixed by some tricks on server side, for now, it's enough. Maybe we don't need it mode at all.
Mixed mode, for tightly controlled enviroments. (Some very restrict Organization have their own root certificates?)
Client side creates X509CertificateValidator subclass assigned in app.config:
<behavior name="myClientBehavior"> <clientCredentials> <serviceCertificate> <authentication certificateValidationMode="Custom" customCertificateValidatorType="Premotion.Services.MyX509Validator,client" /> </serviceCertificate> <!-- in B2B bindings, add <clientCertificate findValue = "MyClientCert" storeLocation = "LocalMachine" storeName = "My" x509FindType = "FindBySubjectName" </clientCertificate> --> </clientCredentials> </behavior>
same as the example shown in http://www.devatwork.nl/index.php/2007/05/31/wcf-username-authentication
A post about Fundamentals of WCF Security.