My website keeps losing session state, logging users out without explanation. I've been troubleshooting but can't pinpoint the cause.
I implemented an action filter to verify if the UserSession exists; if not, it checks if the user is authenticated and tries to recreate the session based on the user's ID.
If authentication fails, users are redirected to the login page. There's also code to check for ajax requests, set the status code to 403, and handle redirections in JavaScript.
This is my Action Filter:
public override void OnActionExecuting(ActionExecutingContext filterContext) {
SecuredController baseController = filterContext.Controller as SecuredController;
// Check if session is available
if (filterContext.HttpContext.Session["UserSession"] == null) {
if (!filterContext.HttpContext.User.Identity.IsAuthenticated) {
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest()) {
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
filterContext.Result = new JsonResult {
Data = new { Error = "Unavailable", Url = "~/Account/Login" },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
return;
}
if (!string.IsNullOrEmpty(HttpContext.Current.Request.RawUrl)) {
string returnUrl = HttpUtility.UrlEncode(HttpContext.Current.Request.RawUrl);
HttpContext.Current.Response.Redirect("~/Account/Login?returnUrl=" + returnUrl);
} else {
HttpContext.Current.Response.Redirect("~/Account/Login");
}
}
string userId = filterContext.HttpContext.User.Identity.GetUserId();
Web.Helpers.Common common = new Helpers.Common();
UserSession userSession = common.GetUserSession(userId);
filterContext.HttpContext.Session["UserSession"] = userSession;
}
baseController.CurrentUser = (UserSession)filterContext.HttpContext.Session["UserSession"];
base.OnActionExecuting(filterContext);
}
And here's my Javascript Code:
$.ajax({
type: method,
url: rootUrl + serviceUrl,
async: aSync,
data: dataParameters,
cache: false,
beforeSend: function() {
if (targetProgressContainer === undefined) {
return;
}
if ($(targetProgressContainer).length === 0) {
console.log('The Progress Container Div "' + targetProgressContainer + ' could not be found!');
return;
}
$(targetProgressContainer).html($(_progressContainer).html());
},
statusCode: {
403: function(data) {
window.top.location.href = sessionEndedUrl;
}
},
success: function(responseData, status, xhr) {
successCallback(responseData);
},
error: function(request, textStatus, errorThrown) {
errorCallback(request, textStatus, errorThrown);
}
});
This is my Startup.ConfigureAuth method:
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions {
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider {
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
},
SlidingExpiration = true,
ExpireTimeSpan = TimeSpan.FromDays(30)
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
Additionally, rules have been added to ensure the user's URL always includes the full domain:
<rules>
<rule name="Add www prefix to example.com domain" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^example\.com" />
</conditions>
<action type="Redirect" url="http://www.example.com/{R:1}" />
</rule>
</rules>
Any suggestions or insights would be greatly appreciated!