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

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).

Related

AuthenticationManager.GetExternalLoginInfoAsync always null

I have ASP.NET MVC 5 web app with different third-party auth providers (Facebook, Vkontakte aka VK, Odnoklassniki aka OK). I use Microsoft.Owin.Security.Facebook for Facebook authentication, and KatanaContrib.Security.VK and KatanaContrib.Security.Odnoklassniki for others (i've a bit customized VK and OK to meet my purposes)
3 days ago everything was fine, but since that some of my customers complaining that they can't login using third-party providers. I also able replicate the problem with some interesting points
it's not persisntent in Google Chrome (Version 71.0.3578.80) for me
it's persistent in Opera (Version:57.0.3098.91)
I can login when my web app running locally or on dev.site.ru (both Chrome and Opera)
I've added more logs in the auth workflow and found
AuthenticationManager.GetExternalLoginInfoAsync() always returns
null in Opera
.AspNet.Correlation.* cookies removed in the end of login process in Chrome, but not in Opera
I have all Microsoft.Owin and Microsoft.Owin.Security.* version 4.0.0. I also upgraded API used by providers to latest. But it doesn't help me. I also add logs to VK auth handler, and found that AuthenticationTicket is not null, and contains relevant information in Identity
Any ideas what can be wrong? Maybe you can give me some direction for further investigation?
After have all Microsoft.Owin.Security.* updated I found that login failed (GetExternalLoginInfoAsync returns null) in case ASP.Net_SessionId cookie haven't created yet, but can login if it exists. So putting code Session["logging"]=true on Login page loading solves the problem.
It's also mentioned here

OpenIdConnectProtocolValidationContext.Nonce was null

HI can someone please help imgetting below error when calling outlook rest api
IDX21323: RequireNonce is '[PII is hidden by default. Set the 'ShowPII' flag in IdentityModelEventSource.cs to true to reveal it.]'. OpenIdConnectProtocolValidationContext.Nonce was null, OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce was not null. The nonce cannot be validated. If you don't need to check the nonce, set OpenIdConnectProtocolValidator.RequireNonce to 'false'. Note if a 'nonce' is found it will be evaluated.
aka IDX21323 points towards losing the nonce cookie (set by the initial Challenge call). Inspect your initial SignIn call (or WebForms postback SignIn) and confirm that you have a OpenIdConnect.nonce cookie actually set (Chrome network tab).
If not, I suspect that you have the same issue we had, which is that the OWIN Middleware sets the cookie, but its content gets accidentally overwritten by some other cookie modifications of your legacy application.
This is very likely a bug of the OWIN middleware (see ASP.NET_SessionId + OWIN Cookies do not send to browser), as it handles cookies through its own OwinContext and Cookie representation implementation, which is not in sync with the standard HttpContext.
How to fix when you have the initial nonce cookie missing:
We avoided any cookie changes during the SignIn request -> therefore the OWIN middleware can read/write its cookies with no interference.
When setting the nonce cookie running on localhost (non-secure) in a Chromium based browser, it's blocked because of SameSite=none and it not being secure. The fix for this case is to change localhost to use SSL (use https on asp.net application running on localhost) and update the Azure AD redirect URL to match.
In a WebForms app I got the same error when I used my machine name in the project url, but used "localhost" as my login redirect url. When I set them both to localhost the problem went away.
If your tenant was created on or after October 22nd, 2019, it’s possible you are experiencing the new secure-by-default behavior and already have security defaults enabled in your tenant.
How to Fix :- goto your Azure AD account => properties => on tab Access management for Azure resources => enable this tab to Yes.

Request.Cookie does not work after deploy on IIS

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);

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 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