SAML - STS implementation for WCF

I finally decided to publish a STS implementation for WCF.  (It is based on one of my previous posts, "Implementing a Secure token service with WCF")

I received a lot of mails from people asking me for a official version of that code, so here it is. I implemented this STS using latest WCF release (September CTP).

All the classes previously provided by WCF to parse the RST and RSTR messages have gone (They are now private). I am not sure about the reason to take that decision, but it certainly complicates everything.

Therefore, a person developing a STS (me) has only two options:

  1. Create different classes to parse those messages. In other words, duplicate all the code previously provided by WCF
  2. Copy that code from the Martin Gudgin's implementation (Same as 1, but it makes your life easier).  

The code also includes the following features:

  • A custom Security Token Manager to reuse the same SAML token instance in different WCF channels. You can find more information about this solution in this post. This token manager is quite simple, and it only shows how this task can be performed. 
  • Two configuration files showing different binding settings between the client, the service and the STS. The first one uses the standar wsFederationHttpBinding, and the last one uses customBindings.

Download the code from this location

Update, feedback received from the WCF team regarding the RST/RSTR classes:

"We made those classes internal during our RC1 milestone because this will enable us to align the product better for future version of the WS-Trust protocol without exposing user to the necessary changes. When doing this we have actually changed our samples that show our Federation feature so that those samples now contain source code of RST/RSTR library that you can use to parse RST and RSTR messages in your application. For example the FederationHttp binding sample in the Windows SDK in WCF samples collection contains source code for parsing RST/RSTR messages. It can be found in TechnologySamples\Basic\Binding\WS\FederationHttp directory. I hope this answers your concern. Thanks, --Jan" 
 

 

