Asp.Net MVC – Avoid resetting the form authentication cookie timeout for a request

I have a site that is using Asp.Net’s forms authentication, with sliding expiration. A user may log in and make some operations (requests), and after 30 minutes (for example) from her last action, she will be logged out.
However – what if I want to make a request that will not reset that timeout? For example, I may want to send an Ajax request for tracking the user, periodically check for notices, etc. How can I prevent that “system” request from extending the authentication cookie?

As it turns out, there is a simple way of doing that, once you understand exactly how sliding authentication works in asp.net.

I won’t go into too much detail, but the basic mechanism is:

  • After authentication, an authentication cookie is sent to the user, with expiration time of 30 minutes (or whatever you defined).
  • The authentication cookie contains an encrypted data, which is really the authentication ticket.
  • The ticket contains information related to the authentication, and the expiration time. Note the browsers don’t send the cookies’ expiration times when making a request, so that data is included in the authentication ticket instead.
  • For actions the user does in the first half of the expiration period (that is, the first 15 minutes), nothing happens. The authentication timeout does not reset.
  • On requests that happen on the second half of the expiration period, the timeout is reset, and the expiration is extended by another 30 minutes.

So, there is a chance our response will contain a new auth cookie, with extended expiration time. If the user is inactive, and our periodical action is the only thing happening, one of the responses will contain a new cookie, and the user will be logged in indefinitely.

So, how an we prevent that? This is as simple as removing the cookie from the response:

///<summary>
/// Prevent the auth cookie from being reset for this action, allows you to
/// have requests that do not reset the login timeout.
/// </summary>
public class DoNotResetAuthCookieAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var response = filterContext.HttpContext.Response;
        response.Cookies.Remove(FormsAuthentication.FormsCookieName);
    }
}

Use of this action is pretty simple:

[DoNotResetAuthCookie]
public ActionResult SampleAction()
{
    return Json(new {Request.IsAuthenticated, CookiesCount = Response.Cookies.Count});
}

Notes

  • You may also want to disable caching for such an action, using OutputCacheAttribute
    [OutputCache(NoStore = true, Duration = 0)]
    
  • I have some more defensive code in production (some more null checks), but this should be ok. Specifically, you don’t have to test the cookie is actually there to delete it: HttpCookieCollection.Remove
  • I used this to check if the user is still logged in, and get the time she will (presumably) log out – I needed something that works in an Ajax application, with many possible tabs or windows open.

See Also

.Net Regular Expressions – Finding Decimal Numbers that are Divisible by Three

It’s very easy to check a decimal number is divisible by three using a simple DFA with 3 states.

A regex, therefor, is possible, but not too pretty (source):

(?:[0369]|
[147](?:[0369]*[147][0369]*[258])*(?:[0369]*[258]|[0369]*[147][0369]*[147])|
[258](?:[0369]*[258][0369]*[147])*(?:[0369]*[147]|[0369]*[258][0369]*[258])
)*

Example: http://www.rubular.com/r/ZcRDblHg8M

Here’s another approach, using .Net’s stacks as a simple counter:

\b
(?>             # No regrets - don't backtrack on if/else decisions.
    [0369]      # = 0 (mod 3)
    |
    [147]       # = 1 (mod 3)
    (?:         # if possible pop 2, else push 1
        (?<-Sum>){2}|(?<Sum>)
    )
    |
    [258]       # = 2 (mod 3)
    (?:         # if possible pop 1, else push 2
        (?<-Sum>)|(?<Sum>){2}
    )
)+
\b
(?(Sum)(?!)) # Assert nothing's left in the stack

Why? Well, I was bored while I shaved. Luckily, this regex is simple enough for Mono. Working example: http://ideone.com/Yp6Ti (ok, maybe not, mono is missing 111222)

.Net Regular Expressions – Using the Stack State to Understand Numeric Values

It is common knowledge that regular expressions should handle text and not values. A recent stack overflow question got me thinking though – it is possible to use .Net regular expressions to understand numbers or other values while matching the pattern?
Regular expressions can be used to perform numerical tasks, but that is usually when working in unary base.
It turns out this is possible – .Net keeps a stack for every capture of every matched group while matching the pattern, and that state is available for use while matching. The idea is simple: we can represent numbers as depth of the stack, so the number 0 is an empty stack, 6 is a stack with 6 captures, and so forth.

