Windows Identity Foundation not removing Session Security Token from Cache

Recently were I work we had a PEN test on one of our applications and that highlighted that the federated authentication token for a relying party wasn’t being cleaned up correctly when logging out. After sitting down and working out what was cause for this problem I thought I would share my findings and the solution.

The problem

At work we use a custom session security token cache to store the token so we don’t have to pass around so much data to and from the client. When logging out from a replying party using a federated sign out e.g. “wsignoutcleanup1.0” the WIF code base should use the federation authentication module (FAM) and the “SignOut” method to get the session authentication module (SAM) and tidy up/delete the current session token. See the code example 1 below.

Example 1

public virtual void SignOut(bool isIPRequest)
{
  try
  {
    this.OnSigningOut(new SigningOutEventArgs(isIPRequest));
    SessionAuthenticationModule.Current.DeleteSessionTokenCookie();
    this.OnSignedOut(EventArgs.Empty);
  }
} 

The session authentication module and its method “DeleteSessiontokenCookie” then checks that the property “ContextSessionSecurityToken” isn’t null before calling the actual code to remove the session security token from the persistent cache and the in memory one. See example 2 below.

Example 2

public void DeleteSessionTokenCookie()
{
  this.CookieHandler.Delete();
  if (this.ContextSessionSecurityToken == null)
    return;
  this.RemoveSessionTokenFromCache(this.ContextSessionSecurityToken);
}

Now debugging the code and decompiling it I was able to work out that the session authentication module sets the “ContextSessionSecurityToken” when the “OnAuthenticateRequest” event is handled in the SAM. However, when signing out from the RP using “wsignoutcleanup1.0” this event is not fired or handled by the SAM if the FAM is defined above it in the web.config modules section (see below). No you read that correctly the order of the FAM and SAM in the web config appear to determine whether your token is cleared from the cache or not!

Does not remove the item from the cache

<removename="FormsAuthentication" />

<add name="WSFederationAuthenticationModule"
  type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  preCondition="managedHandler" />

<add name="SessionAuthenticationModule" 
  type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
  preCondition="managedHandler" />

The fix

Now, I’m not certain but I do not believe an application should be dependent on the order of HTTP modules to function correctly. Am I missing something? A quick fix for us is indeed to switch the order of the modules in the web.config to get the “ContextSessionSecurityToken” to be set (See example modules below).

<remove name="FormsAuthentication" />

<add name="SessionAuthenticationModule" 
  type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
  preCondition="managedHandler" />

<add name="WSFederationAuthenticationModule" 
  type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
  preCondition="managedHandler" />

Additionally I can also add some code to the FAM to do manually set the property on the SAM (see below). Both approaches feel wrong to me in that they fix an issue in the underline WIF implementation. Well potential issue…

FAM change

public override void SignOut(bool isIPRequest)
{
  var sessionModule = FederatedAuthentication.SessionAuthenticationModule;
  SessionSecurityToken token;
  var hasManagedToRead = sessionModule.TryReadSessionTokenFromCookie(out token);
  if (hasManagedToRead)
  {
    var lafSam = sessionModule asLafSessionAuthenticationModule;
    lafSam.ContextSessionSecurityToken = token;
  }
  sessionModule.DeleteSessionTokenCookie();
  base.SignOut(isIPRequest);
}

