If there is a cookie set for a subdomain, metric.foo.com, is there a way for me to delete the metric.foo.com cookie on a request to www.foo.com? The browser (at least Firefox) seems to ignore a Set-Cookie with a domain of metric.foo.com.
Cookies are only readable by the domain that created them, so if the cookie was created at metric.foo.com, it will have to be deleted under the same domain as it was created. This includes sub-domains.
If you are required to delete a cookie from metric.foo.com, but are currently running a page at www.foo.com, you will not be able to.
In order to do this, you need to load the page from metric.foo.com, or create the cookie under foo.com so it can be accessable under any subdomain. OR use this:
Response.cookies("mycookie").domain = ".foo.com"
...while creating it, AND before you delete it.
..untested - should work.
I had the same problem with subdomains. For some reason getting the cookie first from the request didn't work. Instead I ended up just creating a new cookie with the same cookie name, and expiry date in the past. That worked perfectly:
void DeleteSubdomainCookie(HttpResponse response, string name)
{
HttpCookie cookie = new HttpCookie(name);
cookie.Expires = DateTime.Now.AddMonths(-1);
cookie.Domain = ".yourdomain.com";
response.Cookies.Add(cookie);
}
Related
I am using both session and cookie to save information login details in sign in page and then checking this session and cookie before displaying details in the other page. Below is my code in sign in page
Session["PartnerId"] = authenticate.ToString();
//Cookie
HttpCookie CookiePartnerId = new HttpCookie("PartnerId");
CookiePartnerId.Value = authenticate.ToString();
//CookiePartnerId.Expires = DateTime.Now.AddHours(24);
Response.Cookies.Add(CookiePartnerId);
and here is the another page which retrieving session and cookie value
if (Session["PartnerId"] != null)
{
PartnerId = Convert.ToInt32(Session["PartnerId"].ToString());
}
else
{
PartnerId = Convert.ToInt32(Request.Cookies["PartnerId"].Value);
}
But now what I am facing is session is working fine but when it expires the cookie is not able to set the value ie (it is null). I am thinking of removing the session but cookie alone is not working.
I observed that in my local environment cookie is working but it is not working on the server. Is this because of SSL (https) I have in server? Or is there anything related to cookie I am not doing? Please advice
I am facing a weird issue regarding cookies: I am trying to set up a cookie with the user id the first time the user logs into the application, and next time, if the cookie exists, not require the user authentication again.
For this I am using the code below:
to set the cookie:
HttpCookie userCookie = new HttpCookie("UserCookie");
userCookie.Value = UserId.ToString();
userCookie.Expires = DateTime.Now.AddHours(1);
System.Web.HttpContext.Current.Response.Cookies.Add(userCookie);
to get the cookie:
HttpCookie UserCookie = System.Web.HttpContext.Current.Request.Cookies["UserCookie"];
if (UserCookie != null)
{
// redirect the user to another screen inside the application
}
The weird thing is that my cookie seems not to exist and the user is prompted with the log in screen all the time. When I try to use debugging, it appears to me that the cookie is not null, but it's got an empty string value. What can I do about this?
Many thanks!
Are you trying to GET the cookie in the same code that SETS the cookie? If so, the cookie won't exist. Cookie gets SET on the users browser when the page has been delivered.
Also, can you confirm UserID.ToString() isn't actually an empty string..?
To test properly, set the cookie on page A, then redirect to page B and GET the cookie here.
Title should say it all.
Here's the code to set the cookie:
// snip - some other code to create custom ticket
var httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encodedTicket);
httpCookie.Domain = "mysite.com";
httpContextBase.Response.Cookies.Add(httpCookie);
Here's my code to signout of my website:
FormsAuthentication.SignOut();
Environment:
ASP.NET MVC 3 Web Application
IIS Express
Visual Studio 2010
Custom domain: "http://localhost.www.mysite.com"
So when i try and log-off, the cookie is still there. If i get rid of the httpCookie.Domain line (e.g default to null), it works fine.
Other weird thing i noticed is that when i set the domain, Chrome doesn't show my cookie in the Resources portion of developer tools, but when i dont set the domain, it does.
And secondly, when i actually create the cookie with the custom domain, on the next request when i read in the cookie from the request (to decrypt it), the cookie is there, but the domain is null?
I also tried creating another cookie with the same name and setting the expiry to yesterday. No dice.
What's going on? Can anyone help?
I believe if you set the domain attribute on the forms element in you web.config, to the same as the one in your custom cookie, it should work. (EDIT: that approach won't work because the SignOut method on FormsAuthentication sets other flags on the cookie that you are not, like HttpOnly) The SignOut method basically just sets the cookie's expiration date to 1999, and it needs the domain to set the right cookie.
If you can't hardcode the domain, you can roll your own sign out method:
private static void SignOut()
{
var myCookie = new HttpCookie(FormsAuthentication.FormsCookieName);
myCookie.Domain = "mysite.com";
myCookie.Expires = DateTime.Now.AddDays(-1d);
HttpContext.Current.Response.Cookies.Add(myCookie);
}
An authentication cookie is just a plain cookie; so you would remove it the same way you would any other cookie: expire it and make it invalid.
I had a similar problem. In my case, I was storing some userData in the AuthCookie and experienced the same effects as described above, and upon authentication at each request, reading the cookie and putting the userData in a static variable. It turned out in my case that the data was being persisted in the application. To get around it, I had to first clear my static variable, and then expire the cookie. I used the following in the LogOff method of my AccountController:
AuthCookie.Clear(); //STATIC CLASS holding my userdata implemented by me.
Response.Cookies[FormsAuthentication.FormsCookieName].Expires = DateTime.Now.AddYears(-1);
Response.Cookies[FormsAuthentication.FormsCookieName].Value = null;
return RedirectToAction("Index", "Home");
Hope this helps.
UPDATE
On a hunch after submitting, I replaced the middle two lines with:
FormsAuthentication.SignOut();
... and it worked fine where it didn't before.
Note:
AuthCookie.Clear();
... does not touch the AuthCookie, it just resets the static class I wrote to default values.
Again, hope this helps.
I have an app with multiple subdomains, subone.parent.com, subtwo.parent.com.
I have a logon page at parent.com/login. When a user logs in I redirect them to the proper domain based on which one they are a member of. This works fine.
FormsAuthenticationTicket ticket = new FormsAuth...
string encTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
cookie.Domain = subone.parent.com
Response.Cookies.Add(cookie)
This properly authenticates the user for subone.parent.com and not subtwo.parent.com. However I would like to do the following.
If the user goes back to parent.com, I would like to know that they are logged in and redirect them back to subone.parent.com.
Is there a best practice for accomplishing this? Or do I have to set another cookie for parent.com?
I'm working in asp.net mvc if it matters.
THanks!
You can share cookies across domains like you are trying to do, but its not straight forward, example here.
Another options is to set the cookie to be ".parent.com" rather than specifying the sub-domain explicitly and use the cookie store the details of the sub-domain. Then you can access the cookie from any of your sub-domains (and parent assuming its www.parent.com).
If your using MVC, you can pretty easily create a custom filter and add to the www.parent.com controllers to check for the existence of the cookie, and if so redirect to the sub domain the cookie specifies. Further details of filters here.
I would set the cookie for the explicit domain as you have there because that maintains any security information within that specific domain's cookie. You can also add a non-encrypted cookie at the *.parent.com level that holds information about which domains have been authenticated. There is no real way to tie this together though without using maybe timestamps and having a logical connection between the applications (ie - sub2 has a session timeout of 20 minutes so if the domain + valid timestamp occur in the parent cookie it would be valid, however this is business logic).
I'm not sure the reasoning behind the disconnect between domains, but you might actually prefer to have a single cookie that has encrypted text behind encrypted text. EG:
1) Sub1 logs in, sets the parent.com cookie as valid. Sends a piece of user data to an authentication web service.
2) The authentication service recognizes sub1 as the sender, encrypts the user data, and adds it to a custom cookie object.
3) The custom cookie object constructs a composite string on a unique split character (or sequence) and makes it available to the service method.
4) The service, using the forms encryption, encrypts the entire ticket and sends it back to the original login.
That way each server would be able to unencrypt the global ticket, but each piece of data would be encrypted using a common algorithm but a server based salt. So if sub2 attempts to read the cookie data from sub1, it gets the encrypted version rather than raw data.
you could share the same session on all subdomains. That is the code we use to accomplish that :-)
void MasterPage_Unload(object sender, EventArgs e)
{
///ASP.NET uses one cookie per subdomain/domain,
///we need one cookie for _all_ subdomains.
if (Context.Response.Cookies["ASP.NET_SessionId"] == null)
return;
var sessionCookie = new HttpCookie("ASP.NET_SessionId", Context.Session.SessionID);
sessionCookie.Domain = ".yourdomain.com" ;
Context.Response.SetCookie(sessionCookie);
}
inside the Page_Load method is:
Unload += MasterPage_Unload;
it works great :-)
robert
I have multiple asp.net sites. When a user logs unto one of the sites, I want to store a cookie telling me that a user has logged on. When the user later visits one of the other sites I have, I would like to read the cookie from that site.
AFAIK you neither can read cookies from or write cookies to other sites, so what could a workaround be?
Perhaps making a redirect to http://www.othersite.com/SaveCookie.aspx ?
Give me some ideas :-)
One of our clients has exactly the same requirement (logging into multiple sites on different domains), complicated by the fact that one of the sites requires that the user is logged in to a classic ASP application, a .NET 1.1 application and a .NET 3.5 application running on different hardware, but under the same domain...
We've basically implemented a system of round-robin style redirects, where each domain logs the user in, then bounces them on to the next domain until they return to the original domain at which point they are redirected to their original request.
So (pages and domains changed to protect the innocent):
User requests www.example1.com/page1.aspx
A cookie is set that tells us the user was attempting to access page1.aspx, and the user is sent to the www.example1.com/login.aspx
The user logs in, and is then redirected to www.example2.com/processlogin.aspx?token=EncryptedToken
ProcessLogin.aspx checks for a cookie telling it where to direct the user, if it can't find one, it decrypts the token, logs the user in on example2.com, and then redirects them to www.example1.com/processlogin.aspx?token=EncryptedToken (or example3.com - repeat as required)
As in 4, ProcessLogin.aspx checks for the cookie, finds it, deletes it and redirects the user to /page1.aspx.
If the user later on visits a page on www.example2.com, before the authentication ticket timeout, they will still be logged in on that site as well.
Edit to respond to comment
That depends on how you are making the "request to the other pages". If you make the request from your code behind, what you're doing is effectively setting the cookie on the server, rather than on the users browser.
Cookies need to be issued by the server to the client browser, and that is done in the headers of the page response - so you need to direct the users browser to a page on the other site to issue the cookie from that domain.
You could generate a request to the other page in an IFrame, or try and do it in a self closing pop-up window - but that has other issues like pop-up blockers, flickering windows, etc.
After some investigation we found that a round-robin set of redirects like this was the simplest and most reliable solution.
A very basic code setup:
An .aspx page, containing a Login control, with a method "OnLoggedIn" attached to the LoggedIn event of the control:
void OnLoggedIn(object sender, EventArgs e){
string returnUrl = Request.QueryString["returnUrl"];
// Create new cookie, store value, and add to cookie collection
HttpCookie myCookie = new HttpCookie("WhereTo");
myCookie["ReturnUrl"] = ReturnUrl;
Response.Cookies.Add(myCookie);
// Redirect user to roundtrip login processor on next domain.
// Work out domain as required.
string redirect = GetNextDomain();
// Add encoded user token
redirect += "?token=" + EncodeUserToken();
// Redirect the user, and end further processing on this thread
Response.Redirect(redirect, true);
}
Then on both servers you have ProcessLogin.aspx, that has something like this in it:
protected void Page_Load(object sender, EventArgs e){
// Look for redirect cookie
if (Request.Cookies["WhereTo"]["ReturnUrl"] != null){
// Save value from cookie
string redirect = Request.Cookies["WhereTo"]["ReturnUrl"];
// Delete original cookie by creating an empty one, and setting it
// to expire yesterday, and add it to the response.
HttpCookie myCookie = new HttpCookie("WhereTo");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
// Redirect the user, and stop processing
Response.Redirect(redirect, true);
}
// Still here, so log in and redirect
string encryptedToken = Request.QueryString["token"];
if (!string.IsNullOrEmpty(encryptedToken)){
// Decrypt token, and log user in
// This will vary depending on your authentication mechanism
PerformLogin(encryptedToken);
}
// Redirect user to roundtrip login processor on next domain.
// Work out domain as required.
string redirect = GetNextDomain();
// Add encoded user token - no need to recalculate, it will be the same
redirect += "?token=" + encryptedToken;
// Redirect the user, and end further processing on this thread
Response.Redirect(redirect, true);
}
You're looking for a Single Sign-On (SSO) solution.
If it's possible for you to host your sites at different subdomains below the same domain, you can save cookies that are shared for the whole domain, e.g.:
"site1.yourdomain.com" and
"site2.yourdomain.com"
can both read cookies saved to the domain "yourdomain.com"
Another alternative is to tell the other site about the login via a request to it, as in your redirect suggestion. You could do this in several ways, e.g. by loading the page in an iframe, sending the data directly from one server to another, and so on. None of these are particularly elegant, though, and in the case of login, as Tomas Lycken says, you should really be going for a proper SSO implementation.