28 Comments

  • Windows Complication Foundation. :P

    I guess all STS samples that had previously been provided are no longer not very useful.

    While I would tend to go with option 2, you could do option 1 using Reflector to copy the WCF code :S :(

  • OK, I'm confused about when to use the RST\RSTR code and when to use the custom security token manager to re-use saml token across channels. Can I use the custom security token manager in conjunction with Gudge's RST\RSTR implemenetation? Or does the custom security token assume I'm using wsFederationHttpBinding? If I can't use them in conjunction, is there a way to get at the saml assertion (and saml token) out of the RSTR? Basically, I want to be able to use the same SAML token across mutliple channels (thus your custom stm sample) but I also want to be able to access the SAML token on the client (to get custom information out of it, like user roles) I don't think I can use the wsFederationHttpBinding, I need to use a CustomBinding. So which route do I take???

  • Hi Al, the token manager to reuse the same security token across different channels does not depend on my STS implementation. I mean, you can use it with the Gudge's implementation without problems, just use the TokenCache project included in my code.

  • Forgive me for saying this -- but what a PITA. That's more code for me to maintain, and not trivial code at that. It's effectively a barrier to creating STS-based services. *sigh*

  • Sean: Well, yes. It is more code to maintain, but you probably will not touch the STS code unless you have some specific requeriments currently not supported by this solution.

  • Al, I think I misunderstood what you were trying to say me. It seems that you can not use the RST classes directly with my custom token manager. You have to use infrastructure provided by WCF for Federation Scenarios (wsFederationBinding).

  • OK, so I need to use the RST\RSTR classes because I want to call the STS ONLY, then later potentially call services. So how do I get the saml assertion\token out of the RSTR so I can use it on later calls?

  • Using your TokenCache, is there a way to get at the cached token from the client?

  • Al, if you want to use only the RST classes, you need to manually parse the RST/RSTS messages to get the SAML tokens. If you use the Federation Binding, it automatically negociates the token with the STS, creates and parses the RST/RSTS messages. My TokenCache solution is not intended to be used alone as you are doing now.

  • Right, but if I let WCF handle the parsing of RSTR and the calling of the STS and use your TokenCache, can I get at the security token stored in the token cache from the client?

  • Al. Yes, absolutely, my token cache is just a HashTable (It is something private). You should add some public API, so the client application can get the tokens from that cache. In other words, you should use a cache shared between the client application and the TokenCache implementation.

  • Hi Pablo,
    I really liked your STS implementation and used it for my "Diplomarbeit". That's basically the thesis of a german diploma-studies. I adapted your implementation to meet the requirements of a case study within the thesis.

    Coming to my question: Would it be ok for you if I publish an article in a magazine (likely in german language) about this? I would mention you there and mark that you created the basis for this solution, of course.

    Sorry that I did not use a private message, but this currently does not work on your server... Please contact me by mail (replace anti-spam by @):
    pollmeier[ANTI-SPAM]gmx.de

    Thanks in advance!
    Michael

  • I am new to WCF and WSE for the most part and I am trying to run this solution. I am getting the error below on a specific line of code. I have played around with the IIS VDir permissions and nothing changes. Any insight?

    line:
    string response = helloWorldService.HelloWorld("John Doe");

    error:

    An unhandled exception of type 'System.ServiceModel.Security.MessageSecurityException' occurred in mscorlib.dll

    Additional information: The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate,NTLM'.

  • Hi Pablo,
    I wanted to try out your STS example. I installed it and ran those setup batch scripts on my machine and it works great. I was wondering, is it possible to run it distributedly, meaning to put each (STS, service, client) on a different machine? How would I install those certificates then?
    Sorry if I am asking a dumb question... I am a WCF newbie.

    Regards,
    Dima

  • Hi Pablo:
    I posted a comment earlier and it did not show up, so I am re-posting.
    How do I enable Username and Password authentication (between the client and STS) on top of Client-STS Mutual Cert authentication ?
    Or is it just either or, but not both ?

    Thanks!

  • i'm also interested about Kumar's question, is it possible to post something about this, Pablo?

    thanks

  • Can you place the STS implementation Code where the client sends username and password to STS for validation

  • Pablo,

    I would like to deploy a SAML STS within a three tier architecture (web(asp.net) -> services -> database) and I would like to use a TCP transport between the web and services tier for performance reasons. I have been unable to get this to work with your sample and have yet to hear anything from Microsoft to indicate if this is a supported deployment scenario. Could you provide any insight on this?

    -Thanks in advance for your help.

  • Hi Mike,

    You can use TCP between the client (asp.net) and the STS for the interchange of the RST/RSTR messages, but you can only use http to send the SAML token (Or the negotiated token) to the service. They called WsHttpFederationBinding to that binding because only http is supported.

    Regards,
    Pablo.

  • hi Pablo,

    is it possible to send the STS extra parameter other then username/password pair. I mean somehow send own custom usernamesecure supporting token that I will be able to read in sts and authenticate my user. I m looking everywhere but could not find any solution. thanx

  • hi Pablo,

    is it possible to send the STS extra parameter other then username/password pair. I mean somehow send own custom usernamesecure supporting token that I will be able to read in sts and authenticate my user. I m looking everywhere but could not find any solution. thanx

  • Hi dejawoo,

    You can configure any security token for the communication between the client and the STS. In your case, you will need a custom token, since the username token only supports user and password.
    I will write a post about this topic in a couple of days.

    Pablo.

  • What are the terms of use for the published code?

  • Hi
    Can you please help me out to understand the sample project "STS Example" and how it has to be implemented and executed.

    Thanks
    Alice

  • I'm developing a WCF client server application for a client. The client has a SSO application where they use a web page to authenticate (no web service). My application strips out the SAML token from the returned page which is passed onto our web application for validation and strips out the required parameters.

    My question is can I use this SAML token as it is to secure the WCF channel?

  • HI,
    I have a requirement as dipicted below for authenticating client with his username/password. could you please help me out how i can use this STS implimentation and go ahead to support non federated perspective(to support non wcf clients).
    My requirement is:

    1.) The client should call the STS with a username/password (RST) and get back a claim set in SAML (RSTR).

    2.) Then the client should call the service with the claims attached somehow.
    -What do the SAML claims look like
    -How to attach the token credentials to the request?
    -Where does .Net put them in the message? In the Header?

    3.) The service would read the claims and then without having to communicate back to the STS would be able to validate that the claims are good and process the request.
    -How does the service validate the claims?

  • Hi pablo,
    could you please let me know your view for my previous comment. how can i use this code. will this solution run alone to understand the implimentation.

    please do respond.

    Thanks....JR

  • Hi Pablo,

    Great post.
    I'm trying to use your example STS for Java Interop and i'm running into some problems with the TokenSerializer (WSSecurityTokenSerializer) or at least that's where my problems are surfacing. I'm trying to make this work with a Metro based java Webservice and the requirement for token encryption and signing on the Java side is X509SubjectKeyIdentifierClause and i successfully changed the encryption token to use the SubjectKeyIdentifier and it serializes correctly.
    When i try to do the same thing for the signing token i get a serialization exception, i changed your code like this:
    private SecurityToken GenerateSamlToken(RequestSecurityToken rst, RequestSecurityTokenResponse rstr, SecurityKeyIdentifier proofKeyIdentifier)
    {
    // create saml:Assertion
    SamlAssertion samlAssertion = new SamlAssertion();
    samlAssertion.AssertionId = Constants.AssertionIdPrefix + Guid.NewGuid().ToString();
    samlAssertion.Conditions = new SamlConditions(DateTime.UtcNow, DateTime.Now.AddSeconds(SamlConfiguration.SamlTokenIssuerConfiguration.TtlInSeconds));

    samlAssertion.Issuer = OperationContext.Current.IncomingMessageHeaders.To.ToString();

    X509SecurityToken signingToken = (X509SecurityToken)SamlConfiguration.SamlTokenIssuerConfiguration.GetAuthorityToken();

    X509AsymmetricSecurityKey signingKey = new X509AsymmetricSecurityKey(signingToken.Certificate);
    //PH HACK use SubjectKey identifier
    //samlAssertion.SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest,
    // new SecurityKeyIdentifier(new X509ThumbprintKeyIdentifierClause(signingToken.Certificate)));
    SecurityKeyIdentifier ski = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { new X509SecurityToken(signingToken.Certificate).CreateKeyIdentifierClause() });

    samlAssertion.SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest, ski);

    this.GenerateSamlStatements(samlAssertion.Statements, proofKeyIdentifier, rst);

    ..........

    When i subsequently try to write the SamlToken i get an xmlException: "Keyset does not exist", "The SamlAssertion could not be serialized to XML. Please see inner exception for details."

    I can't figure out what i'm doing wrong and why the encryption token serializes without problems while the signing token fails?

Comments have been disabled for this content.