3
votes

I'm currently using ADFS as a security token service. I want to federate the WCF service with ADFS. I created WCF service and added the STS reference of ADFS by using Federation utility.

Inorder to use the federated wcf service, I created WPF application and added service reference. I called the service api using following code.

var client = new SecureWpfApplication.ServiceReference1.Service1Client();

Uri uri = new Uri("http://tempuri.org/");
ICredentials credentials = CredentialCache.DefaultCredentials;
NetworkCredential credential = credentials.GetCredential(uri, "Basic");

client.ClientCredentials.Windows.ClientCredential = credential;

client.ClientCredentials.SupportInteractive = false;

client.GetData(323);

I got the error "The binding to use to communicate to the federation service at 'https://{ADFS server}/adfs/services/trust/13/usernamemixed' is not specified.

How to resolve this?

I created the wcf service configuration like

<services>
  <service name="SecureWcfService.Service1" behaviorConfiguration="SecureWcfService.ServiceBehaviour">
    <endpoint address="https://wcfserver/SampleWcfService/Service1.svc" binding="ws2007FederationHttpBinding" contract="SecureWcfService.IService1" bindingConfiguration="SecureWcfService.IService1_ws2007FederationHttpBinding" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
<serviceBehaviors>
    <behavior name="SecureWcfService.ServiceBehaviour">
      <federatedServiceHostConfiguration name="SecureWcfService.Service" />
      <serviceMetadata httpGetEnabled="true" />
      <serviceCredentials>
        <serviceCertificate findValue="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
      </serviceCredentials>
    </behavior>
</serviceBehaviors>
</behaviors>
<extensions>
    <behaviorExtensions>
        <add name="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </behaviorExtensions>
</extensions>
<bindings>
<ws2007FederationHttpBinding>
    <binding name="SecureWcfService.IService1_ws2007FederationHttpBinding">
        <security mode="Message">
            <message>
                <issuerMetadata address="https://adfsserver/adfs/services/trust/mex" />
                <claimTypeRequirements>
                    <add claimType="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="true" />
                    <add claimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" isOptional="true" />
                </claimTypeRequirements>
            </message>
        </security>
    </binding>
</ws2007FederationHttpBinding>
</bindings>
<microsoft.identityModel>
    <service>
        <audienceUris>
            <add value="https://wcfserver/SecureWcfService/Service1.svc" />
        </audienceUris>
        <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <trustedIssuers>
                <add thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="http://asfsserver/adfs/services/trust" />
                <add thumbprint="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" name="http://adfsserver/adfs/services/trust" />
            </trustedIssuers>
        </issuerNameRegistry>
        <certificateValidation certificateValidationMode="None" />
    </service>
</microsoft.identityModel>   

I got the error "The binding to use to communicate to the federation service at 'https://adfsserver.com/adfs/services/trust/13/usernamemixed' is not specified.

2

2 Answers

1
votes

It seems to me as if you need to follow some more tutorials and/or read some more web pages before you continue with your WCF Service. How to use WCF is far too broad a topic for this website, but in basic, you need to define a binding element in your config files that specifies that you want to use the Federation Service in your WCF Service.

Have a good, long read of the How to: Create a WSFederationHttpBinding page on MSDN. From the linked page:

Create a element in the bindings section that can be used to communicate with the security token service. For more information about creating a binding, see How to: Specify a Service Binding in Configuration.

You could also read the (WCF) Getting Started Tutorial page on MSDN for some further background reading.

0
votes

The way I got this to work for me was by not using the configuration generated by adding the service reference at all and instead do it all programatically. This is what worked for me:

//Helper to get SAML token from STS
public static SecurityToken GetSamlToken(string realm, string trustUrl, string userName, string password, string keyType, SecurityToken actAsToken = null)
{
    var factory = new WSTrustChannelFactory(
        //You will need to use WindowsWSTrustBinding here I think
        new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
        trustUrl
    );

    factory.TrustVersion = TrustVersion.WSTrust13;

    //Here you would use Windows credentials instead of username/password
    factory.Credentials.UserName.UserName = userName;
    factory.Credentials.UserName.Password = password;

    var rst = new RequestSecurityToken
    {
        RequestType = RequestTypes.Issue,
        TokenType = TokenTypes.Saml2TokenProfile11,
        KeyType = keyType, //I used KeyTypes.Bearer here
        AppliesTo = new EndpointReference(realm)
    };

    if (actAsToken != null)
    {
        rst.ActAs = new SecurityTokenElement(actAsToken);
    }

    var token = factory.CreateChannel().Issue(rst);

    return token;
}

var token = GetSamlToken(...);

var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.Message); 
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;

var factory = new ChannelFactory<IService1>(binding, new EndpointAddress(serviceEndpoint));

ChannelFactoryOperations.ConfigureChannelFactory<IService1>(factory);

factory.Credentials.SupportInteractive = false;
factory.Credentials.UseIdentityConfiguration = true;

var channel = factory.CreateChannelWithIssuedToken<IService1>(token);

channel.CallSomeServiceMethod();