Search code examples
asp.netsession-cookieswifws-federation

How to set FedAuth cookie SessionToken.IsPersistent conditionally when SessionSecurityTokenCreated


I am using WIF with WS Federation so that my ASP.NET application can authenticate against an STS (Thinktecture IdentityServer). In my RP I would like to pragmatically set the cookie persistence based off of the claims of the user.

Watching the traffic in Fiddler I can see the WIF FedAuth cookie is first set when the STS token is posted to the RP. Before the cookie is set I would like to intercept some event and either set the cookie to be persistent (or not) depending on the current claims.

I understand that I can set the cookie persistence in the web.config, however this behavior needs to be conditional based off of the user.

<wsFederation ... persistentCookiesOnPassiveRedirects="true" />

My first approach was to try handling the various SessionSecurityTokenCreated events but these events never seemed to be fired. Am I adding the handlers incorrectly? Or is there a better way of doing this?

protected void Application_Start()
{
    ...

    FederatedAuthentication.SessionAuthenticationModule.SessionSecurityTokenCreated +=
        new EventHandler<SessionSecurityTokenCreatedEventArgs>(SessionAuthenticationModule_SessionSecurityTokenCreated);

    FederatedAuthentication.WSFederationAuthenticationModule.SessionSecurityTokenCreated +=
        new EventHandler<SessionSecurityTokenCreatedEventArgs>(WSFederationAuthenticationModule_SessionSecurityTokenCreated);

}



//This never seems to fire...
void SessionAuthenticationModule_SessionSecurityTokenCreated(object sender,
        SessionSecurityTokenCreatedEventArgs e)
{
    if (e.SessionToken.ClaimsPrincipal.HasClaim("someClaim", "someValue"))
        e.SessionToken.IsPersistent = true;
    else
        e.SessionToken.IsPersistent = false;
}


//This never seems to fire either...
void WSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender,
        SessionSecurityTokenCreatedEventArgs e)
{
    if (e.SessionToken.ClaimsPrincipal.HasClaim("someClaim", "someValue"))
        e.SessionToken.IsPersistent = true;
    else
        e.SessionToken.IsPersistent = false;            

}

Interesting to note: if I add a handler for SessionAuthenticationModule_SessionSecurityTokenReceived this event seems to fire. Here I can re-issue the cookie and set IsPersistent = true but this doesn't get fired until after the cookie is first set and I would prefer to do this when the cookie is first issued.

After testing a bit: If I Reissue the cookie in SessionAuthenticationModule_SessionSecurityTokenReceived then SessionAuthenticationModule_SessionSecurityTokenCreated will be fired. I just can't seem to find out why this is not fired on the initial creation of the cookie when the token is first POSTed to the RP.


Solution

  • The source of my problem was: a) I was using a custom WSFederationAuthenticationModule. b) I wasn't wiring up the events in the Global.asax using the name of the custom module.

    Assuming my web.config has this in it:

    <system.webServer>
    
    // ...
    
        <add name="MyCustomWSFederationAuthenticationModule"
         type="MyLib.MyCustomWSFederationAuthenticationModule, Thinktecture.IdentityModel, Version=1.0.0.0, Culture=neutral"
         preCondition="managedHandler" />
    
        <add name="SessionAuthenticationModule"
         type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
         preCondition="managedHandler"  />
    
    
    // ...
    
    </system.webServer>
    

    And assuming "MyCustomWSFederationAuthenticationModule" is the name of the custom fed-auth module. Then I just had to fix the name of the method handler (with nothing in app start).

    protected void Application_Start()
    {
        //Nothing here.
    }
    
    //This never seems to fire either...
    void MyCustomWSFederationAuthenticationModule_SessionSecurityTokenCreated(object sender,
            SessionSecurityTokenCreatedEventArgs e)
    {
        if (e.SessionToken.ClaimsPrincipal.HasClaim("someClaim", "someValue"))
            e.SessionToken.IsPersistent = true;
        else
            e.SessionToken.IsPersistent = false;            
    }