Can't control Session time in ASp MVC 4.5 Application - c#

I am using this to login:
var f = from b in db.AdminToybias
where b.UserName == a.UserName
&& b.Password == a.Password
select b;
if (f.Count() >= 1)
{
Session["uname"] = f.FirstOrDefault().UserName;
Session["pass"] = f.FirstOrDefault().Password;
Session["role"] = f.FirstOrDefault().Role;
I tried both:
<sessionState timeout="1440" mode = "InProc"></sessionState>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="288000" />
</authentication>
But the application automatically logout user after few mins (don't know exact time). I want to get session unlimited time untill he manually logout.
I tried so many hours but failed. What can i do to achieve this?
I am using Godaddy Hosting.

They are different things. The Forms Authentication Timeout value sets the amount of time in minutes that the authentication cookie is set to be valid, meaning, that after value number of minutes, the cookie will expire and the user will no longer be authenticated - they will be redirected to the login page automatically-. The slidingExpiration=true value is basically saying that after every request made, the timer is reset and as long as the user makes a request within the timeout value, they will continue to be authenticated. If you set slidingExpiration=false the authentication cookie will expire after value number of minutes regardless of whether the user makes a request within the timeout value or not.
The SessionState timeout value sets the amount of time a Session State provider is required to hold data in memory (or whatever backing store is being used, SQL Server, OutOfProc, etc) for a particular session. For example, if you put an object in Session using the value in your example, this data will be removed after 30 minutes. The user may still be authenticated but the data in the Session may no longer be present. The Session Timeout value is always reset after every request.

Related

How to set session timeout and session idle timeout in asp.net

I have a simple question but not able to find solution to it. I have set session timeout of the application in the web.config as :
<sessionState timeout="30" mode="InProc"/>
and its working fine but now I got the requirement that if the user is idle that is, he is not performing any action on the page for one minute his session should get expired. I tried to do it using form authentication as :
<authentication mode="Forms">
<forms loginUrl="~/Login.aspx" timeout="1" slidingExpiration ="false" defaultUrl="login.aspx"/>
</authentication>
But its now working. Any help would be appreciated.
If I have understood the question correctly (see comments by OP) then the problem is that OP wants both slidingExpiration and absoluteExpiration to be active, but with separate timeouts.
This would enable the system require a user to log back in after a certain time of idling, and to require a user to log back in after a different time even if the user was not idling.
Unfortunately this is not supported out of the box using forms authentication. You have to choose either sliding or absolute expiration. Or you have to build a workaround yourself.
You can use a very simple work around by:
Setting the timeout of the session longer than the corresponding forms authentication timeout, and also longer than the desired absolute timeout:
<sessionState timeout="35" mode="InProc"/>
Set forms authentication to use slidingExpiration = true
Create a user logged in timestamp in the session whenever a user logs in:
Session["userLoggedInAt"] = DateTime.UtcNow;
Add an Application_PostAcquireRequestState method to Global.asax:
void Application_PostAcquireRequestState(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
if (context.Session != null && context.User.Identity.IsAuthenticated)
{
bool forceLogout = false;
if (context.Session["userLoggedInAt"] == null)
forceLogout = true;
else if (!(context.Session["userLoggedInAt"] is DateTime))
forceLogout = true;
else if (DateTime.UtcNow > ((DateTime)context.Session["userLoggedInAt"]).AddMinutes(30))
forceLogout = true;
if (forceLogout)
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
}
}
}
Disclaimer: Code above was hacked together quickly, may not be fool proof...
Notes:
Setting sliding expiration to timeout after 1 minute seems excessively paranoid. Even a fast user will not be able to finish any significant work in the application during that time. Even my web bank has a longer idle timeout that that. I would recommend a minimum of 5-10 minutes.
Sliding expiration in forms authentication has an interesting feature: The sliding happens by updating the authentication cookie, moving the expiration date forward when the user is active. But this only happens when at least half the expiration time has passed. If you want to guarantee that a user can be idle for 10 minutes without getting logged out, you must therefore set the timeout to be 20 minutes.

Handle User Session Logout Time With Authentication Forms

I have session table in database where datetime values of login and logout are stored. In my MVC application I am using authentication Forms. Where the cookie is persistent for example 20 minutes with slidingExpiration = true. What is the good practice to ping the session in database and to set accurate logout time. For example when the slidingExpiration fires and reset the expire time of cookie to plus 20 minutes in the same session key. How to handle this in databse to update the logout time of user session ? My end point is to keep accurate logout time of user session in database.
Web.config
<forms loginUrl="/KJH/Account/SignIn" protection="All" timeout="20" name="FedCookie" path="/" requireSSL="false" slidingExpiration="true" defaultUrl="/NCB/Home/Index" cookieless="UseDeviceProfile" enableCrossAppRedirects="false" />
SQL script to update user session
UPDATE dbo.tSession SET LogoutTime = DATEADD(mi, 20, GETDATE()) WHERE Ukey = #Session and LogoutTime > GETDATE()

Cookies and Sessions Expiration in .NET

I have an MVC4 single application page. In the log-in page there are 3 fields: user, password and "remember me" checkbox.
The C# login code is this:
if (WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return Json(new { success = true, redirect = returnUrl });
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
I want to do this:
If a user logs in with "remember me" true - The cookie will stay until the user logs off.
If the user logs in with "remember me" false - The cookie will expire after 3 hours.
In web.config I have this code:
<authentication mode="Forms">
<forms loginUrl="~/" timeout="180" cookieless="UseCookies" slidingExpiration="false" />
</authentication>
<sessionState timeout="180" />
The problem is when the user doesn't touch the page for a short time (10-30 mins usually), and then the user tries to do something in the page - there is an error
"Authorization has been denied for this request."
(Although sessionStation is more than 30 minutes!)
After the user refresh the page - if the cookie hasn't expired yet - everything works fine. But of course I don't want to make the user refresh the page every 15 minutes or so, it's a single-page-application.
So, I tried to change slidingExpiration to "true" and create a ping (with ajax) every 17 minutes and it really stopped the session expiration and the annoying message - but the cookie didn't expired after 3 hours (I logged in with remember me 'false')!
What can I do?
Right click your application pool from IIS management console and look for "Idle time-out(minutes)".
You can adjust the setting to 0 (zero) which effectively disables the timeout so that the application pool will never shut down due to being idle.
I would double check your IIS settings. See what your App Pool Idle Timeout value is set to. By default it's 20 minutes. When the App Pool goes idle (no users accessing the app pool) for twenty minutes, you will loose session state (All data stored in the session will be cleared).
With more users this problem would work itself out, but presuming you are the only person testing, increasing this value to something greater than 180 minutes will prevent the timeout, or you could set the value to zero to disable the app pool idle timeout altogether.
See this answer for information on checking your app pool timeout in IIS Express... https://stackoverflow.com/a/10222419/386856
Do note that a dead app pool can take several seconds to re-spawn. It may be beneficial to increase this value anyways. This will prevent users from having an extremely slow experience if they happen to be the person that's unlucky enough to have to wait for the app pool to restart.
Update
To allow for a change in timeout for users who don't click remember me, you can create a custom attribute or you could modify the FormsAuthentication timeout via C#. Here are good references on setting the timeout via code. https://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration.timeout%28v=vs.110%29.aspx and https://msdn.microsoft.com/en-us/library/system.web.configuration.formsauthenticationconfiguration(v=vs.110).aspx If you want the timeout to expire right at 3 hours, even if the user has activity be sure slidingExpiration is false in your web config. If you want the timeout to expire 3 hours after the user's last activity be sure slidingExpiration is true. So before you set the cookie try something like the following (Be sure to check the OpenWebConfiguration path):
System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("/aspnetTest");
AuthenticationSection authenticationSection = (AuthenticationSection)configuration.GetSection("system.web/authentication");
FormsAuthenticationConfiguration formsAuthentication = authenticationSection.Forms;
formsAuthentication.Timeout = System.TimeSpan.FromHours(3);
formsAuthentication.SlidingExpiration = true;
I solved this by just creating my own encrypted cookie which will persist the user's session if present. In an action filter attribute, check if the user's session is expired, check for this cookie. If the cookie exists, verify the information and reestablish the session. If the user doesn't have a session, doesn't have a cookie, or the encrypted credentials are incorrect, redirect the user to the login page. Since everything is handled in the code, there is no guess work on the server settings.
On login with remember me checked:
if (RememberMe ?? false)
{
var authCookie = new HttpCookie(Config.AuthorizationCookie);
authCookie.Values.Add("ID", Crypto.EncryptStringAES(UserSession.Current.Account.ID.ToString(), Config.SharedSecret));
authCookie.Expires = DateTime.Now.AddDays(30);
AuthorizationCookie = authCookie;
}
Response.AppendCookie(AuthorizationCookie);
On page visit without session (done inside an attribute attached to necessary controllers and actions):
_account = UserSession.Current.Account;
// check if there is currently an account in the session
if(_account == null)
{
// check the user authorization cookie for a user id
HttpCookie authCookie = HttpContext.Current.Request.Cookies[Config.AuthorizationCookie] ?? new HttpCookie(Config.AuthorizationCookie);
if (authCookie.HasKeys && !String.IsNullOrEmpty(authCookie["ID"]))
{
// decrypt the user id for database lookup
_userID = Crypto.DecryptStringAES(authCookie.Values["ID"], Config.SharedSecret);
}
}
Re-establish the session if necessary (done inside a database connection)
// called within a database connection's using statement
protected override void Query(DatabaseContext db)
{
// check the database for the user account
if(_account == null && !String.IsNullOrEmpty(_userID))
{
int tempID;
int? id;
id = int.TryParse(_userID, out tempID) ? tempID : (int?)null;
if(id.HasValue)
{
_sessionRestored = true;
_account = db.User.Find(id);
if(_account != null)
{
_account.LastLogon = DateTime.UtcNow;
db.SaveChanges();
}
}
}
}
Finally restore the session:
if (_account != null)
{
// set the current account
UserSession.Current.Account = _account;
if(_sessionRestored)
{
UserSession.Current.Refresh();
}
}
Your code may look a bit different but that is the crux of how I did it.

Increase timeout of an already started session

I want to add a "keep me logged in" option to my custom login control.
This is how I'm currently using the session:
I'm saving and reading values from HttpContext.Current.Session["key"] manually. Works fine.
Relevant parts of web.config:
<sessionState mode="StateServer" useHostingIdentity="true" cookieless="false" timeout="120" stateConnectionString="tcpip=127.0.0.1:42424" />
<authentication mode="Forms">
<forms loginUrl="/login" name="AuthCookie" timeout="120" slidingExpiration="true" path="/" />
</authentication>
<authorization>
<allow users="*" />
</authorization>
As you can see, the default duration of a session is 120 minutes.
"Logout":
Session.Clear();
Session.Abandon();
Through a custom login control with textboxes, I grant access to a member area. (I don't use System.Web.Security.FormsAuthentication)
After entering valid credentials and a checked checkbox "keep logged in", I want to increase the duration of the already active session to ~30 days.
So far I've found solutions like
FormsAuthenticationTicket fat = new FormsAuthenticationTicket(1, "username", DateTime.Now, DateTime.Now.AddMinutes(1), false, "username");
string encTicket = FormsAuthentication.Encrypt(fat);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) { Expires = fat.Expiration });
which don't work, because System.Web.Security.FormsAuthentication.Timeout is still at 120 minutes.
The same goes for setting
Session.Timeout = 666;
Any suggestions?
You can't really approach it this way. You can't persist a session over days - it's just not going to scale well.
What most people do is provide a means for automatic login, so that when their session expires, they are seamlessly logged back in on the next action/reload. Most people do this with a cookie that contains a unique hash, which is checked at the server. If you want the person to be logged in for 30 days, you just set the cookie to expire in 30 days time.
I decided to give a short summary how I ended up doing it, because #David Haney asked me to:
I added a column to my usertable, which contains a GUID that is used for "relogging in" / giving credentials again. That GUID is created upon login and stored in the database.
It's also stored as an ecrypted value in a cookie. (My site doesn't use SSL)
Added to Login routine (if a user checked the "remeber me" checkbox):
HttpCookie aCookie = new HttpCookie("Session");
Guid sessionGuid = // Buisiness layer call to generate value
String sessionID = sessionGuid.ToString();
aCookie.Value = Helper.Protect(sessionID, "sessionID");
aCookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(aCookie);
where Helper.Protect and Helper.Unprotect are used from here How to use MachineKey.Protect for a cookie? to store an encrypted and MAC signed value in a cookie.
Relogging is done by having every content page inherit from a class, that implements that logic and inherits from System.Web.UI.Page.
public class BasePage : System.Web.UI.Page
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Request.Cookies["Session"] != null && !CustomIsLoggedInCheckMethod)
{
String unprotected = Helper.Unprotect(Request.Cookies["Session"].Value, "sessionID");
Guid sessionID = Guid.Parse(unprotected);
// Calls to buisiness layer to get the user, set sessions values et cetera
}
}
}
If a user was banned after the last session or logs out, the cookie value expiration date will be set to a date in the past:
HttpCookie myCookie = new HttpCookie("Session");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
Edit:
Ah I forgot to mention this. I've also added a notification bar, that tells the user that he has been logged back in. It's based on http://blog.grio.com/2012/11/a-copypaste-ble-jquery-notification-bar.html
See Demo

