ASP.NET MVC Cookie loses value when page is changed - c#

When a user logs in to my site, I create a cookie with some info in it. However, whenever they change page from logging in, the cookie loses it's value. Cookie is still there but it's empty.
I've checked my code and the cookie doesn't get rewritten by anything I've done.
Does anyone have any idea to why the cookie becomes empty when the page is changed?
Here's the method for creating the cookie.
public static void CreateUserCookie(long userId, string username, bool rememberMe) {
HttpCookie cookie = new HttpCookie("CookieName");
cookie.Value = string.Format("{0}+{1}+{2}", userId, username, SecurityUtils.CreateHashedCookieValue(userId, username));
if (rememberMe) {
cookie.Expires = DateTime.Now.AddMonths(1);
} else {
cookie.Expires = DateTime.MinValue;
}
HttpContext.Current.Response.Cookies.Add(cookie);
}

When you call this method, do you pass in true for the "rememberMe" parameter? If not, the cookie will instantly expire.
You haven't shown your calling code, so this is potentially what you've done.

Related

System.ArgumentException: Invalid value for 'encryptedTicket' parameter happens on any login after the first successful login

I am currently trying to replace our company wide user authentication that we use for all our internal web apps and what not as our current one was made in 2006 and fails on the regular. I was told to make it as simple as possible to implement on all existing projects. It is a .NET class library. It's .dll will be added as a reference to existing projects.
I am having an issue where I can log in exactly one time after all cookies have been cleared. Once I logout and log back in I get System.ArgumentException: Invalid value for 'encryptedTicket' parameter. I found some posts suggesting the cookie may be null, or I'm not trying to decrypt the name and not the value, but that wasn't the case. This happens on chrome and edge.
The user is authenticated every time though, assuming the correct username and password is used as I get redirected to the success page.
After authentication I add a cookie and then redirect.
private void AddCookie(int compID, bool persist, HttpContext httpContext)
{
httpContext.Request.Cookies.Add(SetUpSession(compID, persist));
FormsAuthentication.RedirectFromLoginPage(compID.ToString(), persist);
}
My method for creating the cookie
private HttpCookie SetUpSession(int companyID, bool persist)
{
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1, // ticket version
companyID.ToString(), // authenticated username
DateTime.Now, // issueDate
DateTime.Now.AddMinutes(30), // expiryDate
persist, // true to persist across browser sessions
FormsAuthentication.FormsCookiePath); // the path for the cookie
String encTick = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie("Cookie", encTick);
cookie.HttpOnly = true;
return cookie;
}
After I redirect to the success page there is a snipped of code that checks to see if the user is logged in. This is where the error happens
public dynamic isLoggedIn(HttpContext httpContext)
{
AuthenticationUtilities authUtil = new AuthenticationUtilities();
if (httpContext.Response.Cookies["Cookie"] != null)
{
companyID = authUtil.Authenticate(httpContext.Request.Cookies["Cookie"]);//the error occurs here
authUtil = new AuthenticationUtilities(companyID);
return authUtil;
}
else
{
httpContext.Response.Redirect("~/login.aspx");
return null;
}
}
The method that decrypts the cookie
public int Authenticate(HttpCookie cookie)
{
FormsAuthenticationTicket authTick = FormsAuthentication.Decrypt(cookie.Value);
return int.Parse(authTick.Name);
}
this method is called on any page that requires the user to be logged in, like this.
LMFJAuth.AuthenticationUtilities auth = _LMFJAuth.isLoggedIn(HttpContext.Current);//if the cookie is null it redirects to login.
This is the logout method
public void LogOut(HttpContext httpContext)
{
FormsAuthentication.SignOut();
HttpCookie cookie = new HttpCookie("Cookie");
cookie.Expires = DateTime.Now.AddMinutes(-1);
httpContext.Session.Clear();
httpContext.Response.Cookies.Add(cookie);
httpContext.Response.Redirect(FormsAuthentication.LoginUrl);
}
Can somone help explain what may be going on in which the value for the encrypted ticked is coming up as invalid after the first successful login/logout?
For me it was that the encrypted value of cookie.Value was coming up as greater than the maximum value of 4096, being 4200 in my case. I had just added some role strings to the user data.
I found it help to look up the source code of Microsoft classes when I'm stuck, in this case I used:
http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8#0/untmp/whidbey/REDBITS/ndp/fx/src/xsp/System/Web/Security/FormsAuthentication#cs/1/FormsAuthentication#cs.

ASP.Net MVC 5 Cookie loses expiration upon return from the browser

