How do I configure WCF to use a custom Realm in URN format with Azure ACS?

ε祈祈猫儿з 提交于 2019-12-07 14:47:14

问题


How do I make my WCF client authenticate using the ACS to my internally hosted WCF service? The issue revolves around setting a custom Realm (which I can't figure out how to set.)

My ACS is configured similar to the ACS Samples however the "Realm" is defined as shown below.

Excerpt from Azure ACS Configuration page



Client Side Code

      EndpointAddress serviceEndpointAddress = new EndpointAddress( new Uri( "http://localhost:7000/Service/Default.aspx"),  
                                                                      EndpointIdentity.CreateDnsIdentity( GetServiceCertificateSubjectName() ),
                                                                      new AddressHeaderCollection() );

        ChannelFactory<IStringService> stringServiceFactory = new ChannelFactory<IStringService>(Bindings.CreateServiceBinding("https://agent7.accesscontrol.appfabriclabs.com/v2/wstrust/13/certificate"), serviceEndpointAddress );

        // Set the service credentials.
        stringServiceFactory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
        stringServiceFactory.Credentials.ServiceCertificate.DefaultCertificate = GetServiceCertificate();

        // Set the client credentials.
        stringServiceFactory.Credentials.ClientCertificate.Certificate = GetClientCertificateWithPrivateKey();

Server Side Code

 string acsCertificateEndpoint = String.Format( "https://{0}.{1}/v2/wstrust/13/certificate", AccessControlNamespace, AccessControlHostName );

        ServiceHost rpHost = new ServiceHost( typeof( StringService ) );

        rpHost.Credentials.ServiceCertificate.Certificate = GetServiceCertificateWithPrivateKey();

        rpHost.AddServiceEndpoint( typeof( IStringService ),
                                   Bindings.CreateServiceBinding( acsCertificateEndpoint ),
                                   "http://localhost:7000/Service/Default.aspx"
                                   );

        //
        // This must be called after all WCF settings are set on the service host so the
        // Windows Identity Foundation token handlers can pick up the relevant settings.
        //
        ServiceConfiguration serviceConfiguration = new ServiceConfiguration();
        serviceConfiguration.CertificateValidationMode = X509CertificateValidationMode.None;

        // Accept ACS signing certificate as Issuer.
        serviceConfiguration.IssuerNameRegistry = new X509IssuerNameRegistry( GetAcsSigningCertificate().SubjectName.Name );

        // Add the SAML 2.0 token handler.
        serviceConfiguration.SecurityTokenHandlers.AddOrReplace( new Saml2SecurityTokenHandler() );

        // Add the address of this service to the allowed audiences.
        serviceConfiguration.SecurityTokenHandlers.Configuration.AudienceRestriction.AllowedAudienceUris.Add( new Uri( "urn:federation:customer:222:agent:11") );

        FederatedServiceCredentials.ConfigureServiceHost( rpHost, serviceConfiguration );

        return rpHost;

... where urn:federation:customer:222:agent:11 is the Relying party ID

... and http://localhost:7000/Service/Default.aspx is the location I want the above WCF / WIF client to bind to once the ACS authentication is made.

Question

How do I edit the code above so that the client and server will both operate against a certain port (localhost:700) and also with a realm of urn:federation:customer:222:agent:11

I think I have the server code correct; however how do I set AudienceRestriction on the client?


回答1:


Your server side code looks fine, but Sixto is right about standard channel factories. Luckily, you can request a security token from ACS yourself using a WSTrustChannelFactory. In the context of your sample, your code would look like this:

//
// Get the token from ACS
//
WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(
    Bindings.CreateAcsCertificateBinding(),
    new EndpointAddress( acsCertificateEndpoint ) );
trustChannelFactory.Credentials.ClientCertificate.Certificate = GetClientCertificateWithPrivateKey();

RequestSecurityToken rst = new RequestSecurityToken()
{
    RequestType = RequestTypes.Issue,
    AppliesTo = new EndpointAddress( new Uri( "urn:federation:customer:222:agent:11" ) ),
    KeyType = KeyTypes.Symmetric
};

WSTrustChannel wsTrustChannel = (WSTrustChannel)trustChannelFactory.CreateChannel();
SecurityToken token = wsTrustChannel.Issue( rst );

//
// Call StringService, authenticating with the retrieved token
//
WS2007FederationHttpBinding binding = new WS2007FederationHttpBinding( WSFederationHttpSecurityMode.Message );
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = false;

ChannelFactory<IStringService> factory = new ChannelFactory<IStringService>(
    binding,
    new EndpointAddress(
            new Uri( ServiceAddress ),
            EndpointIdentity.CreateDnsIdentity(GetServiceCertificateSubjectName()) ) );
factory.ConfigureChannelFactory<IStringService>();
factory.Credentials.SupportInteractive = false;
factory.Credentials.ServiceCertificate.DefaultCertificate = GetServiceCertificate();

IStringService channel = factory.CreateChannelWithIssuedToken<IStringService>( token );
string reversedString = channel.Reverse( "string to reverse" );



回答2:


Some answers may be better late than never. I've been unable to find any official documentation on using WCF in this fashion, however in reading the WS-Trust papers and the MSDN documentation on configuration, I have come up with the following solution which appears to work.

From the service consuming client's config at configuration/system.serviceModel/bindings/ws2007FederationHttpbinding/binding/security/message. It overrides the AppliesTo element of the token request message.

<tokenRequestParameters>
  <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
    <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
      <Address>urn:x-Organization:Testing</Address>
    </EndpointReference>
  </wsp:AppliesTo>
</tokenRequestParameters>

Adding this same snippet in the configuration of the service, will cause the Service Reference utility to include this within the trust:SecondaryParameters element of the service client. It must be moved into the parent tokenRequestParameters element to work properly.




回答3:


Haven't actually tried the approach referenced in this MSDN article but from reading it sounds like the standard channel factory doesn't have the right hooks to do what you want. The WSTrustChannelFactory is built for WIF & SAML but I'm not familiar enough with ACS to determine if it is applicable. This article in this six-part series will probably be worthwhile perusing too.



来源:https://stackoverflow.com/questions/5598388/how-do-i-configure-wcf-to-use-a-custom-realm-in-urn-format-with-azure-acs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!