How can I expire the session when the user doesn't work with website?

Hello, I created a web site application with asp.net 4.5 and asp.net membership. I want user session to be expire if the user doesn't work with site (like Facebook).
I have set the timeout in web.config for the session but this time gets finished (times out), either if user works or doesn't work. Is there something I'm missing?
<authentication mode="Forms">
<forms loginUrl="~/Pages/Login.aspx" slidingExpiration="true" timeout="1"></forms>
</authentication>
While setting the forms auth cookie you need to set an expiry time for the cookie and create a http module in your application where you check the auth cookie in the request headers and if its not present you logout the user and redirect to the login page. And if the cookie exists just reset the expiry time for the cookie in the response.
Refer to this link. This is an answered that I'm currently help with another user. This should show you how to make the session start once the user logs in.
Edit: Not sure why the downvote, but here is code then.
Change the timeouts on each of the forms authentication and sessionState like below.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" defaultUrl="~/Dashboard.aspx" timeout="60"/>
</authentication>
<sessionState timeout="60" mode="InProc" cookieless="false" />
Then, put this into your Site.Master.cs under the page load.
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
// Handle the session timeout
string sessionExpiredUrl = Request.Url.GetLeftPart(UriPartial.Authority) + "/DealLog/Account/SessionExpired.aspx";
StringBuilder script = new StringBuilder();
script.Append("function expireSession(){ \n");
script.Append(string.Format(" window.location = '{0}';\n", sessionExpiredUrl));
script.Append("} \n");
script.Append(string.Format("setTimeout('expireSession()', {0}); \n", this.Session.Timeout * 60000)); // Convert minutes to milliseconds
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "expirescript", script.ToString(), true);
}
The session will only expire if the user is authenticated. The user logs in, becomes inactive, and then session times out. Once it times out, goes to an SessionExpired page. On the session expired page, place
FormsAuthentication.SignOut();
in the page load so it signs out the user. Then you can set up a redirect from there. The Authentication and SessionState timeouts are both in minutes. 60 = 1 hour.
Edit 2: It looks like the user of the question that was linked in my answer was deleted by the user. Sorry for that. Hope this helps though.

Categories