SecurityToken

Federated SignIn Requires Federated SignOut

Posted on Updated on

Using WIF and a Passive STS is cool, but it’s even cooler when your Passive STS is in a different machine.

Now that we have Federation SignIn and a Passive STS that lives in a Different box and all out web apps rely on that external STS… How can I sign out?

In my case I tried everything and of course, it worked in my machine. Then it got deployed and the user didn’t get signed out because the browser didn’t expire the WIF token.

I executed all this and custom code to make the cookies expire but there was one left, the one created by the STS.

FederatedAuthentication.SessionAuthenticationModule.SignOut();
FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
FederatedAuthentication.WSFederationAuthenticationModule.SignOut(false);
FormsAuthentication.SignOut();

Bloody cookie, die!!! But nothing. The browser wouldn’t expire it and then it all made sense, I can’t make expire cookies that I haven’t created myself. So I thought that there would be a solution to this and I run all this without any luck. I checked the WIF doco, I Goggled it with Bing and nothing.

Finally I found a reference to something and of course NO SAMPLES (Isn’t WIF wonderfull!!!)

The solution is using the FederatedSignOut method that redirects to the STS, this one signs you out and redirects the browser to the page that you wanted to go to let the user know that he’s out.

WSFederationAuthenticationModule authModule = FederatedAuthentication.WSFederationAuthenticationModule;
string signoutUrl = (WSFederationAuthenticationModule.GetFederationPassiveSignOutUrl(authModule.Issuer, authModule.Realm, null));
WSFederationAuthenticationModule.FederatedSignOut(new Uri(authModule.Issuer), new Uri(authModule.Realm + "LoggedOut.html"));

It’s up to you to find out how to solve the new issue, the redirection to LoggedOut.html sends you back to the Login page in the STS because you where logged out (this is good fun if you use Windows Authentication because you get logged in again without knowing it.

The second catch is… once you are in the LoggedOut.html page, press the back button in the browser 🙂

Have fun

Serializing/Deserializing the bootstrap token

Posted on Updated on

I’ve been doing some work with WCF and WIF. Yes this new foundation thing called Windows Identity Foundation.

If you have seen the PDC09 demos than you probably thought that it’s so easy to add security to an application… well yes and no. It’s easy if you only want the standard functionality out of the box, but if you need to do something different… it’s quite complicated to get everything working. However, once you understand what’s going on then it is a lot smoother and you don’t need to worry anymore about how it works, it just works.

The last tornado I had to deal with was the serialization of security tokens. You may want to know why you would want to serialize tokens if WIF does it for you adding them to cookies or WCF heathers. Well that’s like asking why you would generate plain HTML to add custom CSS when you can use ASP.Net controls that spit out heaps of formatted html with colors. In this case, my reason is that I wanted to be able to open a windows application from the web browser and keeping the credentials I had in the browser.

To do that, you need to serialize the token into a file and your browser opens the application associated to that extension. It’s like when you download an excel sheet and instead of saving the file you open it directly in Excel or the same with a PDF. But in our scenario, we send the information that WIF had put in a cookie to the windows app so that we can call some WCF services. Easy. Serialize that monster and you deserialize it in the client to create the Channel. Go for it. If you are reading this is because it wasn’t that easy, isn’t it? Then, try to deserialize it now that you managed to serialize it. Ha!!.

The Idea is that you serialise your bootstrap token into an XML string


var bootstrapToken = ((IClaimsPrincipal)Thread.CurrentPrincipal).Identities[0].BootstrapToken; 

// Serialize
var req = new SamlSecurityTokenRequirement();
var handler = new Saml11SecurityTokenHandler(req);
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb))
{
   handler.WriteToken(writer, bootstrapToken);                   
}

string serializedToken = sb.ToString();

Serializarion is quite simple, but to deserialize the token we need to have the public key of the signing certificate because the classes that do the deserialization want to validate that moster. This sample shows how to read the certificate from a file, but the constructors allow reading from a stream (or you may want to serialize the x509 certificate together with the token in the file that you send to your win app).

// Deserialize
string path = @"c:\temp\STSPublic.cer";
// It can be deserialised from a byte[]
var cert = new X509Certificate2(path);
var token = new X509SecurityToken(cert);
var tokens = new List<SecurityToken>() {token}; 

var resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
var conf = new SecurityTokenHandlerConfiguration();
conf.IssuerTokenResolver = resolver;
handler.Configuration = conf; 

using (var reader = XmlReader.Create(new StringReader(sb.ToString())))
{
   bootstrapToken2 = handler.ReadToken(reader);
}

Instead of reading the certificate from a file you can read the certificate from the list of installed certificated from the local machine you can also use the following code.


var token = new X509SecurityToken(CertificateUtil.GetCertificate(StoreName.My, StoreLocation.LocalMachine, "CN=STSCertificateName"));

Now it’s up to you to do whatever you want with the token in the windows app.

I hope this helps.

R.