Friday, May 27, 2011

WIF, WS-Federation and Single sign-out for RP – R-STS – IP-STS scenario

There seems to be no strict specification on how Single sign-out should be implemented for WS-Federation. Not so long ago I’ve blogged about a simple scenario involving an IP-STS and a group of RPs.

A simple scenario

In such simple scenario, when the IP-STS receives a wsignout1.0 request from one of RPs (which is basically a request to sign out the whole party from current session), it returns a page to the browser which contains a list of images pointing back to all RPs that have signed using the IP-STS. Each single url to the image is of the form:

<img src="http://the.relyingparty.com/default.aspx?wa=wsignoutcleanup1.0" />

Thus, it’s not the IP-STS who signs out everyone but rather it’s the responsibility of the browser to tell everyone to log off.

Imagine that the browser is an office-boy who passes messages between the boss (IP-STS) and his workers (RPs). When one of workers says “I want everyone to log off”, the boy delivers the request to the boss and in return the boss gives a list of workers to the boy saying “go, tell everyone from this list to log off”.

What works like a charm in a simple scenario, seems to be problematic in a more complicated one.

A complicated hierarchy

Suppose that this time there are not only RPs and the IP-STS but also R-STSes in the middle (Relaying Security Token Services which pass sign in requests upwards). Each of such R-STSes acts just like a lower-level manager who’s now collecting requests from his workers and passes them to the boss.

Note that such hierarchy can be arbitrarily complicated, with a single IP-STS at the top, possibly multiple layers of R-STSes in the middle and RPs at the bottom.

Suppose now that, as previously, the office-boy (one of RPs) asks his manager (one of R-STSes) to log-off. This time however the manager would be torn between two conflicting needs:

  • he has to inform all his workers (RPs that are directly under him) to sign off (by sending links with wa=wsignoutcleanup1.0)
  • he has to ask his boss (the IP-STS) to log off everyone (all other possible R-STSes)

The office-boy (the browser) can unfortunately perform only one of above requests at a time. Either the R-STS will return images to log off all his child RPs or it will push the log-off request to the IP-STS.

The former is a bad choice – as the log off request should not be restricted to a subtree of such complicated hierarchy. The latter however raises a new issue – yes, the log-off request can be pushed to the IP-STS but if the IP-STS returns a list of images to log off is direct descendants (R-STSes), it will log off only R-STSes! None of RPs will log off, as the IP-STS has no idea of what happens two levels above him!

And just for the record: the difference in handling a sign-out request between an IP-STS and a R-STS is presented below:

...
else if ( action == WSFederationConstants.Actions.SignOut )
{
    // Process signout request.
    SignOutRequestMessage requestMessage = 
        (SignOutRequestMessage)WSFederationMessage.CreateFromUri( Request.Url );
 
    // IP-STS: answer to the signout request
    FederatedPassiveSecurityTokenServiceOperations.ProcessSignOutRequest( 
        requestMessage, 
        User, 
        requestMessage.Reply, 
        Response );
    
    // R-STS: push signout request upwards
    WSFederationAuthenticationModule.FederatedSignOut( 
        null, 
        new Uri( requestMessage.Reply ) );
}
Frames to the rescue

A solution to this issue can be easily inferred from the way ADFS 2.0 handles sign-out requests.

It seems that instead of returning a list of images containing signout requests to his direct descendants, a STS should return a list of invisible iframes of a form:

<iframe src="the.relyingparty.com/default.aspx?wa=wsignoutcleanup1.0" class="MakeItInvisible" />

This way, the browser deilvering such request to each of R-STSes expects a web page in a return.

But, in contrast “imaging approach”, a web page can contain further references which will make the browser go after them.

Each of R-STSes should then return a page containing a list of iframes containing links to log off his descendants and so on.

Note, that the structure of dependency tree in such approach can be arbitrarily complicated as each parent node returns iframes pointing to its descendants.

The only drawback of such approach is that if you’d like to have some visual feedback from consecutive STSes then you have to implement it on your own (embed some images inside returned iframes).

2 comments:

Anonymous said...

Thanks for the post, I was wondering how to understand the SSOut with one RP-STS in the middle. I am surprised the book about WIF doesn't properly handle this problem. If you could post one simple example with dummy RP, RP-STS and IP-STS, it would be great :)

Wiktor Zychla said...

Email me and I will send some more details on this.