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.
Related
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.
We have Session hijacking and Session fixation problem with our asp.net application.
We have implemented SSL also.
1.. I have added below code in web.config file.
<----
<httpCookies httpOnlyCookies="true" requireSSL="true" />
<forms loginUrl="Homepage.aspx"
protection="All"
timeout="20"
name=".ASPXAUTH"
path="/"
requireSSL="true"
slidingExpiration="true"
/>
--->
2... Encrypting formsathuntication ticket and adding to the cookie after user is athunticated.
<---
FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;
tkt = new FormsAuthenticationTicket(1, uname, DateTime.Now, DateTime.Now.AddMinutes(20),false, "your custom data");
cookiestr = FormsAuthentication.Encrypt(tkt);
ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
ck.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(ck);
-->
3.. I'm removing session variables and passing null value to ASP.NET_SessionID on logout page and Error page.
SessionHandler.EndSession();
Session.RemoveAll();
Session.Abandon();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
}
if (Request.Cookies["AuthToken"] != null)
{
Response.Cookies["AuthToken"].Value = string.Empty;
Response.Cookies["AuthToken"].Expires = DateTime.Now.AddMonths(-20);
}
HttpCookie authcookie = Request.Cookies[FormsAuthentication.FormsCookieName];
authcookie.Expires = DateTime.Now.AddDays(-1D);
Response.Cookies.Add(authcookie);
FormsAuthentication.SignOut();
still problem is not solved...
Is your problem session hijacking, or authentication hijacking?
Are you trusting session values without validating identity? (Note that session and authentication are not intrinsically linked in ASP.NET).
If you've implemented SSL, why is your session cookie still set to requireSSL="false"?
Research best-practice, and see for yourself where you've gone wrong. For example - http://www.troyhunt.com/2010/07/owasp-top-10-for-net-developers-part-3.html
To elaborate on point 2.
There are two cookies in use here, one is for Session, the other for FormsAuthentication.
The FormsAuth cookie identifies the user, and all reasonable steps need to be taken to keep this one secure. Typically, requiring SSL is a good step (as you've applied in the edit of your example). The Session cookie though, often doesn't come under as close scrutiny for developers, but depending on how you're using it can be just as sensitive. A session fixation steals the session, not the authentication.
An example:
UserA logs in, they are an admin user. They receive a FormsAuth cookie stating "This is UserA", they might also get a session cookie stating "This User Is Admin".
UserB gets a copy of the session cookie belonging to UserA (they might do this via interception, or even just by being on the same machine after UserA logs out if the session cookie isn't cleared).
UserB logs in, they are a "read-only" user (not admin). They receive a FormsAuth cookie stating "This is UserB", they then inject the session cookie stolen at step 2. Meaning they have a FormsAuth cookie stating "This is UserB", and a Session cookie stating "This User Is Admin".
Presto, UserB is now admin.
The problem here (as it relates to point 2 of my original list of concerns), is that the server didn't verify the identity of the user in relation to its session. You can do your best to try and link the Session and Forms authentication tickets together somehow, and definitely make certain you're encrypting (SSL). OR, you can stop storing sensitive data in the session (or at least reduce it). When it comes to my "This User Is Admin" example above, the better implementation is to use the ASP.NET Role and Profile providers in conjunction with the Membership provider. The three of them go hand in hand, and there's a lot of examples out there on how to use them to your advantage.
This is only one possible line of investigation though and as #JohnFx rightly pointed out, you really need a focused question here before you can expect a good answer. When it comes to security implementation, it's important to understand the concepts involved, instead of just throwing example code at the issue. Your example code provided thus far looks suspiciously similar to a CodeProject article discussing session fixation, but do you understand what it's trying to accomplish? Do you know if it even applies to the problem you're experiencing?
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 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.
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.