Tuesday, March 14, 2006 4:41 PM cibrax

Implementing a Secure token service with WCF

I decided to write this post in order to show some necessary steps to build a Secure Token Service (STS) with the latest WCF CTP.

There is a lot of messages in the newsgroups from people with problems to implement a solution like this, so they may find this article useful.

The image below illustrates a generic architecture for an application that uses a brokered authentication with a STS.

 

 

 

 

 

The client application is using a customBinding to secure the communication with the STS and a wsFederationHttpBinding to do that with the target service. In this case, the wsFederationHttpBinding includes the token obtained from the STS in the request message for the service.

As you can see in the image, the following steps are performed in order to execute the final service:

 

1. The client application sends a RequestSecurityTokenMessage (RST) to the STS according to WS-Trust specification.

2. The STS receives a RST message, extract some information from it and creates a token. After that, it sends back a RequestSecurityTokenResponseMessage (RSTR) with the new token.

3. The client application sends a request message to the service and includes the token obtained from the STS.

4. The service executes the service and returns the response to the client application. The token is used to build the security claims for the authenticated user before calling the service method.

 

 

WCF configuration for the client application

 

 

<system.serviceModel >

        <client>

            <!-- Endpoint configuration -->

            <endpoint name="clientendpoint" address="http://localhost/WCFSampleService/service.svc"

                binding="wsFederationHttpBinding"

                contract="IHelloWorld"

                behaviorConfiguration="ServiceBehavior"

                bindingConfiguration="ServiceBinding">

                <identity>

                    <dns value="WCFQuickstartServer"/>

                </identity>

            </endpoint>

        </client>

 

        <bindings>

 

            <!-- Binding used to secure the communication with the STS -->

            <customBinding>

                <binding name="UsernameBinding">

                    <security authenticationMode="UserNameForCertificate"

                            requireSecurityContextCancellation ="false"

                            requireSignatureConfirmation="false"

                            messageProtectionOrder ="SignBeforeEncryptAndEncryptSignature"

                            requireDerivedKeys="true">

                    </security>

                    <httpTransport/>

                </binding>

            </customBinding>

 

            <!-- Binding used to secure the communication with the service -->

            <wsFederationHttpBinding>

                <binding name="ServiceBinding">

                    <security mode="Message">

                        <message issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" negotiateServiceCredential="false">

                            <!-- Uncomment this section to ask for specific claims to the STS

                            <claims>

                                <add claimType  ="http://schemas.microsoft.com/ws/2005/05/identity/claims/EmailAddress"/>

                                <add claimType  ="http://schemas.microsoft.com/ws/2005/05/identity/claims/GivenName"/>

                                <add claimType  ="http://schemas.microsoft.com/ws/2005/05/identity/claims/Surname"/>

                            </claims>

                            -->

 

                            <!-- Information related to the Secure token service -->

                            <issuer address="http://localhost/WCFSecurityTokenService/service.svc" bindingConfiguration="UsernameBinding"

                                binding="customBinding">

                                <identity>

                                    <dns value="WCFQuickstartServer"/>

                                </identity>

                            </issuer>

                        </message>

                    </security>

                </binding>

            </wsFederationHttpBinding>

        </bindings>

        <behaviors>

            <!-- Credentials configuration -->

            <behavior name="ServiceBehavior">

                <clientCredentials>

                    <serviceCertificate>

                        <defaultCertificate findValue="CN=WCFQuickstartServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>

                        <authentication revocationMode="NoCheck" certificateValidationMode="None"></authentication>

                    </serviceCertificate>

                </clientCredentials>

            </behavior>

        </behaviors>

 </system.serviceModel>

 

 

Some notes about the configuration above:

 

1. The communication between the client and the STS is secured by a UsernameForCertificate binding. That is, the STS expects a UsernameToken as client token (Token used to authenticate the client)  and a X509Certificate as service token (Token used to encrypt and sign the message).

2. The "issueTokenType" attribute in the "message" element specifies the token type expected by the Service. The client application will include that value in the RST message and therefore the STS will know what kind of token it must create. If the STS does not support that kind of token, then it will return a fault message. For this sample, the client application is asking for a SAML token.

3. The "negotiateServiceCredential" attribute in the "message" element specifies if the client must interchange additional messages with the STS in order to negotiate the service certificate. I will give more information about this flag later in the next paragraphs.

4. The "address" attribute in the "issuer" element specifies the address of the STS. WCF also includes a default implementation of a InfoCard STS. In order to use that STS, you must configure the address http://schemas.microsoft.com/ws/2005/05/identity/issuer/self.

5. The claims element is only valid for SAML tokens. It specifies what claims are expected in the token.

 

 

WCF configuration for the STS

 

 

<system.serviceModel>

        <services>

            <service behaviorConfiguration="ServiceBehavior" name="MySecureTokenService">

                <endpoint binding="customBinding" address="" bindingConfiguration="ServiceBinding" contract="IMySecureTokenService"></endpoint>

            </service>

        </services>

        <bindings>

            <customBinding>

                <binding name="ServiceBinding">

                    <security authenticationMode="UserNameForCertificate"

                            requireSecurityContextCancellation ="false"

                            requireSignatureConfirmation="false"

                            messageProtectionOrder ="SignBeforeEncryptAndEncryptSignature"

                            requireDerivedKeys="true">

                    </security>

                    <httpTransport/>

                </binding>

            </customBinding>

        </bindings>

        <behaviors>

            <behavior name="ServiceBehavior" returnUnknownExceptionsAsFaults="false">

                <serviceCredentials>

                    <serviceCertificate findValue="CN=WCFQuickstartServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>

                    </serviceCredentials>

            </behavior>

        </behaviors>

 </system.serviceModel>

 

 

In this case, the STS implementation is in the class "MySecureTokenService" and it exposes the contract "IMySecureTokenService".

The binding configuration is similar to the configuration in the client.

 

 

WCF configuration for the Service

 

 

<system.serviceModel>

        <services>

            <service

                behaviorConfiguration="ServiceBehavior"

                name="SampleService.HelloWorldService">

                <endpoint binding="wsFederationHttpBinding"

                    address=""

                    bindingConfiguration="ServiceBinding"

                    contract="SampleService.IHelloWorld"/>

            </service>

        </services>

        <bindings>

            <wsFederationHttpBinding>

                <binding name="ServiceBinding">

                    <security mode="Message">

                        <message issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1" negotiateServiceCredential="false">

                            <!--<claims>

                                <add claimType="http://schemas.microsoft.com/ws/2005/05/identity/claims/EmailAddress"/>

                                <add claimType="http://schemas.microsoft.com/ws/2005/05/identity/claims/GivenName"/>

                                <add claimType="http://schemas.microsoft.com/ws/2005/05/identity/claims/Surname"/>

                            </claims>-->

                            <issuer address="http://localhost/SamlSecurityTokenService/SamlTokenIssuer.ashx" bindingConfiguration="UsernameBinding" binding="customBinding">

                                <identity>

                                    <dns value="WCFQuickstartServer"/>

                                </identity>

                            </issuer>

                        </message>

                    </security>

                </binding>

            </wsFederationHttpBinding>

        </bindings>

        <behaviors>

            <behavior name="ServiceBehavior" returnUnknownExceptionsAsFaults="false">

                <serviceCredentials>

                    <serviceCertificate findValue="CN=WCFQuickstartServer" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName"/>

                </serviceCredentials>

 

            </behavior>

        </behaviors>

 </system.serviceModel>

 

 

Again, the configuration of the wsFederationHttpBinding is identical to the configuration in the client application.

 

 

STS implementation

 

 

The contract for the STS is quite simple and looks as follows:

 

 

[ServiceContract]

public interface IMySecurityTokenService

{

    [OperationContract(Action = "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue",

                      ReplyAction = "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue")]

        Message IssueToken(Message rstMessage);

}

 

 

It exposes one method "IssueToken" for the action "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue" that is part of the WS-Trust specification.

 

 

public class MySecureTokenService : IMySecurityTokenService

{

        public MySecureTokenService()

        {

        }

 

        public Message IssueToken(Message rstMessage)

        {

            RequestSecurityToken rst = RequestSecurityToken.CreateFrom(rstMessage.GetReaderAtBodyContents());

 

            SecurityToken issuedToken = null;

 

            //Code to create the token goes here ......

 

            // setup RSTR

            RequestSecurityTokenResponse rstr = new RequestSecurityTokenResponse();

 

            //attach security token to RSTR

            rstr.RequestedSecurityToken = issuedToken;

            rstr.TokenType = rst.TokenType;

 

            // send RSTR

            rstr.MakeReadOnly();

            Message rstrMessage = Message.CreateMessage(rstMessage.Version, "http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue", rstr);

            rstrMessage.Headers.RelatesTo = rstMessage.Headers.MessageId;

 

            return rstrMessage;

        }

    }

 

 

The STS implementation receives a generic message containing the RST and creates a token using that information.
At the end, it returns a message containing the RSTR with the issued token. For this sample, I have omitted the code to build the token since you can create any token there (UsernameToken, SamlSecurityToken, etc)  depending on the value of the property "rst.TokenType".

 

 

Avoiding the service credential negotiation

 

WCF provides a new feature to negotiate the service credentials for a service.

When this feature is turned on, the client does not need to manually configure or specify the service credentials for the service. As a result, the client application interchanges an additional message with the service using a a protocol called SP-Nego.

There is not any documentation or information around for that protocol, so it could be a problem if want to host your service in different platform like WSE. That is not a problem in WCF because the security bindings know how to interpret this message and create a response according to its content.

 

There are two ways to disable this feature in WCF:

 

1. Secure the communication with a customBinding since it does not provide this feature.

2. Turn off the attribute "negotiateServiceCredential" in the "message" element for the bindings wsFederationHttpBinding or wsHttpBinding.

 

UPDATE: The STS implementation code is available in this post http://weblogs.asp.net/cibrax/archive/2006/09/08/SAML-_2D00_-STS-implementation-for-WCF.aspx

Filed under: ,

Comments

# Sam Gentile blog

Thursday, March 16, 2006 12:30 PM by TrackBack

Sam Gentile blog

# Robert Hurlbut blog

Thursday, March 16, 2006 12:32 PM by TrackBack

Robert Hurlbut blog

# re: Implementing a Secure token service with WCF

Tuesday, March 21, 2006 12:49 PM by Anthony Yott

Pablo,

Can you provide a zip file with the code or is this from one of the samples included in the WCF examples?

# re: Implementing a Secure token service with WCF

Tuesday, March 21, 2006 12:54 PM by Cibrax

Hi Anthony,
No, it is a custom sample. Send me your mail address if you want the code.

Thanks
Pablo.

# re: Implementing a Secure token service with WCF

Thursday, April 06, 2006 10:00 AM by Cooly

Hi,

Is it possible to use TCP transport between the client and the service instead of the default Http transport?

What about callbacks from the server to the client? how is this being handled?

Thanks,
Cooly.

# re: Implementing a Secure token service with WCF

Thursday, April 06, 2006 10:41 AM by Cibrax

Hi Cooly,

It is not possible to use TCP transport, that is why the WCF team renamed the federation binding to "wsFederationHttpBinding".

Sorry, I am not sure to understand your question about the callbacks.

Thanks
Pablo.

# How To: STS/Windows Authentication with ADAM/AD, Roles in AzMan with WCF

Friday, May 26, 2006 1:55 PM by Sam Gentile

The last week I have been connecting up my seamless Single-Sign On with Windows Authentication scheme...

# .NET Resources

Saturday, May 27, 2006 6:47 AM by mattonsoftware.com

The following links to .NET resources have been collated over time with the assistance of colleagues.&amp;nbsp;...

# re: Implementing a Secure token service with WCF

Monday, June 12, 2006 11:47 AM by AndrewSeven

Hi,

Is this sample still good if we are using the May 22 version of WinFx?

Thanks.

# re: Implementing a Secure token service with WCF

Saturday, August 19, 2006 4:37 AM by Ray

Hi, Pablo Could you send the zip file with the code to me? My Email is: bihpgh20@gmail.com. I must implement STS with WCF in my project, I think your code would help me. Thanks.

# re: Implementing a Secure token service with WCF

Tuesday, August 29, 2006 8:48 AM by L.Liu

Hi Pablo, I have implemented your STS sample with the latest CTP - June CTP. The STS works fine and the client can get a SAML security token from the STS. However, the service does not accept the message with the SAML token and throws the exception "The security protocol cannot verify the incoming message." all the time. This exception takes place as the client try to set up a secure session with the service. Do you know to what this exception may be due? Thanks a lot! L.Liu

# SAML - STS implementation for WCF

Friday, September 08, 2006 10:31 AM by Pablo M. Cibraro (aka Cibrax)

