azurehttpsacs

Calling relying party over HTTPS and token encryption


I have an issue with the Windows Azure ACS and I can't quite determine if it's supposed to be that way, or if there's an error in my code.

I have a number of relying parties configured in the ACS and all of them are configured with HTTPS. Every service is configured in such a way that Token Encryption is required. For this, I've uploaded a certificate created using MakeCert.exe.

When the client communicates with the relying party, I add the public part of the certificate as the service certificate and I add the subject name as a DnsIdentity:

var identity = EndpointIdentity.CreateDnsIdentity( GetClientCertificateSubjectName() );
var serviceEndpointAddress = new EndpointAddress( new Uri( _serviceAddress ), identity );

// Creation of channel factory

if( channelFactory.Credentials != null ) {
  channelFactory.Credentials.ServiceCertificate.DefaultCertificate = GetClientCertificate();
  channelFactory.Credentials.ClientCertificate.Certificate = GetServiceIdentityCertificate();
}

Here's the thing: when I call the relying party over HTTPS, then I can skip the creation of the EndpointIdentity and then the relying party will give me a correct answer. I can also skip setting the ServiceCertificate.DefaultCertificate property or set a totally random certificate, and the relying party will still give me a correct answer.

When calling over HTTP, doing any of the above will result in the ACS erroring out with messages indicating that I haven't used the correct certificates. In short: when calling over HTTP, I can only communicate with the correct client certificate. I expected that this was the case for HTTPS as well.

I can imagine that the ChannelFactory<T> or the ACS is smart enough to detect that HTTPS is used and that the configured encryption is skipped, in favour of SSL encryption. Sadly, I can't find any documentation that supports this idea.

My question is: Is it normal to ignore the EndpointIdentity and certificates when calling a relying party over HTTPS? Or do I need additional configuration to make this work?

Thanks in advance!


Solution

  • The amount of information I gave turned out to be insufficient to properly answer the question. It turned out that it was all in the bindings we were creating. It creates a binding with the following piece of code:

    public static Binding CreateServiceBinding( string acsCertificateEndpoint, string bindingNameSpace, bool useSsl ) {
      var binding = new IssuedTokenWSTrustBinding( CreateAcsCertificateBinding(), new EndpointAddress( acsCertificateEndpoint ) );
    
      if( useSsl ) {
        binding.SecurityMode = SecurityMode.TransportWithMessageCredential;
      }
    
      if( !string.IsNullOrWhiteSpace( bindingNameSpace ) ) {
        binding.Namespace = bindingNameSpace;
      }
    
      return binding;
    }
    
    public static CertificateWSTrustBinding CreateAcsCertificateBinding() {
      return new CertificateWSTrustBinding( SecurityMode.TransportWithMessageCredential );
    }
    

    That results in the following:

    1. If it is http communication, it goes through MutualCertificate authentication mode flow and it is applied on the message layer only. That is why client is mandated to present a client certificate. This binding element creates an asymmetric security binding element that is configured to require certificate-based client authentication as well as certificate-based server authentication.
    2. If it is https communication, it goes through the CertificateOverTransport authentication mode flow and it is applied on transport layer only. That’s why even though client certificate is not presented, it works. This binding element expects the transport to provide server authentication as well as message protection (for example, HTTPS).

    For more information on the security modes, check out the following links:

    https://msdn.microsoft.com/en-us/library/ms733098%28v=vs.110%29.aspx https://msdn.microsoft.com/en-us/library/ms731074%28v=vs.110%29.aspx

    Hope this helps someone!