This way I can see an extra branch for each implementation in the test runner and I don’t have to copy-paste the test method body since it is automatically inherited in test classes:

Second approach – parametrized tests

The former approach has a significant disadvantage – everytime I create a new implementation, I have to create a new test subclass. I will use then a Nunit feature called “Parametrized tests” which allows me to inject a given set of parameters to a test method, one value after the other, and still be able to see all tests in the test runner.

Note that there are few differences. First, the test class is no longer abstract. Then, the implementation of the service is injected to the test method and because of the TestCaseSource attribute, I inform NUnit where to look for values ready to be injected. When the test starts, I register the injected instance in my container so that when the service implementation asks again for the implementation bound to the service interface, it will get the same object.

Note also that this approach still allows me to select a test in the test runner:

This subtle issue causes a deadful issue in an environment built around the ADFS2.

The problem is as follows: you have your applications federated with the ADFS2, tons of them. Each application has the “SignOff” button which takes users to ADFS2. ADFS2 renders the signoff page (containing iframes with urls with wsignoutcleanup1.0) which uses a jscript to redirect to the login page (if the wreply parameter is included).

One of our clients alarmed us that signing off from applications still allows users to see the last visited page. Upon closer inspection, it turned out that because of the way Opera, Firefox and Chrome treat “redirect” pages (please consult the mentioned blog entry), clicking Back on the login page (after succesful sign off) takes users back to the last page they visited (the one they clicked “sign off” on). And because most pages are read from a disc cache, the page is rendered even though a user hasjust signed off from the application!

A disaster.

A general solution was proposed in the last blog entry. It involves a modified javascript where the redirect is not done in an explicit way but rather with a setTimeout which prevents the unintended browser behavior.

Luckily, when ADFS2 is deployed, web pages have both *.aspx and *.cs available for modifications. There is a chance then to change the way the script is generated in the SignOut.aspx page.

The offensive javascript, generated in the SignOut.aspx is as follows:

<script>

window.onload = function()

{

document.location = decodeURIComponent('return_url_herex')

}

</script>

What you have to find out is to find a way to replace this script with the modified one.

When you open the SignOut.aspx.cs however, you will find out that there’s nothing much to do there:

//------------------------------------------------------------

// Copyright (c) Microsoft Corporation. All rights reserved.

//------------------------------------------------------------

using System;

using Microsoft.IdentityServer.Web.UI;

/// <summary>

/// This page sends WS-Federation SignOutCleanup messages to all the relying parties

/// that the user has signed in to during this session.

/// </summary>

publicpartialclass SignOut : SignOutPage

{

protectedvoid Page_Load( object sender, EventArgs e )

{

CleanupUrisRepeater.DataSource = SignOutMessages;

CleanupUrisRepeater.DataBind();

}

}

There does not seem to be an explicit way to change the way the unfortunate javascript is generated. The base class, SignOutPage, is one of the ADFS2 core classes, it comes from Microsoft.IdentityServer.Web.UI library. If you decompile the class, it seems that it registers the startup script in the constructor.

The critical detail to change is then to replace the javascript with a new one which would use the setTimeout. Since you cannot modify the SignOutPage class and its constructor (would have to decompile, modify, recompile and resign the DLL!), my approach is as follows – I introduce a new class, CustomSignOutPage, which inherits from SignOutPage. The SignOut page class will then inherit from the newly introduced one.

Since I cannot replace the base class’ constructor – my new class will always call it. That’s unfortunate as the script is registered in the constructor, using ClientScript.RegisterStartupScript. But the ClientScriptManager class lacks a way to unregister scripts! Another unfortunate issue!

What I can do however, is to generate a new window.onload handler which will replace the one created by the script registered with an existing, base class code. The intention is to have the following structure of scripts in the SignOut page:

<!-- this one cannot be replaced because of the design! unfortunate! !-->

First as you can see, I introduce a new class between the core SignOutPage class and the actual SignOut page class. The introduced class creates two scripts and injects them to the generated web page. The first script is rendered using a reflection on the FederationPassiveAuthentication type – this is because the type is internal in the ADFS2 core libraries. The second script uses the JSEncode method which is rewritten to mimic the way ADFS2 implements it.

And this is it. This does the trick and solves the unfortunate issue. Newly introduced scripts prevents the application page to be seen when users press the Back button in their browsers.

Once again – for this to work, you have to copy the above SignOut.aspx.cs and replace the original one. Remember to save a backup copy of the original file. Also, altough the solution was tested in a development environment, I can’t be 100% sure that there are no unexpected side effects of this change.

About

I am a software architect and an academic lecturer. I've been awarded Microsoft MVP in C# Architecture between 2005 and 2010. Got a PhD in computer science in 2008.
Currently I work mostly with C# and Javascript and love both languages. I consider myself a design/architecture patterns evangelist.
In 2003 I wrote first Polish book on C#/Windows programming, "Windows oczami programisty" (Windows through the eyes of a programmer) (the book is out of print)