WCF Federation with ACS v2

Recently I worked on WCF Federation with ACS v2. The developer who approached me was trying to authenticate the WCF service (on-premise/azure hosted) using Azure Appfabric Access Control (ACS ).  He wanted to use an Identity provider (Windows LiveID or Facebook) as listed in the msdn magazine article below.

Re-Introducing the Windows Azure AppFabric Access Control Service - https://msdn.microsoft.com/en-us/magazine/gg490345.aspx

By Design,  ACS supports active (WCF) federation with 3rd party identity providers such as ADFS, however LiveID does not offer an active endpoint. You can only do LiveID authentication through ACS using passive (browser redirect based) based federation. This works great for ASP.Net but not for WCF due to the design limitation mentioned.

(Source: https://social.msdn.microsoft.com/Forums/en-NZ/windowsazuresecurity/thread/f3bc5461-cdfe-4f69-a3ac-9a743d12ca85)

So the only option that WCF has for federation is to using ACS Service. Zulfiqar has a good blog on this - https://zamd.net/2010/10/05/web-services-federation-with-acs-v2/

With the help from this blog, I was able to use ACS hosted STS and authenticate  to on-premise WCF service using ACS Service Identities (username/certificate) as the client credentials. You will basically pass through all the claims. All you have to do to  switch between different client authentications is change bindings for ACS STS, which is listed under secureConversationBootstrap in customBinding section for the on-remise/azure
WCF service  as explained in the above blog. As you can see below, I've enabled username authentication.

                                 <!--<issuer address=https://alphawif.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric binding="customBinding"
                                           bindingConfiguration="https://alphawif.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric"/>

                                    <issuerMetadata address="https://alphawif.accesscontrol.windows.net/v2/wstrust/mex"/>-->

                                 <issuer address=https://alphawif.accesscontrol.windows.net/v2/wstrust/13/username bindingConfiguration="https://alphawif.accesscontrol.windows.net/v2/wstrust/13/username"
                                 binding="ws2007HttpBinding" />

                                 <!--<issuer address="https://alphawif.accesscontrol.windows.net/v2/wstrust/13/certificate bindingConfiguration="https://alphawif.accesscontrol.windows.net/v2/wstrust/13/certificate"
                                       binding="ws2007HttpBinding" />-->

Here's the binding that will be picked to connect to ACS in order to authenticate with username.

                                  <ws2007HttpBinding>
                                       <binding name="https://alphawif.accesscontrol.windows.net/v2/wstrust/13/username"
                                        closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00"
                                        sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false"
                                        hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
                                        maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8"
                                        useDefaultWebProxy="true" allowCookies="false">
                                       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                                       <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
                                       <security mode="TransportWithMessageCredential">
                                            <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
                                            <message clientCredentialType="UserName" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="false" />
                                       </security>
                                       </binding>
                                    <ws2007HttpBinding>

Zulfiqar's blog explains username authentication, certificate authentication is no different. You have to add a certificate for the client authentication as shown in the screenshots below.

 

 

Once everything is set, you provide the client credentials like you do to while calling any other WCF service.

Username Authentication:

            var client = new ServiceReference1.ServiceClient();

            client.ClientCredentials.UserName.UserName = "user";

           client.ClientCredentials.UserName.Password = "pwd#123";

           Console.WriteLine(client.GetData(33));

Certificate Authentication:

           var client = new ServiceReference1.ServiceClient();

           client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "DefaultApplicationCertificate");

           Console.WriteLine(client.GetData(33));

I tried issued token (symmetric -  https://alphawif.accesscontrol.windows.net/v2/wstrust/13/issuedtoken-symmetric) but ran into some issue. I still have to figure out how to make it work , hopefully will come in my next blog part for this topic.

The sample is uploaded for your convenience. Otherwise, the blog (https://zamd.net/2010/10/05/web-services-federation-with-acs-v2/ ) itself let's you create a sample yourself very quickly.

Note: alphawif is my ACS namespace, this is something you need to take care of when you use the sample.

WCFFederation-ACSv2.zip