Request.Cookie does not work after deploy on IIS - c#

This code below runs on the development environment, but when deployed on Windows Server 2012 R2 the DsCookie cookie could not get the values created from the cookie creation.
It uses MVC 4 with Entity Framework v4 and jQuery.
HttpCookie ds_id = new HttpCookie("ds");
ds_id.Value = reqCookie.ToString();
ds_id.Expires = DateTime.Now.AddHours(1);
Response.SetCookie(ds_id);
Response.Flush();
private HttpCookie DsCookie
{
get
{
return Request.Cookies["ds"];
}
}
Does anyone know why my solution only works in a development environment and not live?

May be there is a difference between the server time and your local time.
The code
DateTime.Now.AddHours(1);
takes the server time.
And if the server time is 1 hour earlier than your local pc time, the cooke will be created and deleted immediately.
Check the server time, if this is the case, change the expiration time like
ds_id.Expires = DateTime.Now.AddHours(10); //Or more.
Or you can precise time difference and :
ds_id.Expires = DateTime.Now.AddHours(1 + time difference between the server and your local time);

You haven't provided a great variety of information so here's my guesses based on what I can think of.
Check your IIS settings
Under your IIS settings, head to your website deployment then under the features panel, navigate to IIS > Authentication > Check you have the correct authentication methods in place. You could also verify that you are allowing all users to authenticate via cookie authentication
Web.config must allow IIS to send cookies to you
If your web.config file is not set up correctly, it may be preventing your deployment from sending cookies. Read through and check that it allows IIS to send them out.
Try adding a single day like so
If you don't receive a cookie, it could be that the cookie is instantly deleted? It's rare, but it happens. Try doing this instead:
ds_id.Expires = DateTime.Now.AddDays(1d);
This should make the cookie persist
Check the server's datetime is correct
If it isn't this could very well be the root of the issue. It sounds silly, but it has been a legitimate problem in the past for some.
Make sure your browser accepts the cookie
If you have any options in your browser to reject cookies, this will prevent you from accepting the login and therefore it will be almost as if you can't log in.
If you still have problems after these fixes, please let us know and provide a bit more detail and we might be able to help narrow down the issue for you.
As an additional note, this is a much better (and cleaner) way of doing this:
var dsCookie = new HttpCookie("dsCookie")
{
Value = reqCookie.ToString(),
Expires = DateTime.Now.AddHours(1)
};
Response.Cookies.Add(dsCookie);

Related

ASP.NET cookies doesn't appear to be set when on IIS

I have an rather simple ASP.NET application that sets a cookie (actually 2) after a user has logged in.
This all works fine in any browser (I tested with IE, Chrome and Firefox) when I'm on my local machine running the app from VS2015 (aka IIS Express).
I can read the cookie as expected and I can also check the browser cookie collection and see that my cookie is there.
However, when I publish my project and bring it to a remote IIS (8.5 I believe, Windows Server 2012 R2) it doesn't work anymore.
I would provide some further information if only I knew what to provide - I have no idea what would be of interest in this regard for anyone trying to help me out - so I'm aware that I probably need to provide some extra information, I just don't know what :)
Please let me know how I can help you help me (and whoever might have the same issue).
UPDATE:
I didn't add the cookie code because it appears to be working (at least on my local IIS Express), but maybe I should be setting more of the cookie attributes for it to work on the remote IIS as well?
Setting the cookie
HttpCookie cookie_cusr = new HttpCookie("app_portal_cusr", JsonConvert.SerializeObject(cusr));
cookie_cusr.Expires = DateTime.Now.AddYears(30);
context.Response.Cookies.Add(cookie_cusr);
Reading the cookie (ClientUser is a custom class)
ClientUser cu = JsonConvert.DeserializeObject<ClientUser>(Request.Cookies["app_portal_cusr"].Value);
The application doesn't throw any exceptions - the cookie is just not set as in, it doesn't exist when i check the browser cookie collection and also when my code tries to read it (I check for NULL or it would actually throw an exception I assume).

ASP.NET 4.5 persistent cookies not working correctly

