Pablo M. Cibraro (aka Cibrax)

My thoughts on Web Services and .NET development

News

Pablo Cibraro's VisualCV

Blogs

Personal

Programming

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" 
 

 

Posted: Sep 08 2006, 12:25 PM by cibrax | with 32 comment(s)
Filed under: ,

Comments

Anonymous Coward ;) said:

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 :(
# September 8, 2006 11:26 AM

Al said:

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???
# September 11, 2006 3:35 PM

cibrax said:

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.

# September 11, 2006 3:48 PM

Sean said:

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*
# September 11, 2006 5:22 PM

cibrax said:

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.

# September 11, 2006 9:55 PM

Al said:

OK, I tried using gudge's RST class and the custom security manager and the custom security manager code never gets called. I don't get an error or anything. I get an RSTR back, but the custom manager never gets called. Here's my client code: ChannelFactory f2 = new ChannelFactory("clientendpoint3"); f2.Credentials.UserName.UserName = "alice"; f2.Credentials.UserName.Password = "alice"; ISTSChannel c = f2.CreateChannel(); RequestSecurityToken rst = new RequestSecurityToken(); rst.RequestType = "http://schemas.xmlsoap.org/ws/2005/02/trust/Issue"; rst.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1"; // Create some entropy RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); byte[] entropy = new byte[256 / 8]; random.GetNonZeroBytes(entropy); // Set the requester rst.RequestorEntropy = new BinarySecretSecurityToken(entropy); Message request = Message.CreateMessage(MessageVersion.Soap12WSAddressing10, "http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue", rst); // Send message Message resp = c.Issue(request); Here's my config file:
# September 11, 2006 11:46 PM

cibrax said:

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).

# September 12, 2006 10:06 AM

Al said:

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?
# September 12, 2006 11:49 AM

Al said:

Using your TokenCache, is there a way to get at the cached token from the client?
# September 13, 2006 11:23 AM

cibrax said:

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.

# September 13, 2006 11:58 AM

Al said:

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?
# September 13, 2006 3:16 PM

cibrax said:

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.

# September 13, 2006 3:23 PM

Al said:

OK, cool, thanks!
# September 13, 2006 3:30 PM

mpollmeier said:

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

# December 17, 2006 7:11 AM

Christian said:

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'.

# February 21, 2007 4:27 PM

Dima said:

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

# February 22, 2007 4:15 PM

Kumar said:

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!

# March 1, 2007 1:54 PM

eidolon said:

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

thanks

# March 6, 2007 8:33 PM

shankar prasad said:

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

# March 9, 2007 5:03 AM

Mike Zimmerman said:

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.

# April 9, 2007 11:36 AM

cibrax said:

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.

# April 10, 2007 10:59 AM

dejawoo said:

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

# May 3, 2007 5:17 AM

dejawoo said:

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

# May 3, 2007 5:17 AM

cibrax said:

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.

# May 3, 2007 8:51 AM

Mikkel Christensen said:

What are the terms of use for the published code?

# February 1, 2008 8:00 AM

Pablo M. Cibraro (aka Cibrax) said:

I decided to write this post in order to show some necessary steps to build a Secure Token Service (STS

# May 15, 2008 8:55 AM

Alice said:

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

# May 28, 2008 5:44 AM

Bronumski said:

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?

# June 13, 2008 11:02 AM

Jankiraj said:

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?

# September 24, 2008 3:40 PM

Jankiraj said:

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

# October 1, 2008 10:19 AM

phjortholm said:

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<X509SubjectKeyIdentifierClause>() });

           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?

# October 28, 2008 4:43 AM

ashwanikumar98 said:

Hi Pablo,

I have a requirement to consume the WCF Federated service to be consumed from .Net 2.0. How I can do this. Does some library from .net 2.0 supports this.

Steps:

a. Client(built in .Net 2.0) gets the token from STS(built using Geneva Framework) for calling Service(built in WCF)

b. Client then send the token to Service to call the appropriate service method.

Thanks,

Ashwani

# May 27, 2009 10:02 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)