Hi,
Apologies in advance for the length, but I wanted to thoroughly document my analysis of this issue.
I have spent an inordinate amount of time (weeks and weeks) Googling/researching/testing/debugging the IIS Client Certificate Authentication security scenario for WCF Web Services. And, in short, while acknowledging that I could very well be mistaken, based
on my results, I have come to the conclusion that there is either a bug in either IIS Web Site/Application Authentication; .Net Web Client Authentication configuration, or both.
The problem in short appears to be that there is currently no way for a web client to authenticate to IIS via X.509 certificate, without enabling "Anonymous Authentication" in IIS. I believe this to be a bug because in addition to the reasons laid out below,
in my opinion, this behavior is completely inconsistent with the other IIS Authentication schemes, and there is no logical reason for such a requirement. Depending on the configuration settings, attempts to implement client certificate authentication, without
enabling Anonymous Authentication in IIS, result in one of the following errors, which I believe indicate an issue with how certificate authentication is implemented in .Net and/or IIS:
#1 Exception: System.ServiceModel.ServiceActivationException: The service 'MyService.svc' cannot be activated due to an exception during compilation. The exception message is:Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.. ---> System.NotSupportedException:
Security settings for this service require 'Anonymous' Authentication but it is not enabled for the IIS application that hosts this service.
#2 System.ServiceModel.ServiceActivationException: The service 'MyService.svc' cannot be activated due to an exception during compilation. The exception message is:The authentication schemes cannot be inherited from the host for binding 'CustomBinding'. No AuthenticationScheme was specified on the ServiceHost or in the virtual application in IIS. This may be resolved by enabling at least
one authentication scheme for this virtual application in IIS, through the ServiceHost.Authentication.AuthenticationSchemes property or in the configuration at the <serviceAuthenticationManager> element.. --->
#3 System.ServiceModel.ServiceActivationException: The service '/SecureWCFSvc/EmployeeGetSvc.svc' cannot be activated due to an exception during compilation. The exception message is:The value of the property 'authenticationScheme' cannot be parsed. The error is: The enumeration value must be one of the following: None, Digest, Negotiate, Ntlm, IntegratedWindowsAuthentication, Basic, Anonymous.. --->
The first error CLEARLY indicates that A. Anonymous Authentication is disabled for the IIS web app. And B. The web client/service configuration settings (Transport.clientCredentialType="Certificate") dictate thatAnonymous Authentication be enabled in IIS for the web app.
In the second error, the web app (IIS) configuration is indicating that NO authentication scheme has been specified, when in fact the iisClientCertificateMappingAuthentication scheme has been enabled for the web app in IIS.
Finally, when attempting to use a custom binding with authenticationScheme="Certificate", the response is basically that there is no such authentication scheme, and that one must be selected from the enumerated values that are helpfully provided in the exception
message. Which of course begs the question: Where is the value that maps to the IIS "iisClientCertificatMappingAuthentication" Authentication Scheme?
Here are the pertinent settings/configuration/setup steps:
IIS
1. Configured web site/app for SSL with valid self-signed Cert
2. IIS Certificate Mapping correctly configured and enabled in applicationHost/web site/web app config files:
<iisClientCertificateMappingAuthentication enabled="true" oneToOneCertificateMappingsEnabled="true"
defaultLogonDomain="myDomainName">
<oneToOneMappings>
<clear />
<add userName="wcfUser" password="[enc:IISCngProvider:iEncoded Value=:enc]" certificate="Encoded Cert String" />
</oneToOneMappings>
<manyToOneMappings />
</iisClientCertificateMappingAuthentication>
3. All Authentication modes disabled in IIS Manager/Authentication settings UI
Web Service/Client App:
1. Specify Transport Client Credential Type = "Certificate" in both service and app bindings:
<wsHttpBinding>
<binding name="wsHttpTransportCertBinding" >
<security mode="Transport/TransportWithMessageCredential" >
<transport clientCredentialType="Certificate" />
<message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
2. Delete or specify same binding for Mex endpoint
3. Specify valid self-signed Client Cert in client app.config <clientCredentials> section
Test Cases/Results
1. Using above settings/configuration
Result: Exception #1 above: "Security settings for this service require 'Anonymous' Authentication"
Huh?????
Why is enabling Anonymous Authentication in IIS required for a Client Credential Type of "Certificate", while when I specify a Client Credential Type of "Basic", I can enable ONLY Basic Authentication in IIS, and the service works as expected?
2. Enable "Anonymous Authentication" for site/application
Result: Service method successfully called with
mapped certificate user account shown in IIS logs!!! ![undecided]()
![undecided]()
![undecided]()
***Now here's the kicker***
3. Set binding to INHERIT the authentication scheme from host
Result: - Exception #2 above: "No AuthenticationScheme was specified on the ServiceHost or in the virtual application in IIS"
Say what?????
How can this be when the iisClientCertificatMappingAuthentication Scheme is CLEARLY enabled for the web site/application??? Why does the exception indicate that no authentication scheme has been specified, when clearly it has?
4. Configure Custom Binding with CertificateOverTransport
Result: - Exceptions comparable to above wsHttpsBinding errors.
5. Implement various IIS/.Net configuration steps outlined in numerous posts, blogs, and forum answers.
Result: - My early experience was that on several occasions, the posted "solution" actually appeared to work...Initially. But what I found, was that when I re-published my web service app to IIS, the Anonymous Authentication
scheme was "silently" re-enabled on the web app. Once I discovered this, and again disabled it, I was back to receiving the usual exceptions. Because of that, I added code explicitly disabling Anonymous Authentication to my service's web.config file, to prevent
that behavior going forward. I suspect that this same behavior may have occurred with others, and that the "false positives" were not discovered (if then) until after the purported "solutions" were publicly posted.
The error conditions I've documented above are why it appears that there is a bug, but it's not clear which side is the culprit. In other words, is IIS indicating to the .Net client that NO authentication scheme has been enabled, even though it has? OR,
is it that IIS actually indicates to the client app that the iisClientCertificateMappingAuthentication scheme is indeed enabled, but for whatever reason, .Net either doesn't map the IIS scheme to "Certificate"; erroneously maps "Certificate" to the "Anonymous"
authentication scheme, or falls back to that Anonymous because the enumeration mapping to the IIS iisClientCertificateMappingAuthentication scheme is missing/invalid/not implemented on the .Net side? Or some combination of both, or other? Whichever is the
case, in my mind, there clearly appears to be an issue here.
Obvious Questions:
1. At this point, why is there STILL no "Certificate Authentication" option in IIS Manager UI available for Web Site/Applications' Authentication settings?
2. In .Net web.config, why is there no authenticationSchemes enumeration value that corresponds to the IIS iisClientCertificateMappingAuthentication scheme?
3. If this is indeed an issue of "lack of guidance" rather than a bug, why has Microsoft provided such extensive documentation (and examples) for IIS and WCF configuration, but has glaringly omitted guidance for implementing one of the most common, asked-about,
and apparently most difficult to implement business use-cases?
In my humble opinion, Microsoft should do one (or more) of the following:
1. Acknowledge that this is a bug. Commit to fixing it, and then do #3.
2. Acknowledge that this is a bug and that they are NOT going to fix it (and why), and CLEARLY indicate that developers must enable Anonymous Authentication in IIS in order to implement Client Certificate Authentication, instead of requiring developers to spend
hours/days/weeks googling Stackoverflow and blogs for the answer...Which, because any developer worth his salt, isn't going to take at face value, results in frustration and wasted time spent trying to verify what seems to be an inexplicable requirement.
Also, by making such a public acknowledgement, Microsoft will not only save untold man-hours in wasted effort, it will also allow developers to point at official Microsoft guidance, when explaining (justifying) to internal sysadmins, clients, and third-parties
why they must enable Anonymous Authentication on their web site(s)/app(s) if they want clients authenticated by
X.509 certs.
3. Provide clear guidance (documentation and examples) in Microsoft Docs on both the server and client configurations for correctly implementingClient Certificate Authentication in IIS WITHOUT enabling Anonymous Authentication.
Again, I acknowledge that I am NOT an expert, and could very well be mistaken in my analysis of this issue, and would welcome any guidance and/or references to successful implementations of this use case.
Any and all responses welcomed.
Thanks!
TWebby1763