I finally decided to publish a STS implementation for WCF. (It isbased onone of my previous posts, &quot;Implementing

# New and Notable 112

Wednesday, September 13, 2006 9:09 AM by Sam Gentile

Wow, Scott Hanselman recommends these and then I don't have one since July 21st. As usual, I am busy

# re: Implementing a Secure token service with WCF

Monday, October 02, 2006 12:25 PM by sabadin enrico

Hi, before getting into the federation stuff I wanted to set up a security sample that used the IssuedToken clientcredentialtype I've setup a client a server and STS i can successfully call the sts directly, however when the infrastructure tries to contact the STS the server raise a security exception Supporting token signatures not expected. at System.ServiceModel.Security.ReceiveSecurityHeader.ProcessSupportingSignature( DO you have any working sample of using the the IssuedToken clientcredentialtype ? thank in advance best regards Enrico Sabbadin

# re: Implementing a Secure token service with WCF

Monday, October 02, 2006 12:33 PM by cibrax

Hi Enrico, I do not have any working sample to show a federation scenario. The WCF SDK already provides a sample showing that scenario, I recommend you to take a look there.

# re: Implementing a Secure token service with WCF

Monday, December 11, 2006 6:42 PM by Vicel

Hi Pablo,

I wonder if there is a way to make a STS work like:

Client sends RST using username token

STS returns RSTR with a list of values to select from

Client returns RSTR with a value from the list

STS sends SamlToken including the selected value

I was not able to find anything about that  :(

May be you have an idea where i can start from?

Thanks

# re: Implementing a Secure token service with WCF

Thursday, March 01, 2007 2:51 AM by mmkk

based on your figure-1, in step 1,can i just use wsHttpBinding with custom username & password validator behavior?

# re: Implementing a Secure token service with WCF

Thursday, March 01, 2007 4:05 AM by mmkk

in figure-1, can i just use wsHttpBinding with custom username & password validator behavior to replace the original customBinding?

# re: Implementing a Secure token service with WCF

Thursday, March 01, 2007 6:29 AM by mmkk

In figure-1, is it possible to use wsHttpBinding with custom username & password validator behavior to replace the original customBinding?

# re: Implementing a Secure token service with WCF

Thursday, March 01, 2007 4:31 PM by cibrax

Hi mmkk,

Yes, you can use any binding there, the same for the custom username & pasword validator. (My sample shows a custom binding but it can be easily replaced). I only decided to use a custom binding because it can be easily configured with any setting.

Regards

Pablo.

# re: Implementing a Secure token service with WCF

Wednesday, March 28, 2007 4:50 AM by Frits

Hello,

I've tried to work out this solution, but i didn't work. My application didn't recognize equestSecurityToken.CreateFrom and rstr.MakeReadOnly(); Is it possible for you to send me a working demo?

Regards Frits

# re: Implementing a Secure token service with WCF

Sunday, June 03, 2007 7:58 AM by hitshay

Can i get the source as a zip please.

This is great, something I have been looking for .. Also was wondering if STS can be done  using just Windows (kerbrose) and not use x509 certs at all.. if you could you provide some guidance.

Hits

# re: Implementing a Secure token service with WCF

Friday, July 06, 2007 1:39 PM by Eric Ramseur

Keep up the god work Pablo.  Drop me the code also when you get a chance please ( ramseur[at]gmail[dizot]com )

It would be gold to have a WCF STS to authenticate clients of any environment to consume our services.  I can use http so thats not a problem.

Regards

ramseur

# Click here

Sunday, July 22, 2007 2:12 AM by Click here

The period of continually digging up credible conceptions on this affair are finished.

# re: Implementing a Secure token service with WCF

Thursday, August 23, 2007 2:40 AM by Suresh

hi i need source code fort his article

# Single Sign-On scenarios with Federation

Monday, February 11, 2008 10:24 AM by Pablo M. Cibraro (aka Cibrax)

Before reading this post, if you know the basic concepts and ideas behind the implementation of an STS

# My Resume - Pablo M. Cibraro (aka Cibrax)

Sunday, February 17, 2008 6:43 PM by My Resume - Pablo M. Cibraro (aka Cibrax)

Pingback from  My Resume - Pablo M. Cibraro (aka Cibrax)

# re: Implementing a Secure token service with WCF

Friday, June 13, 2008 4:44 AM by Ranju

Hi Pablo,

I am trying to implement your STS for my university project. The Relying Patry is showing a strange error that the "token requested and can not be issued...."

this is showed in the browser and it is too long. when I looked at the massege log i found this following error:

"The message could not be processed because the action 'schemas.xmlsoap.org/.../Issue' is invalid or not recognized"

could you please help me out in this?

cheers,

Ranju

# re: Implementing a Secure token service with WCF

Friday, June 13, 2008 11:29 AM by cibrax

Hi Ranju, are you trying to access the service from a web browser ?. This implementation only works if the client application knows how to talk WS-Trust (That could be WCF or any other implementation).

Thanks

Pablo.

# re: Implementing a Secure token service with WCF

Wednesday, June 18, 2008 4:14 AM by AKS

Hi,

  Many thanks in advance

  I  need code in zip for plz send it to me

  My mail id is atul.suyal@nechclst.in

# re: Implementing a Secure token service with WCF

Sunday, August 03, 2008 5:12 AM by username and password

Hi ,

I wonder how to enable the username and passowrd authincation , I don't need to use the certificates

Leave a Comment

(required) 
(required) 
(optional)
(required)