I am creating my own authentication ticket using the following code:
string formsCookieStr = string.Empty;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // version
username, // user name
DateTime.Now, // issue time
DateTime.Now.AddMinutes(30), // expires
false, // Persistence
userRoleData // user data
);
formsCookieStr = FormsAuthentication.Encrypt(ticket);
HttpCookie FormsCookie = new HttpCookie(FormsAuthentication.FormsCookieName, formsCookieStr);
HttpContext.Response.Cookies.Add(FormsCookie);
I want the expiration to be a sliding expiration - each time the client sends a request then the expiration should be reset to 30 mins. However, I'm only creating the ticket when the user first logs in. Will ASP.NET automatically keep sliding the expiry time for me, or do I need to do something 'manually' to implement the sliding expiration?
That's configured in the forms section of web.config. The way sliding expiration works is that on each request the ASP.NET engine rewrites the authentication cookie by incrementing the timeout:
<authentication mode="Forms">
<forms
loginUrl="~/Account/LogOn"
timeout="2880"
slidingExpiration="true"
/>
</authentication>
Note however that enabling sliding expiration is one of the things considered as bad practice in the ASP.NET Security Practices.
Related
I developed website with ASP.NET. Now I make an authentification.
Authorization is made by another web service. If the answer from web-service is success, I create a ticket:
var ticket = new FormsAuthenticationTicket(1, param.Login, DateTime.Now, DateTime.Now.AddDays(1), false, string.Empty, FormsAuthentication.FormsCookiePath);
var encTicket = FormsAuthentication.Encrypt(ticket);
var AuthCookie = new HttpCookie(FormsAuthentication.FormsCookieName)
{
Value = encTicket,
Expires = DateTime.Now.AddDays(1)
};
Response.Cookies.Set(AuthCookie);
This code added authentification cookie. But if I add the next string after previous code:
Response.Redirect("<redirect address>");
cookie is disappeared after redirect.
Why it's happened?
web.config part of authentification here:
<authentication mode="Forms">
<forms name=".ASPXFORMSAUTH" loginUrl="~/login.ashx" />
</authentication>
It may happen that the cookie data being associated with the cookie has exceed the maximum allowed size in its encrypted format. Unencrypted, the data will not be too large.
Large size of the cookie may result in dropping of the cookie from the response header. Below fixes are worth trying:
Reduce the Amount of Data set in a cookie
Try cookie just once in unencrypted format. This way you will be confirmed that it is indeed the Size of cookie which is creating a problem
This POST gives a good information on Cookie size.
I'm using the Membership API for my login system and a wierd thing has been bothering me. I allow user to choose whether to "Remember Me", which means whether to create a persistent cookie with one month expiration period.
In the Web.config, I wrote:
<authentication mode="Forms">
<forms timeout="60" />
</authentication>
This is supposed to be a default session cookie of 60 minutes.
In the code behind of the login page:
if(Membership.ValidateUser(UsernameTextBox.Text, PasswordTextBox.Text))
{
authCookie = FormsAuthentication.GetAuthCookie(UsernameTextBox.Text, RememberMeCheckBox.Checked);
if(RememberMeCheckBox.Checked)
authCookie.Expires = DateTime.Now.AddMonths(1);
Response.Cookies.Add(authCookie);
Response.Redirect(FormsAuthentication.GetRedirectUrl(UsernameTextBox.Text, RememberMeCheckBox.Checked));
}
The result however is strange. I seem to have created a persistent cookie of 60 minutes! How is this possible?
You are setting the cookie expiration time to be be 1 month, but the authentication ticket that it contains has not been modified. It has inherited the default value of 60 minutes from your web config.
You likely want to synchronize cookie expiration with the authentication ticket expiration, or alternatively set the cookie to have a very long expiry date.
What you need to do is
create a FormsAuthenticationTicket instance manually and set the
Expiration property of the instance.
Use FormsAuthentication.Encrypt() to encrypt the ticket
Add a cookie to the Response.Cookies collection containing the ticket, manually. (rather then using get/setAuthCookie(), which uses
the web.config settings).
Some example code is in the documentation for FormsAuthentication.Encrypt().
I want to expire cookie that for FormsAuthentication when browser closed.
(I want to it works like PHP session does)
Here is my Auth code that located in Model (Not controller).
Models/Auth.cs
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
model.UserId,
DateTime.Now,
DateTime.Now.AddDays(1),
true,
model.UserId +" "+reader["lastname"],
FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
HttpContext.Current.Response.Cookies.Add(cookie);
Web.config
<authentication mode="Forms">
<forms name="user" timeout="60" loginUrl="~/Auth/login" path="/"></forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
And one more questions is, there are 2 times setting cookie timeout,
in ticket,
DateTime.Now.AddDays(1),
and in authentication in Web.config file
<forms name="user" timeout="60" loginUrl="~/Auth/login" path="/"></forms>
how different they are, and which one will effect to actual expire cookie?
Anybody know, please advise me.
Thank you!
You can't expire the cookie when the browser is closed. You can, however, make the cookie non-persistent, which means it will not save the cookie and thus when you open a new browser it will have a new cookie (be aware, however, that with the way most browsers cache non-persistent cookies with tabs, the entire browser has to be closed for this to clear it out).
As for your second question, the web.config entry is used if you do not specify a timeout.
jQuery unload event can be used to detect the browser closing.
But this event is also fired when : The user clicked on a link to leave the page, or typed in a new URL in the address bar. The forward and back buttons will trigger the event.Even a page reload will first create an unload event.
Bind an event handler to the "unload" JavaScript event.
Answer the your second question, the timeout that you set in your code with override the web.config entry.
On the same IIS web site, I have two ASP.NET web applications called /foo and /bar. Both use forms authentication and I want users to be able to log in and out of both sites independently.
With the standard configuration for forms authentication, it seems to send a cookie path of "/" for the forms auth cookie. This means that when a user logs into /bar it logs him out of /foo which is undesirable behaviour for me.
The obvious solution seems to be this:
FormsAuthentication.RedirectFromLoginPage(username, false, Request.ApplicationPath);
This makes the forms auth cookie have the application path which allows the user to log into /foo and /bar independently :-) However there is a further and more nasty problem: If the user tries to log into /Foo (with a capital F), IIS directs them to the web application /foo, but they can never log in because the browser (chrome in this case) is case sensitive when deciding whether to send the cookie based on the cookie path.
This seems to be a common problem which every ASP.NET web app developer will face but I can't see a sensible solution for it. Please tell me i've missed something obvious?
Thanks
Andy
I assume you have already solved this issue somehow, but since I stumbled upon this question I thought I should add my few cents.
To solve the issue use different cookie names in web.config. Something like:
<authentication mode="Forms">
<forms name=".ASPXFORMSAUTH_FOO"
loginUrl="public/login.aspx" cookieless="UseCookies" slidingExpiration="true"/>
</authentication>
and
<authentication mode="Forms">
<forms name=".ASPXFORMSAUTH_BAR"
loginUrl="public/login.aspx" cookieless="UseCookies" slidingExpiration="true"/>
</authentication>
Dim ticket As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, _
pUsernameEntered, _
DateTime.Now, _
DateTime.Now.AddMinutes(60), _
True, _
pOperatorID, _
FormsAuthentication.FormsCookiePath)
' Encrypt the ticket.
Dim encTicket As String = FormsAuthentication.Encrypt(ticket)
'create a cookie with the encrypted ticket
Dim authenticationCookie As New HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
'only create a persistent cookie if ticket persistent is checked
If (ticket.IsPersistent) Then
'give the cookie an expiration date outside of the forms authentication encrypted ticket
authenticationCookie.Expires = ticket.Expiration
End If
'save the cookie
HttpContext.Current.Request.Cookies.Remove(".cookiename")
Response.Cookies.Add(authenticationCookie)
In cookiename you can set you cookie name.
and in AddMinutes you can set your minutes values currently it is 60.
I'm using ASP.NET MVC 3 with the Authorize attribute, but it keeps kicking me to the logon page after 1 minute, but even though my expiration is set to a very high value, it times out quickly. I check the cookie in my browser and its still there and not set to expire until about a month later, and it's set to be persistent, so I'm not sure why it keeps booting me. It only happens on my published location, locally it works just fine.
var ticket = new FormsAuthenticationTicket(username, true, 500000);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.Expires = ticket.Expiration;
Response.Cookies.Add(cookie);
web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" timeout="7200" slidingExpiration="false"/>
</authentication>
Chances are the worker process is recycled meantime, Where do you store the sessions?
Making your sessions stored out of process may helps.