Skip to content

Instantly share code, notes, and snippets.

@Crisfole
Created February 27, 2014 12:19
Show Gist options
  • Save Crisfole/9249044 to your computer and use it in GitHub Desktop.
Save Crisfole/9249044 to your computer and use it in GitHub Desktop.
NancyFx Forms Auth Sliding Window
/*
* In my project I added the GUID to my implementation of IUserIdentity
* so I had access to it later by a simple cast. In Nancy you'd just want
* to fetch it the same way it's already done in the Before hook.
*
* Also note, I'm using my company's style guide, not Nancy's.
*/
// This is a Drop in replacement for the after hook used by FormsAuth right now.
private static Action<NancyContext> GetRedirectOrExtendWindowHook(FormsAuthenticationConfiguration configuration) {
if (configuration == null) {
throw new ArgumentNullException("configuration");
}
return context => {
if (context.Response.StatusCode == HttpStatusCode.Unauthorized) {
// I felt like it was common enough to want 401s to be passed unharmed to Ajax calls that I
// didn't even add configuratoin for this, it'd be simple enough to change this like so:
// if (!configuration.RedirectAjax && context.IsAjaxRequest()) {
if (context.IsAjaxRequest()) {
return;
}
context.Response = context.GetRedirect(RedirectUrl(configuration, context));
}
// Note this could be added to the configuration:
// else if (configuration.SlidingExpiry && LoggedIn(context)) {
else if (LoggedIn(context)) {
var cookie = context.Response.Cookies.FirstOrDefault(IsAuthCookie);
if (cookie == null) {
// Note this should be replaced by the more correct way of extracting the
// User Identifier from the cookie. I used this because directly copying
// the code from Forms Auth for extracting the GUID was failing for me.
var guid = ((UserWithId) context.CurrentUser).Id;
// Note: the next two lines should be replaced directly by 'BuildLoginCookie'
// which is private
var resp = FormsAuthentication.UserLoggedInResponse(guid);
cookie = resp.Cookies.Single(IsAuthCookie);
context.Response.Cookies.Add(cookie);
}
// Note: number of minutes should be configured, not hard coded
cookie.Expires = DateTime.UtcNow.AddMinutes(30);
}
};
}
private static bool IsAuthCookie(INancyCookie c) {
return c.Name == FormsAuthentication.FormsAuthenticationCookieName;
}
private static bool LoggedIn(NancyContext ctx) {
return ctx.CurrentUser != null // Already Logged In
|| ctx.Response.Cookies.Any(IsAuthCookie); // Logged In as a result of a fresh Login.
}
// This is a duplicate of code that's already in FormsAuth
private static string RedirectUrl(FormsAuthenticationConfiguration configuration, NancyContext context) {
var key = string.IsNullOrWhiteSpace(configuration.RedirectQuerystringKey) ? "returnUrl" : configuration.RedirectQuerystringKey;
var val = context.ToFullPath("~" + context.Request.Path + HttpUtility.UrlEncode(context.Request.Url.Query));
return string.Format("{0}?{1}={2}", configuration.RedirectUrl, key, val);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment