views:

900

answers:

4

Some background: in order to provide authentication I'm using certificates on client and server side (WCF) and use one certificate for all clients (manually loading it from application directory - not the safest way, but it doesn't require to manage certificate storage and making installation more difficult):

        AddressHeader hostHdr = AddressHeader.CreateAddressHeader(ServiceFactory.CLIENT_HOST_HEADER, ServiceFactory.NAMESPACE, hostName);
        builder.Headers.Add(hostHdr);
  builder.Identity = new X509CertificateEndpointIdentity(GetServiceCertificate(name));


        _factory = new ChannelFactory<T>(name, builder.ToEndpointAddress());
        _factory.Credentials.ClientCertificate.Certificate = GetClientCertificate(name);
        X509ServiceCertificateAuthentication auth = _factory.Credentials.ServiceCertificate.Authentication;

        auth.CertificateValidationMode =X509CertificateValidationMode.Custom;
        auth.CustomCertificateValidator = new CustomCertificateValidator(new[] {GetServiceCertificate(name)});

This is client side, and serverside host setting up looks like this:

private void CertificateSetup(ServiceHost host)
 {
  if (ServiceCertificate != null)
   host.Credentials.ServiceCertificate.Certificate = ServiceCertificate;

  X509ClientCertificateAuthentication authentication =
      host.Credentials.ClientCertificate.Authentication;

  authentication.CertificateValidationMode =
   X509CertificateValidationMode.Custom;

  authentication.CustomCertificateValidator =
   new CustomCertificateValidator(new [] {ClientCertificate});
 }

That works fine and allows to sign messages, but as far as security mode set in following way:

      <security mode="Message">            
        <message clientCredentialType="Certificate" />
      </security>

But i need

string name = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name;

somehow to obtain WindowsIdentity in ServiceSecurityContext. Mixed (Transport and Message) security mode is not helpful, because I don't know why but even if i set Windows clientCredentials in config for Transport part mode infrastructure tries to establish SSL connection.

Any ideas ????

A: 

If you're using message security with certificates at each end securing it, I'm not quite sure why you would need a windows identity? What's the reasoning behind that?

Maybe this link will be of use - sections 6 & 7 have details of config settings for certificate authentiaction, which works similarly to SSL:

http://www.codeproject.com/KB/WCF/wcf_certificates.aspx

Tanner
Certificates are used for message signing,i.e. proving that other side is either real client/service.But authorization partially relies on WindowsIdentity in ServiceSecurityContect. All i want-include WindowsIdentity in sec.context, meanwhile PrimaryIdentity is X509CertIdentity.
ProfyTroll
So i need to know on serverside which domain user requested service operation.
ProfyTroll
A: 

Certificates are used for message signing,i.e. proving that other side is either real client or service (man-in-the-middle). But authorization in system being developed partially relies on WindowsIdentity in ServiceSecurityContect. All i want-include WindowsIdentity in sec.context, meanwhile PrimaryIdentity is X509CertIdentity. So i need to know on serverside which domain user requested service operation.

ProfyTroll
+1  A: 

Try this link re: Impersonation:

http://msdn.microsoft.com/en-us/library/ms730088.aspx

section on - "Mapping a Client Certificate to a Windows Account", seems like what you're after.

with config on client:

authentication mapClientCertificateToWindowsAccount="true"

Client code:

' Create a binding that sets a certificate as the client credential type.

Dim b As WSHttpBinding = New WSHttpBinding()

b.Security.Message.ClientCredentialType = MessageCredentialType.Certificate

' Create a service host that maps the certificate to a Windows account.

Dim httpUri As Uri = New Uri("http://localhost/Calculator")

Dim sh As ServiceHost = New ServiceHost(GetType(HelloService), httpUri)

sh.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = True

Hope that helps

Tanner
thanks, you have shown me right direction
ProfyTroll
Glad to be of assistance, WCF can be painful at times!
Tanner
A: 

Tanner, thanks a lot. Though in my case some additional huge amount of work required, because i use certificates which are not in AD storage. If i finish this task, i will gladly write a big article in CodeProject. The main idea was to create new TokenAuthenticator (something like X509CustomSecurityTokenAuthenticator, which will get WindowsIdentity not from Kerberos by certificate, but simple WindowsIdentity.GetCurrent() ). Then create custom ClientCredentialsSecurityTokenManager. Enough of Reflector and brain work, you know... But it look there is no easier way.

ProfyTroll