I am using ADFS 2.0 for quite some time and I understand how things work. I've done dozen of custom RPs, custom STSes as well as using the ADFS as the relying STS.
However, I have a simple requirement which I still fail to fulfill.
I want my users to be forced to relogin after some fixed time. Let's say 1 minute, for test purposes.
First, I've made some corrections at the RPs side. It seems that for unknown reason, the RP retains the session even if the token's validTo
points back in time. This contradicts what Vittorio Bertocci says in his book (page 123) where he shows how to perform sliding expiration - he says that "The SessionAuthenticationModule will take care of handling the expired session right after". Well, for me it doesn't, however I have found a trick here http://blogs.planbsoftware.co.nz/?p=521 - take a look at the "if" clause:
sam.SessionSecurityTokenReceived +=
( s, e ) =>
{
SessionAuthenticationModule _sam = s as SessionAuthenticationModule;
DateTime now = DateTime.UtcNow;
DateTime validFrom = e.SessionToken.ValidFrom;
DateTime validTo = e.SessionToken.ValidTo;
try
{
double halfSpan = ( validTo - validFrom ).TotalSeconds / 2;
if ( validTo < now )
{
_sam.DeleteSessionTokenCookie();
e.Cancel = true;
}
}
catch ( Exception ex )
{
int v = 0;
}
};
This trick fixes the issue at the RPs side. When the token is invalid the application clears it out and redirects to the login page.
Now comes the problem. My login page uses the FederatedPassiveSignIn
control. When clicked, it redirects the browser to the ADFS.
But ADFS happily creates a new session without any prompt for the user.
I have set the token's lifetime for this RP to 1:
Set-ADFSRelyingPartyTrust -Targetname "myrpname" -TokenLifetime 1
and using Get-ADFSRelyingPartyTrust
I can see that it's set to 1 (I even print the token validTo
on my page to confirm that this is set correctly).
Then I set ADFS properties with ADFS-SetProperties
:
ADFS-SetProperties -SsoLifetime 1
ADFS-SetProperties -ReplyCacheExpirationInterval 1
ADFS-SetProperties -SamlMessageDeliveryWindow 1
but still no luck. I am stuck now.
The scenario works correctly with my custom STS where the validity of the STS session is based on a Forms cookie - if I set the STS's forms cookie timeout to 1, after 1 minute of inactivity within my RP application I am redirected to the login page of my RP which then redirects to the STS which presents its login page.
However, this is not the case with ADFS 2.0. After a minute of inactivity, I am redirected to the login page of my RP which redirects to ADFS's login page which in turn redirects back happily just like the session would be still active within ADFS.
I would like someone to:
(1) take a look at the hack described at the top and explain why an expired token is not automatically rejected and such ugly hack is needed
(2) explain how to properly timeout the session at the ADFS 2.0 side so a request to renew the token is guarded with a login page.
Thanks in advance.
edit
I can confirm that setting all above parameters to 1 minute makes the ADFS session invalid after 5 minutes (or more). That's strage and it seems that either I am making a basic mistake or 5 minutes is the minumum acceptable value.
My (2) from above is now then just to confirm and explain my observation.
As per comments above (joint effort with the OP) the Freshness
property on the FederatedPassiveSignIn
instance should be set to 0.
According to http://docs.oasis-open.org/wsfed/federation/v1.2/ws-federation.html this indicates for the IP/STS to re-prompt the user for authentication before it issues the token.
You could also try changing ADFS from windows integrated authentication to forms based authentication. You will probably still have to monkey with the freshness property but now your users will have to enter their credentials even if they are on the same network as your AD.
This article explains it pretty simply:
http://social.technet.microsoft.com/wiki/contents/articles/1600.aspx
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With