SAM change (redefined property in the LAF custom SAM so I could set the property!

public SessionSecurityToken ContextSessionSecurityToken
{
  get
  {
    return (SessionSecurityToken)HttpContext.Current.Items[(object)typeof(SessionSecurityToken).AssemblyQualifiedName];
  }
  set
  {
    HttpContext.Current.Items[(object)typeof(SessionSecurityToken).AssemblyQualifiedName] = (object)value;
  }
}

Until next time.

May 13 2014

Applying a theme to your Chrome Dev Tools

I wanted to make the Chrome dev tools editor easier on the eyes so I had a look around to see if it was possible. Since the web tools UI is web based it seems easy to skin and there is a great eco system of themes available from which to choose from.

A great site to browse through is devthemez.com, although it seems some of the themes no longer render correctly perhaps to due breaking changes in Chrome. One relatively complete theme which did function correctly is chromegray so this is the one I kept.

It will need to be installed into the following directory if your on Windows:

C:\Users\%USERNAME%\appdata\local\Google\Chrome\User Data\Default\User StyleSheets

So you can run the following PowerShell command to get this installed directly.

Invoke-WebRequest -Uri "https://raw.github.com/karelvuong/chromegray/master/Stable/Custom.css" -OutFile "C:\Users\$env:USERNAME\appdata\local\Google\Chrome\User Data\Default\User StyleSheets\Custom.css" 

As a result I have a flatter design and an easier on the eyes editor which reminds me more of sublime text.

image

I have to recommend giving it a go, the editor updates live with the new theme. If you don’t like it then its easy to find another one or remove the theme altogether.

January 3 2014

Dependency Injection in Scala and Play! using the cake pattern

It is my first time using Scala and I wanted a simple way to do DI so I could unit test my controller easily. The ability to use traits really seems to have a positive impact on code design, and enables things like DI to be quite easy without a runtime framework.

Real work scala dependency injection was a great introduction to implementing the Cake pattern in Scala so I won’t repeat the specifics of it here.

In case you haven't come across it the Play! framework is a complete web framework for JVM languages.

Personally I did not want to override plays controller instantiation so things stayed simple and I kept a clean routes table.

# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

POST    /:topic/:key          controllers.Application.send(topic: String, key: String)
GET     /:topic/:key          controllers.Application.get(topic: String, key: String, groupId: String)

The standard play pattern changes slightly with the controller which is split between two definitions. The first is the Application object which works with the play route and inherites the ApplicationController trait. It defines a message consumer to a real implementation which is going to connect to a Kafka cluster and it is this that we will want to mock when running our unit tests.

object Application extends ApplicationController {
  val messageConsumer = new KafkaMessageConsumer
}

Now we have the ApplicationController itself which contains the controller behaviour and inherits from a MessageConsumerComponent which is where it has access to a message consumer. The controller does not care how this is created and just uses it.


trait ApplicationController extends Controller with MessageConsumerComponent {

  def get(topic: String, key: String, groupId: String) = Action {
    this.messageConsumer.get(topic, key, groupId)
    Ok("done")
  }

  def send(topic: String, key: String) = Action(parse.text) {
    request =>

      val body: String = request.body

      this.messageConsumer.send(topic, key, body)

      Ok("received: " + topic + ", " + key + "," + body)
  }
}

The message consumer is implemented as a pair of traits, the first as the interface which can be mocked and the second which is used in the cake pattern.

trait MessageConsumer {
  def get(topic: String, key: String, groupId: String)
  def send(topic: String, key: String, message: String)
}

trait MessageConsumerComponent {

  val messageConsumer: MessageConsumer

  class KafkaMessageConsumer extends MessageConsumer  {
    def get(topic: String, key: String, groupId: String) { ... }
    def send(topic: String, key: String, message: String) { ... }
  }
}

This MessageConsumerComponent defines a messageConsumer field which will be accessible by any classes which inherit from the trait and can be set to either the KafkaMessageConsumer or a mock object. That's all there is to this implementation, so let's take a look at how this is done in a unit test.

trait TestEnvironment extends MessageConsumerComponent with ApplicationController with Mockito
{
  val messageConsumer = mock[KafkaMessageConsumer]
}

@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification with TestEnvironment {

  "getting by topic" should {

    "return list of messages" in {
      val result = this.get("topic","key","group")(FakeRequest())
      there was one(messageConsumer).get("topic", "key", "group")
      status(result) must beEqualTo(OK)
    }
  }
}

I've followed Jonas' example in using a TestEnvironment object, but to avoid creating an extra component for the Application my system under test is the TestEnvironment. It might be worth changing this later but to keep things simple I've chosen this way.

There were a further two implementations I came across which are here and here. You might prefer one of those implementations and they are worth a read.

I am new to Scala so if there are errors, design issues or a Scala faux pas please let me know!

@naeemkhedarun

December 26 2013

Excluding jmxtools with SBT

If you are using Scala and SBT you might experience this problem. In particular I was referencing Apache Kafka and found it trying to resolve the jmxtools which has been removed from the maven repository.

It took me a while to find the syntax to exclude this from my build.sbt file, but here it is:

libraryDependencies ++= Seq(
  "org.apache.kafka" % "kafka_2.10" % "0.8.0" excludeAll(ExclusionRule(organization = "com.sun.jdmk"),
                                                         ExclusionRule(organization = "com.sun.jmx"))
)

For more information you can check out the SBT documentation here.

December 23 2013
Older Posts