HTTP/HTTPS C# MVC 5 Cookies being sent but not being recollected - c#

Ok basically when my website had no SSL certificate I was able to use my remember me cookies just fine
Response.Cookies["censid"].Value = sessInfo.sid;
Response.Cookies["censid"].Expires = DateTime.UtcNow.AddDays(30);
Response.Cookies["censid"].Domain = "my-domain.com";
It worked just fine in this state. Once the SSL Cert was added it still sends the cookie in site responses but the client does not send the cookie on request, same for HTTP. I then changed the code to what is below and still the issue persists.
Response.Cookies["censid"].Value = sessInfo.sid;
Response.Cookies["censid"].Expires = DateTime.UtcNow.AddDays(30);
Response.Cookies["censid"].Domain = "my-domain.com";
Response.Cookies["censid"].Secure = true;
Here is my code to try and retrieve the set cookie
HttpCookie cookie = Request.Cookies["censid"];
if (cookie != null)
{
string sid = cookie.Value;
UserIdFromSession userid = await UserHandler.validateSessionId(sid);
if (userid.status == SessionResult.SessionSuccess)
{
Session["sid"] = sid;
Session["username"] = UserHandler.getUsernameFromUserId(userid.userId);
return RedirectToAction("Index", "User");
}
}
I still have HTTP enabled so people can access HTTPS and HTTP versions of my website, the cookies are still "set" but when I try to load the site again the cookies are not sent in the request.

Related

HttpListenerResponse adding a 2nd cookie makes all cookies disappear

I have the following code:
void WriteConnectionId(HttpListenerContext context, string id)
{
var cookie = context.Response.Cookies[CookieConnectionId];
if (cookie == null)
{
cookie = new Cookie(CookieConnectionId, id)
{
HttpOnly = true,
Secure = true,
Path = "/"
};
context.Response.Cookies.Add(cookie);
}
else
{
cookie.Value = id;
}
//context.Response.SetCookie(new Cookie("lalala", "lololo"));
}
This code stores correctly the cookie for "connection Id" in the client. In Chrome's console I can see the cookie in the list of cookies.
However, if I uncomment the last line that adds an extra cookie, then neither the session cookie or the dummy cookie make it to the client. They do not appear in Chrome's console.
Edit: removing the "/" path on the first cookie makes the first cookie appear, though with both values from the 1st and 2nd cookie concatenated with a comma.
Try
context.Response.AppendCookie(new Cookie("lalala", "lololo"));
I ended up fixing this issue by creating the following function:
void FlushCookie(HttpListenerContext context, Cookie cookie)
{
var builder = new StringBuilder();
builder.Append(cookie.Name);
builder.Append("=");
builder.Append(HttpUtility.HtmlAttributeEncode(cookie.Value));
builder.Append(";");
context.Response.Headers.Add(HttpResponseHeader.SetCookie, builder.ToString());
}
This can be modified further to add cookie expiration, path, etc.

Send Cookie in Post Response WebAPI

I am trying to send the user a cookie after I authenticate him. everything works perfect, the response is being constructed in my code, but even after the client got the response, There is no cookie saved in the browser (checking it via chrome F12 -> Resources).
Note: I can see the response being sent in fiddler with my cookie:
I wonder what is going wrong and why the browser doesn't save the cookie.
Here is the WebAPI function that handles the Post request:
public HttpResponseMessage Post([FromBody]User user)
{
IDal dal = new ProGamersDal();
var currentUser = dal.GetUser(user.Username, user.Password);
if (currentUser == null)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Bad request.");
}
else
{
var res = new HttpResponseMessage();
var cookie = new CookieHeaderValue("user",JsonConvert.SerializeObject(new ReponseUser(){username = currentUser.Username, role = currentUser.Role}));
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
res.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return res;
}
}
I've found out what the problem is since in Firefox the cookie was saved.
In chrome you cannot set a cookie with the domain of 'localhost' since it is considered as invalid domain (valid domain must contain two dots in it) - and therefore the cookie is invalid.
In order to solve it, in case of localhost, you should either:
set the domain to null.
set the domain to '' (empty)
set the domain to '127.0.0.1'
This is the fix in my code:
cookie.Domain = Request.RequestUri.Host == "localhost" ? null : Request.RequestUri.Host;

Do I have to rewrite cookie everytime I postback to retain it?

I don't really understand the difference between request cookie and response cookie. And it seem like everytime I postback, if I don't manually rewrite the cookie from request to response, then it disappears. How do I solve this?
public string getCookie(string name) {
if (Request.Cookies["MyApp"] != null && Request.Cookies["MyApp"][name] != null) {
return Request.Cookies["MyApp"][name];
} else if (Response.Cookies["MyApp"] != null && Response.Cookies["MyApp"][name] != null) {
return Response.Cookies["MyApp"][name];
} else {
return "";
}
}
public void writeCookie(string name, string value) {
Response.Cookies["MyApp"][name] = value;
HttpCookie newCookie = new HttpCookie(name, value);
newCookie.Expires = DateTime.Now.AddYears(1);
Response.SetCookie(newCookie);
}
Request.Cookies["MyApp"];
Code above will return you a cookie with name "MyApp" Doing this:
Request.Cookies["MyApp"][name]
You are taking value "name" from cookie called "MyApp".
But in your setCookie code you are setting a cookie with called name and do not create a cookie called "MyApp":
HttpCookie newCookie = new HttpCookie(name, value);
newCookie.Expires = DateTime.Now.AddYears(1);
Response.SetCookie(newCookie);
So, you should remove ["MyApp"] from any place you have it, or you may do something like this in setCookie:
public void writeCookie(string name, string value) {
if(Response.Cookies["MyApp"] == null) {
HttpCookie newCookie = new HttpCookie("MyApp");
newCookie.Expires = DateTime.Now.AddYears(1);
Response.SetCookie(newCookie);
}
if(Response.Cookies["MyApp"][name] == null)
Response.Cookies["MyApp"].Values.Add(name, value);
else
Response.Cookies["MyApp"][name] = val;
// or maybe simple Response.Cookies["MyApp"][name] = val; will work fine, not sure here
}
Request is the "thing" you get when the user tries to get to your website, while Response is a way of responding to this request.
In other words, see the official msdn documentation, namely this part:
ASP.NET includes two intrinsic cookie collections. The collection
accessed through the Cookies collection of HttpRequest contains
cookies transmitted by the client to the server in the Cookie header.
The collection accessed through the Cookies collection of HttpResponse
contains new cookies created on the server and transmitted to the
client in the Set-Cookie header.
http://msdn.microsoft.com/en-us/library/system.web.httprequest.cookies.aspx
So no, you don't have to create new cookies every time, unless they have already expired. Just be sure you reference the right collection of cookies.
You might want to check the domain and path that are being assigned to the cookie. It could be that your saved cookies are just being orphaned because the path is too specific or because the wrong domain is being set.
Domain is the server name that the browser sees such as "yourdomain.com". If the cookie is set with a different domain than this then the browser will never send it back. Likewise, the path of the cookie is the path to the resource being requested such as "/forum/admin/index" etc. The cookie is sent for that location and all child locations, but not for parent locations. A cookie set for "/forum/admin/index" will not be sent if you're accessing a page that sits in the "/forum" directory.

Lost session/cookie when login as another user