We have a web forms project for a client that kept "timing out" and would log the user out periodically while filling out information in the admin area. We ran into something similar on a previous project but were able to work around that easily with this:
if (RememberMe.Checked)
{
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket((string)r["Login"], true, (90*24*60));
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
cookie.Expires = authTicket.Expiration;
HttpContext.Current.Response.Cookies.Set(cookie);
Response.Redirect(FormsAuthentication.GetRedirectUrl((string)r["Login"], false), true);
}
else
{
FormsAuthentication.SetAuthCookie((string)r["Login"], false);
FormsAuthentication.RedirectFromLoginPage((string)r["Login"], false);
}
When I tried this same approach on the new project, it had no effect. The only difference I could figure out (after many rewrites and adjustments) was that the new project was using .NET 4.5 and the one where it worked was .NET 4.0. Is this a bug in 4.5 and has anyone else come across this?
We downgraded the new project to 4.0 just to see and so far it appears to be working perfectly without any additional code changes. Most of my searching results in answers that give a code example that looks almost exactly like I'm already doing.
In case someone else runs into the same issue, we found the solution here: http://blog.falafel.com/asp-net-forms-authentication-times-out-on-a-shared-host/
Because that application didn’t have it’s own machineKey, it was inheriting the one from the server’s machine.config. This one was configured to auto-generate since it was for a server shared by multiple customers, and it would be a major security flaw if they all shared the same key. Because the key was auto-generating, though, it was also getting regenerated every time the application reset, and failing to decrypt previously handed-out Forms Authentication cookies.
I needed to set a machineKey for my application, so I created a key and put it in a machineKey tag in my application’s web.config, and voila, it worked!
The reason it works on the older site is probably the fact that it has fairly constant traffic and probably isn't idle long enough for the machine key to regenerate. But once we set up a machine key on the new site it worked perfectly: https://blogs.msdn.microsoft.com/amb/2012/07/31/easiest-way-to-generate-machinekey/

Intermittent cookie issues - Chrome / C# ASP.NET MVC / Umbraco

I'm having some really weird cookie issues on a website. It's an ASP.NET website, uses Umbraco 6.1.6 as its CMS but is mainly custom code and uses Forms Authentication for user login. It runs on IIS Server 2012 R2.
On successful registration, the user credentials are passed to the login method, which sets a cookie like this:
var authTicket = new FormsAuthenticationTicket(realUsername, false, 60);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath,
Domain = FormsAuthentication.CookieDomain,
Expires = authTicket.Expiration
};
HttpContext.Current.Response.Cookies.Set(cookie);
It then does a redirect, trying to go to wherever the user was previously on the site before registering.
return Redirect(redirectUrl);
From the redirected page, it checks the request cookie to see whether the user was logged in:
HttpCookie authCookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
Sometimes the authCookie contains the session data, and works for long periods of time..... and other times it is null - for equally long periods of time - so it only intermittently works.
This led me to believe that perhaps IIS is having trouble checking the request cookie on redirect - because the cookie has not yet reached the user's browser. But various docs and other SO posts tell me this should work when I am using a ResponseRedirect type redirect.
The bit where it gets weird is that when I've just registered but the server thinks I'm not logged in, I can look at the cookies for this "not logged in" page in Chrome dev tools, and it's true - there's no cookie set - however, when you click on the site's "Login" button from the "not logged in" page... which forces it to check whether the user is logged in again, this time "authCookie" contains cookie data. Right after Chrome told me this data was not present when I submitted the page! The cookie then reappears in dev tools when the "logged in" page is returned.
At this point, I don't know whether it's that I can't trust Chrome dev tools, or it's that there's some odd browser caching / IIS caching going on, or what. I tried looking up cookie / redirection issues and they only seem to come up with newer versions of IE.
I've tried closing the browser, closing visual studio, and that doesn't seem to have a direct impact.
One last bit of information - I read in one post here that there are sometimes issues when the registration / login is performed on one thread but the code after registration is performed on another thread. I checked the thread debugger and found that indeed the registration / login were being performed on different threads... but this was observed when it was working.
The most frustrating part is when it suddenly starts working for a few hours - and there's seemingly nothing I can do to break it again to try out different things. (Which is where I am now! I wanted to at least try it in different browsers...)

How can you keep a session across multiple subdomains in c# mvc?

A shopping cart application I'm working on jumps domain when it goes from the normal page into the submit-your-details page.
Long story short there are two copies of the application deployed: one server for the 'main' site and one server with an ev certificate running on https for the customer details (including payment; this is a PCI compliance issue).
My question is this:
When jumping from http://shop.domain -> https://secure.domain (and back, if the user browses back), how can I preserve the session?
Its trivial to pass cookies cross domain using JSONP, but I have no idea what to do with them on the remote side to 'reconnect' to the session.
I have read various things about rolling your own custom session provider, etc. etc. but I haven't found one that is more than just generic advice; certainly no examples of how this might be used to rejoin a session.
This is a for an MVC3 c# web app.
Problem with Session's is that they are kept in the same domain.
If you have the 2 applications in sub domains you can always append this to your web.config
<httpCookies domain=".domain.com"/>
and that will do the trick, but if the domains are completely different, the best way is always to roll out your own session provider or use an existing one, like SQL.
You can use for this any Caching System where instead of append variables into a session variable, you append them into the cache as key/value pair, you can always use a NoSQL alternative (plenty of free accounts out there so you can prototyping and make a proof of concept in order to roll out the final bits).
Memcached server is always a good alternative and Couchbase as the community version available for free.
The trick here is to do this:
Cache.AddObject(key + "UserInfo-name", "Bruno Alexandre");
where key could be a query string value appended in global.asax upon session_start
instead of this
Session["UserInfo-name"] = "Bruno Alexandre";
When you create cookie then you must write
Response.AppendCookie("Your cookie name");
To get that the code is something like
if (Request.Cookies["Your cookie name"] != null)
{
string value = Request.Cookies["Your cookie name"].Value;
}
and if there are different solutions then find
machineKey
which need to be same. you get it under
system.web in web.config file
and then write after machineKey
<httpCookies domain=".yourdomainname.com" />
I am creating user session using HttpContext from a function.
HttpContext cu;
string username = cu.User.Identity.Name;
username = Guid.NewGuid().ToString();
cu.Session["username"] = username;
HttpCookie hc = new HttpCookie("username", username);
hc.Domain = ".yourdomain.com";
hc.Expires = DateTime.Now.AddDays(1d);
cu.Response.Cookies.Add(hc);
With this code, I am able to share session within 3 sub-domains.

How can I convince Internet Explorer to allow authentication as another user?

Thanks for reading and for your thoughts; this is a hairy problem, so I thought I'd share to see if it is actually a fair challenge for more seasoned developers than ourselves.
We're developing a web application for a corporate Microsoft Active Directory environment, and we use Windows Authentication provided by IIS to authenticate users for single-sign-on, alongside Forms Authentication. I know IIS complains when both are enabled, but it works very well, and every site we've deployed at has had no weird quirks to work around - until now.
The new site has "shared" machines, logged in permanently with a generic account that has read-only access to the applications they need to use. This means that we can't differentiate between users who should have different permissions to the application; we need some way of prompting the user for authentication details.
First try was some serious googling; nobody else in the world seemed to have our problem except for a few misguided souls who had asked questions into the ether and received no response.
After a bit of brainstorming and nutting out the way IIS's authentication works, it seemed that the most straightforward way to approach the problem was to issue a 401 Unauthorized in response to a user known to be a shared account. Initial tests here seemed fruitful, yielding successful changes of username inside the browser, however a prototype at the site did not prompt for credentials, and the browser kept the same account details. We also hit on the IE-specific javascript
document.execCommand("ClearAuthenticationCache")
which, again, worked in the lab but not onsite. Further experiments with IE security settings onsite revealed that the browser would automatically reauthenticate if the webapp site was excluded from the Intranet Zone, regardless of the method used to trick the browser into prompting the user for new account details.
Now we're stuck. We've got workaround options for getting it going on time, but they're definitely not the "right" answers:
require users to log out of the shared account before logging into our app (...yuck)
exclude our webapp from Intranet Zone on all machines
provide a non-SSO login service for users
I'm convinced that there's a canonical way to do this - a known pattern, a common base problem that's already been solved, something like that - and I'm very interested to hear what sort of inventive methods there are to solve this sort of problem, and if anyone else has actually ever experienced anything remotely like it.
We ended up settling on a solution that submits a query to the LDAP directory the server knows about. It means having to accept the user's password, but no other solution was solid enough to run in a production environment.
Hopefully this helps someone. .NET Framework 3.5+ required.
using System.DirectoryServices.AccountManagement;
private static bool IsLdapAuthenticated(string username, string password)
{
PrincipalContext context;
UserPrincipal principal;
try
{
context = new PrincipalContext(ContextType.Domain);
principal = Principal.FindByIdentity(context, IdentityType.SamAccountName, username) as UserPrincipal;
}
catch (Exception ex)
{
// handle server failure / user not found / etc
}
return context.ValidateCredentials(principal.UserPrincipalName, password);
}
Could you not create a page to which the shared accounts are denied access. Then do a redirect to that page, with a return URL encoded in the query string, at any point where you need the user to reauthenticate with a non-shared account? This should trigger the browser to put up the usual login dialog.
After the user reauthenticates, the new page should just redirect back to the return URL in the query string.

Categories