How to force timeouts in a Sharepoint intranet site when using Windows Authentication
Background:
Security for my sharepoint web site depends on windows authentication. Our workstations are members of the authenticating domain; our users log in to the domain when they access their workstation. The sharepoint web server is also a member of the same domain.
One reason I’m blogging this is because I hope to get any misunderstandings I have cleared up by good comments.
I was not able to find any setting – either in iis, web.config, any sharepoint site setting, etc that would force a timeout when you use windows authentication. I found posts recommending that people use forms authentication if they really wanted to enforce timeouts.
So, why would anybody want timeouts if they are already secured by windows authentication? I think it’s something like the distinction between security and security theater.
We had had a problem where our users put up a number of Microsoft office documents, and then each time they attempted to open a doc, they got a windows authentication challenge. Then after they eliminated those by putting the sharepoint site into their IE “local intranet sites” group, they never had to log in again. That made them feel uneasy – like the site was wide open to the world. (and they had also themselves specifically permitted a huge group of 10,000 users to access the site without realizing what they had done.) So I wanted to make the site “feel” more secure by issuing some challenges after a timeout period.
Here’s how I did it, in C# script in my masterpage:
1) Modify Web.config on the server to allow server side scripting in your master page
Got to – C:InetpubwwwrootwssVirtualDirectories80web.config
Change the path to your master page to match your own site:
<PageParserPaths>
<PageParserPath VirtualPath=”/sites/OIT/_catalogs/masterpage/*” IncludeSubFolders=”true” CompilationMode=”Always” AllowServerSideScript=”true” />
<PageParserPath VirtualPath=”/sites/Banner/_catalogs/masterpage/*” IncludeSubFolders=”true” CompilationMode=”Always” AllowServerSideScript=”true” />
</PageParserPaths>
2) Copy the following c# code to maintain a session variable with the time of the last sign in. Basically, what it does is create a session variable to hold the last time you used the web site, since the master page is executed for each page that you access. You set the timeout in the script. If your user leaves her desk for 33 minutes, for example, and then comes back and clicks on something, the master page will refresh, and the timeout code will see that the session should expire, and I send the user over to a page which forces her to login again.
<script language=”C#” runat=”server”>
// ********************************************************************************
// CONFIGS – not using web.config, using these lines
// ********************************************************************************
Boolean bDebugOn = false; // control Response.Write
Boolean bExecuteAspLoginScript = true; // in my vstudio test project, I don’t have the page
int TimeOutSeconds = 1800; // 30 minutes
protected void Page_Load(object sender, EventArgs e)
{
Handle_CheckSessionForTimeout();
}
// ********************************************************************************
// purpose – check the last time
protected void Handle_CheckSessionForTimeout()
{
String strSession = System.Web.HttpContext.Current.Session["SignIn"] + “”;
if (bDebugOn) Response.Write(“Session Value of SignIn Time:” + strSession);
if (bDebugOn) Response.Write(“<br>Current Time:” + DateTime.Now.ToLongTimeString());
if (strSession == “”)
{
System.Web.HttpContext.Current.Session["SignIn"] = DateTime.Now.ToLongTimeString();
Force_A_New_SignIn(); // force login for new session
return;
}
// check the time, if it’s too long, force a sign in
try
{
DateTime tmSessionPlusTimeout = DateTime.Parse(strSession);
tmSessionPlusTimeout = tmSessionPlusTimeout.AddSeconds(TimeOutSeconds);
if (bDebugOn) Response.Write(“<br>Session plus TimeOutSeconds:” + tmSessionPlusTimeout.ToLongTimeString());
DateTime tmNow = DateTime.Now;
if (tmNow.CompareTo(tmSessionPlusTimeout) > 0)
{
if (bDebugOn) Response.Write(“<br>timeout expired ********************”);
// set session variable so after a successful login they are permitted
System.Web.HttpContext.Current.Session["SignIn"] = DateTime.Now.ToLongTimeString();
Force_A_New_SignIn();
}
else
{
if (bDebugOn) Response.Write(“<br>timeout did not expire:” + tmSessionPlusTimeout.ToLongTimeString());
}
}
catch (Exception ex)
{
if (bDebugOn) Response.Write(ex.Message);
System.Web.HttpContext.Current.Session["SignIn"] = DateTime.Now.ToLongTimeString();
Force_A_New_SignIn();
}
}
// ********************************************************************************
protected void Force_A_New_SignIn()
{
// THIS WORKED
if (bDebugOn) Response.Write(“<br>Force_A_New_SignIn ************************************”);
// set it so next time they get to come in
System.Web.HttpContext.Current.Session["SignIn"] = DateTime.Now.ToLongTimeString();
if (bExecuteAspLoginScript)
{
Response.Redirect(“_layouts/AccessDenied.aspx?loginasanotheruser=false”);
}
else
{
if (bDebugOn) Response.Write(“<br>TEST MODE – DON’T EXECUTE THE ASPX PAGE “);
}
}
</script>
I’ve just put this up, and it’s not getting used heavily. We’ll see how the process matures over the next weeks.
Points:
* I noticed that when I’ve evidently timed out, if I click on a link, such as “Document Library”, that after the login process is complete, I do not continue on to my desired page, but instead return to the default.aspx page. I’m not 100% sure what to do about that.
Comments