(?>
    (?=[0-9])   # optimization - don't multiply when we don't have a digit.
    # multiply the content of the stack by 10
    # for each item on Stack, push 10 items to a Temp stack.
    (?(Decimal)
        (?<-Decimal>
            (?<Temp>){10}
        )
    ){100000}
    (?(Decimal)(?!))
    # Push all items from Temp back to Stack
    (?(Temp)
        (?<-Temp>
            (?<Decimal>)
        )
    ){100000}
    (?(Temp)(?!))
    # match a digit, and push its value to the stack
    (?:
        0                 |
        1 (?<Decimal>)    |
        2 (?<Decimal>){2} |
        3 (?<Decimal>){3} |
        4 (?<Decimal>){4} |
        5 (?<Decimal>){5} |
        6 (?<Decimal>){6} |
        7 (?<Decimal>){7} |
        8 (?<Decimal>){8} |
        9 (?<Decimal>){9}
    )
)+

The idea is very simple: when we see a new digit, we multiply the depth of the stack by 10, and add the number represented by the new digit. The value of the number can be verified using:

match.Groups["Decimal"].Captures.Count

A curious bit here is the use of the loop to copy stacks:

(?(Temp)
    (?<-Temp>
        (?<Decimal>)
    )
){100000}

I’d expect this to be enough:

(?<-Temp> (?<Decimal>) )*
(?(Temp)(?!))

It turns out the above loop is only executed once, and the condition always fails. It is probably a documented optimization, I’ll look more into that later. As a proof of concept, the workaround should do.

It is even possible to perform basic arithmetic operations on these stacks such as adding, subtracting, multiplying and such from within the regex engine, but that may be a few extra steps too many.
It should go without saying, of course, that regex isn’t a good option here – this is for recreational use. The run time and complexity are far from ideal.

See also:

SharePoint 2010 – Adding Created, CreatedBy, Modified and ModifiedBy to SPMetal’s Generated Classes

By default, SPMetal doesn’t map the Created, Created By, Modified and Modified By fields to it’s generated objects. To remind SPMetal they exist you can easily add them to your parameters XML file (using /parameters:myfile.xml at command line). Of course. You can selectively add where you need it, or add it to Item:

<Column Name="Editor" Member="CreatedBy" />
<Column Name="Author" Member="ModifiedBy" />
<Column Name="Created" />
<Column Name="Modified" />

Also, here’s a template of the SPMetal command:

"%programfiles%\Common Files\Microsoft Shared\Web Server Extensions\14\BIN\spmetal.exe" "/web:http://myserver/someweb/foo" /language:csharp /code:SPFoo.cs /serialization:unidirectional /parameters:FooSPMetalParameters.xml

See also:

.Net Regular Expressions – Finding Acronyms, and Reversing the Stack

A recent Stack Overflow question asked if you could (not should) use regular expressions to find acronyms, specifically of the form “Original Poster (OP)” – words followed by the acronym in parentheses.

Well, my first try was this:

\b((?<Acronym>\w)\w*\W+)+
\((?<-Acronym>\k<Acronym>)+\)
(?(Acronym)(?!))

Seems simple – the first line captures the words and pushes each first letter to the stack. The second line pops and matches it, and the last line makes sure there aren’t any extra letters. Seems nice, but wrong. The first letter on the stack in this case comes from the last word, so it matches a reversed acronym – “Oops, Wrong (WO)”.

What I had to do is to reverse the stack. I came up with this regex:

\b((?<Acronym>\w)\w*\W+)+
(?<=(?<-Acronym>.(?=.*?(?<Reverse>\k<Acronym>)))+)(?(Acronym)(?!))
\((?<-Reverse>\k<Reverse>)+\)
(?(Reverse)(?!))

Now, I’m not sure that’s the best way, but it works nicely. The second line is the only thing interesting – I won’t explain it too much, because nobody is reading it. Basically, I match every letter on the stack, and push it to a second stack. I match a dot for each letter because the engine has trouble matching a zero-width expression multiple times (though it works with {5}, for example, but not + or {1,5} – it only tries one). I can match backwards because I know I had at least that many letters, and can look forward because I’m optimistic – I expect to match these letters later, so if they aren’t there, I might as well fail now.