This simple code has left me perplexed.
From this controller action method, I create a cookie , give it an expiration and set it to be HttpOnly. The cookie gets created correctly, added to the Response, looks correct on the browser debugger , however when returned back into the same code after refresh , loses expiration and HttpOnly flag. The cookie itself is still there , but the values are lost. If I watch Request.Cookies["mycookie"] back into the same controller/action method after a trip to the browser, the values are gone - the cookie itself is not deleted though.
If somebody understands this behaviour please explain, what might be happening here-
public class HomeController : Controller
{
public ActionResult Index()
{
if (this.ControllerContext.HttpContext.Request.Cookies["mycookie"] == null)
{
HttpCookie cookie = Response.Cookies["mycookie"];
cookie["mycookie"] = "test";
cookie.Expires = DateTime.Now.AddDays(90);
cookie.HttpOnly = true;
this.ControllerContext.HttpContext.Response.SetCookie(cookie);
}
return View();
}
The problem is this line: return View();
The cookie cannot be set and then read again (server-side) in the same round trip to the server. So, you need to create a second request for the cookie to be available. The simplest way is to force a second request by calling RedirectToAction, although you could use some clever AJAXy way of doing it so it appears to be the same request.
See this post for a working example - here is the part where the cookie is written and deleted.
public class CookieController : Controller
{
public ActionResult Create()
{
HttpCookie cookie = new HttpCookie("Cookie");
cookie.Value = "Hello Cookie! CreatedOn: " + DateTime.Now.ToShortTimeString();
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
return RedirectToAction("Index", "Home");
}
public ActionResult Remove()
{
if (this.ControllerContext.HttpContext.Request.Cookies.AllKeys.Contains("Cookie"))
{
HttpCookie cookie = this.ControllerContext.HttpContext.Request.Cookies["Cookie"];
cookie.Expires = DateTime.Now.AddDays(-1);
this.ControllerContext.HttpContext.Response.Cookies.Add(cookie);
}
return RedirectToAction("Index", "Home");
}
}
Ashiquizzaman is also correct in that you are not setting the value of the cookie, but that is only half of the problem.
Please see this code below.
var request=this.ControllerContext.HttpContext.Request;
var response =this.ControllerContext.HttpContext.Response;
//OR
// var request=System.Web.HttpContext.Current.Request;
//var response =System.Web.HttpContext.Current.Response;
if (request.Cookies["mycookie"] == null)
{
HttpCookie cookie= new HttpCookie("mycookie");
cookie.Value = "test";//your problem hear.
cookie.Expires = DateTime.Now.AddDays(90);
cookie.HttpOnly = true;
response.Cookies.Add(cookie);
}
else//need to update your cookies then use this block or not
{
HttpCookie cookie=Request.Cookies["mycookie"];
cookie.Value = "test";//your problem hear.
cookie.Expires = DateTime.Now.AddDays(90);
cookie.HttpOnly = true;
//response.Cookies.SetCookie(cookie);
response.Cookies.Set(cookie);//To update a cookie, you need only to set the cookie again using the new values.
}
Hopefully it's help you.

Response cookie not updating

When I log I create the following cookie:
HttpCookie cookie = new HttpCookie("Ortund");
// insert cookie values
cookie.Expires = DateTime.Now.AddMonths(1);
Response.Cookies.Add(cookie);
When I request data from this cookie, I use Request.Cookies:
string username = Convert.ToString(Request.Cookies["Ortund"]["Username"]);
When i log out, I do this:
HttpCookie cookie = new HttpCookie("Ortund");
cookie.Expires = DateTime.Now.AddMonths(-1);
Response.Cookies.Add(cookie);
For some reason, now I'm sitting with a cookie that has an expiry date of 0001-01-01 12:00:00 AM in Request.Cookies["Ortund"] and the expiry date of the cookie doesn't change no matter how many times I log in.
Have I done something wrong here? Is this even close to how it should be done?
In your logout you are creating a new instance of the cookie. Also you are using Response.Cookies.Add which may allow multiple cookies of the same name to be appended to the Response.
I would suggest you to check the Request for the cookie key and if it doesn't exist add the cookie.
For updating the cookie, first get the existing cookie object and use Response.SetCookie to update the value.
Code
set
if(!Request.Cookies.AllKeys.Contains("Ortund"))
{
HttpCookie cookie = new HttpCookie("Ortund");
// insert cookie values
cookie.Expires = DateTime.Now.AddMonths(1);
Response.Cookies.Add(cookie);
}
update
if (Request.Cookies.AllKeys.Contains("Ortund"))
{
HttpCookie cookie = Request.Cookies["Ortund"];
cookie.Expires = DateTime.Now.AddMonths(-1);
Response.SetCookie(cookie);
}

SetPrincipal (#User.Identity.Name) from a cookie in ASP.Net MVC

I like to know how I can set the #User.Identity.Name via a cookie when a user clicks on a remember me checkbox.
Cookie code
if (_model.RememberMe)
{
HttpCookie cookie = new HttpCookie("login");
cookie.Values.Add("username", _model.Username);
cookie.Expires = DateTime.Now.AddDays(30);
Response.Cookies.Add(cookie);
}
First login code
if (Membership.ValidateUser(Username,Password))
{
RememberMe();
FormsAuthentication.RedirectFromLoginPage(Username, false);
}
On the first login the Identity.name is set but when I close the browser and go back on to the site. it logs in correctly without the user putting in their credentials but the Identity.name is empty.
if (Request.Cookies["login"] != null)
{
// We know the automatic log in has worked as it comes into here...
}
What do I need to do once the user by passes the login page so I can setup the iPrincipal object?
Thanks
Try below code please
Note : please check it on page view not in the same method on creation of cokies
private void CreateCokies(string userName)
{
var authTicket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(30), true, userName);
string cookieContents = FormsAuthentication.Encrypt(authTicket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieContents)
{
Expires = authTicket.Expiration,
Path = FormsAuthentication.FormsCookiePath
};
Response.Cookies.Add(cookie);
}

When to use Request.Cookies over Response.Cookies?

Do I use response when at a page event (e.g. load) as this is a response from ASP.NET, and request when pressing a button as this is a response going to ASP.NET for processing? Or is there more to it?
They are 2 different things, one SAVES [Response], the other READS [Request]
in a Cookie (informatics speaking) :)
you save a small file for a period of time that contains an object of the type string
in the .NET framework you save a cookie doing:
HttpCookie myCookie = new HttpCookie("MyTestCookie");
DateTime now = DateTime.Now;
// Set the cookie value.
myCookie.Value = now.ToString();
// Set the cookie expiration date.
myCookie.Expires = now.AddMinutes(1);
// Add the cookie.
Response.Cookies.Add(myCookie);
Response.Write("<p> The cookie has been written.");
You wrote a cookie that will be available for one minute... normally we do now.AddMonth(1) so you can save a cookie for one entire month.
To retrieve a cookie, you use the Request (you are Requesting), like:
HttpCookie myCookie = Request.Cookies["MyTestCookie"];
// Read the cookie information and display it.
if (myCookie != null)
Response.Write("<p>"+ myCookie.Name + "<p>"+ myCookie.Value);
else
Response.Write("not found");
Remember:
To Delete a Cookie, there is no direct code, the trick is to Save the same Cookie Name with an Expiration date that already passed, for example, now.AddMinutes(-1)
this will delete the cookie.
As you can see, every time that the time of life of the cookie expires, that file is deleted from the system automatically.
In a web application the request is what comes from the browser and the response is what the server sends back. When validating cookies or cookie data from the browser you should use the Request.Cookies. When you are constructing cookies to be sent to the browser you need to add them to Response.Cookies.
When writing a cookie, use Response but reading may depend on your situation. Normally, you read from Request but if your application is attempting to get a cookie that has just been written or updated and the round trip to the browser has not occured, you may need to read it form Response.
I have been using this pattern for a while and it works well for me.
public void WriteCookie(string name, string value)
{
var cookie = new HttpCookie(name, value);
HttpContext.Current.Response.Cookies.Set(cookie);
}
public string ReadCookie(string name)
{
if (HttpContext.Current.Response.Cookies.AllKeys.Contains(name))
{
var cookie = HttpContext.Current.Response.Cookies[name];
return cookie.Value;
}
if (HttpContext.Current.Request.Cookies.AllKeys.Contains(name))
{
var cookie = HttpContext.Current.Request.Cookies[name];
return cookie.Value;
}
return null;
}
The cookies comes from the browser in the Request.Cookies collection. That is where you read the cookies that was sent.
To send cookies back to the browser you put them in the Response.Cookies collection.
If you want to delete a cookie, you have to tell the browser to remove it by sending the cookie with an expiration date that has passed. The browser is using the local time of the client computer so if you are using the server time to create a date, be sure to subtract at least one day to be sure that it has actually passed in the clients local time.
When i create or update a cookie in .NET i normally do it to both the request and response cookie collection. That way you can be sure if you try to read the cookie further down the page request sequence it will have the correct information.
Andrew's Code gave an error in "AllKeys.Contains" Method. So I corrected a little..
public void WriteCookie(string strCookieName, string strCookieValue)
{
var hcCookie = new HttpCookie(strCookieName, strCookieValue);
HttpContext.Current.Response.Cookies.Set(hcCookie);
}
public string ReadCookie(string strCookieName)
{
foreach (string strCookie in HttpContext.Current.Response.Cookies.AllKeys)
{
if (strCookie == strCookieName)
{
return HttpContext.Current.Response.Cookies[strCookie].Value;
}
}
foreach (string strCookie in HttpContext.Current.Request.Cookies.AllKeys)
{
if (strCookie == strCookieName)
{
return HttpContext.Current.Request.Cookies[strCookie].Value;
}
}
return null;
}

Categories

Resources