I am building dnn module which allow logged in user to log in as another user.
But I have some wired issue here.
This is how I log out current user and login as another user:
UserInfo userInfo = UserController.GetUserById(portalId, userId);
if (userInfo != null)
{
DataCache.ClearUserCache(this.PortalSettings.PortalId, Context.User.Identity.Name);
if (Session["super_userId"] == null)
{
Session["super_userId"] = this.UserId;
Session["super_username"] = this.UserInfo.Username;
}
HttpCookie impersonatorCookie = new HttpCookie("cookieName");
impersonatorCookie.Expires = DateTime.Now.AddHours(1);
Response.Cookies.Add(impersonatorCookie);
Response.Cookies["cookieName"]["super_userId"] = this.UserId.ToString();
Response.Cookies["cookieName"]["super_username"] = this.UserInfo.Username;
PortalSecurity objPortalSecurity = new PortalSecurity();
objPortalSecurity.SignOut();
UserController.UserLogin(portalId, userInfo, this.PortalSettings.PortalName, Request.UserHostAddress, false);
Response.Redirect(Request.RawUrl, true);
}
And in PageLoad() I try to read value from this cookie but it doesn't read anything:
try
{
string super_userId = Request.Cookies["cookieName"]["super_userId"];
string super_username = Request.Cookies["cookieName"]["super_username"];
if (!String.IsNullOrEmpty(super_userId))
{
this.Visible = true;
this.lblSuperUsername.Text = Session["super_username"].ToString();
this.txtPassword.Enabled = true;
this.btnBackToMyAccount.Enabled = true;
}
...
I also have tried to do the same with session but nothing works, and I can't figure why?
As I find here, there can be problems with setting cookies in a request that gets redirected, and here is stated that cookies won't get set with a redirect when their domain is not /.
So you can try to not redirect using HTTP headers, but show a "Logged In" page instead that contains a "Home" link and a meta refresh or Javascript redirect.
By the way, setting a UserID in a cookie is not really the way to go. What if I change that cookie value to 1?
I suggest when you set a new cookie to always set the Domain, and probably and the Expires.
Response.Cookies[cookieName].Domain = RootURL;
Response.Cookies[cookieName].Expires = DateTime.UtcNow.AddDays(cDaysToKeep);
The domain is very importan to be the url with out the subdomain, eg only the mydomain.com with out the www. because if a cookie is set from www.mydomain.com and you try to read it from mydomain.com or vice versa, then the cookie will not be read and you may lost it / overwrite it.
So I suggest to make a function that when you set a cookie, you set at least 3 parametres, the Domain, the Expires, and the Value.
Similar questions and answers :
Multiple applications using same login database logging each other out
asp.net forms authentication logged out when logged into another instance
Put these two statements
Response.Cookies["cookieName"]["super_userId"] = this.UserId.ToString();
Response.Cookies["cookieName"]["super_username"] = this.UserInfo.Username;
after
UserController.UserLogin(portalId, userInfo, this.PortalSettings.PortalName, Request.UserHostAddress, false);
May be the UserLogin method is resetting the Session variables.
Hope it Helps :)

ASP.NET Send Cookies to client Browser

I'm integrating a single sign on over 2 ASP.Net applications. For that matter i have a web service that is called by the main app. when a user logs in. this web service authenticates the user in my second application and brings back the authentication cookies i need to deliver to the client browser so he can navigate freely and logged in both applications.
I was planning to use HttpContext.Current.Response.Cookies.Add(cookie) in order to deliver the new cookies but this seems not to work as no cookies are added what so ever...
Any ideas on what might be going wrong?
here is my code:
var service = new localhost.UserManagement();
service.CookieContainer = new CookieContainer();
if (service.AuthenticateUser("test#user.pt", "test"))
{
var collection = service.CookieContainer.GetCookies(new Uri("http://localhost"));
foreach (Cookie item in collection)
{
HttpContext.Current.Response.Cookies.Add(CookieConverter(item));
}
HttpContext.Current.Response.Flush();
return true;
}
return false;
Note: CookieConverter(item) is used to convert Cookie object i receive to HttpCookie
Thanks
private HttpCookie CookieConverter(Cookie cookie)
{
var result = new HttpCookie(cookie.Name);
result.Value = cookie.Value;
result.Domain = cookie.Domain;
result.Expires = cookie.Expires;
result.Path = cookie.Path;
result.Secure = cookie.Secure;
result.HttpOnly = cookie.HttpOnly;
return result;
}
You should check:
collection is empty? Could you set braeakpoint and check collection?
where is this code located? (.aspx page, web service, http handler?)
try to create minimalistic "Cookie setter" that just add simple cookie in any way

Categories