Here’s a sample program: https://gist.github.com/765417
I tried creating an ideone version, but it fails (probably a mono bug)

.Net Regex – Matching Mixed Balanced Parentheses

Yesterday I got thinking about matching different types balanced parentheses using .net regular expression. I assumed it was similar to matching quotes or a single kind of parentheses, but soon realized it isn’t quite that simple. The main problem is looking into the stack – when I see a closed curly brace, for example, how can I tell the top of the stack has an open one?

A quick search brought up Linguistic Forms’ Regex Balancing Group in Depth, which has a clever approach to the problem in the best use I’ve seen yet to balancing groups, and taught me a few new tricks. I’d recommend reading it. The tl;dr version is this: when I see a closed bracket I look-behind my current position using whatever was matched since the last open bracket, revisit it, and check it again. So, if I see I had a { (by matching it again), I know I should now match a }.

While reading the post I had an interesting idea – who says I must push what I matched to the stack? What if wanted to push an arbitrary string to the stack? When I see an open bracket I really want to push a closing bracket – but how can I?
The trick is to use a look-ahead: find the next occurrence of the character I want to push, and push it:

{(?=.*?(<Stack>}))

Next, when I want to match a closing brace, I already have the right one in stack.
Using this approach, here’s a regex that matches tokens with matching balanced parentheses of 3 different typed:

(
    [^(){}\[\]]+
    | \( (?=[^)]*  (?<Stack> \) ) )
    | \[ (?=[^\]]* (?<Stack> \] ) )
    | \{ (?=[^}]*  (?<Stack> \} ) )
    | \k<Stack> (?<-Stack>)
)+?
(?(Stack) (?!))

Of course, this approach does have limitations – you may not find the character you’d like to push (which might be a good thing – it allows you to fail early). It also gets much trickier if you want to balance something more complicated constant strings, but that’s another subject.

Here’s a sample program on ideone: http://ideone.com/WaXfZ

Happy matching.

SharePoint 2010 – Using Document Id to Link to a Specific Version

SharePoint 2010 introduces Document Id, which is an easy way to create document permalinks across a SharePoint Site (SPSite), without worrying about changing names and folders.
This is all nice and well, but what if you’ve enabled versioning, and want to link to a specific version?
It is a shame DocIdRedir.aspx does not accept a version as an optional parameter, but a small shame, as it is easy enough to implement your own handler, using the API method DocumentId.FindUrlById. Alternately, you could have done that yourself and used DocumentId.FindUrlsById, find the appropriate SPListItem and find the version url, if you don’t approve of the way FindUrlById does that for you.
My solution is to create another page, much like DocIdRedir.aspx, and have it accept a version and act accordingly (in this case I’ve created an ASHX handler, but it should be just the same):

public void ProcessRequest(HttpContext context)
{
	string docId = context.Request.QueryString["id"];
	string versionLabel = context.Request.QueryString["v"];
	SPSite currentSite = SPContext.Current.Site;
	string url = null;
	try
	{
		url = GetUrlFromID(currentSite, docId, versionLabel);
	}
	catch (Exception ex)
	{
		string message = String.Format("Error finding document by id {0} and version [{1}], {2}"
			, docId, versionLabel, ex.Message);
		SPUtility.TransferToErrorPage(message);
	}

	if (url == null)
	{
		string message = String.Format("Could not find document with id {0} and version [{1}]"
			, docId, versionLabel);
		SPUtility.TransferToErrorPage(message);
	}
	else
	{
		context.Response.Write(url);
	}
}

private string GetUrlFromID(SPSite site, string docId, string version)
{
	//FindUrlById throws an exception if version is empty or null,
	// so I check it here to make sure it works.
	if (String.IsNullOrEmpty(version))
	{
		string[] urls = DocumentId.FindUrlsById(site, docId);
		return urls.Single(); // think about what you do here
	}
	else
	{
		return DocumentId.FindUrlById(site, docId, version);
	}
}

After creating and deploying your package, which is effortless in Visual Studio 2010, instead of using the default permalinks:

/_layouts/DocIdRedir.aspx?ID=GROOVY-10-2

you can use your own handler (you may want a shorter solution name and handler):

/_layouts/mySolution/VersionedDocumentId.ashx?id=GROOVY-10-2&v=2.5

See also:

Follow

Get every new post delivered to your Inbox.