Cookies are duplicated from values which don't exist - c#

EDIT Since debugging updates
According to the .net cookie documentation:
After you add a cookie by using the HttpResponse.Cookies collection, the cookie is immediately available in the HttpRequest.Cookies collection, even if the response has not been sent to the client.
My original observation were that my cookies appeared to be out of sync. After Receiving IUserIdentity, I would set an authentication cookie like so:
HttpContext.Current.Response
.RemoveCookie(FormsAuthentication.FormsCookieName);
HttpContext.Current.Request
.RemoveCookie(FormsAuthentication.FormsCookieName);
var authCookie = FormsAuthenticationExtensions.GetPersistentAuthCookie(
FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket), ticket.Expiration)
HttpContext.Current.Response.Cookies.Set(authCookie);
First I noticed that to values for the cookies we're not the same, after inspecting the same cookie in the watch window I noticed the value for the same cookie wasn't even the same:
I walked the code, and noticed that a duplicate cookie value was being set during a statement which didn't execute code. (e.g when stepping into an unrelated function the cookie now the duplicate cookie appeared in the Request and Response Cookies)
I proceeded to update all references to the cookie name in the code to help help verify what could be causing this (VM-AT-89001) => (VM-PAT-89001):
<authentication mode="Forms">
<forms cookieless="UseUri" name="VM-PAT-89001" requireSSL="true" slidingExpiration="true" timeout="1" />
</authentication>
I cleared all existing cookies, deleted the Temporary ASP.NET Files
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files
Did an IISReset and Reset my computer. When walking the code again, still the OLD cookie name was being added to the request and response.
The configurations of the cookies are different but they have the same expiration date. e.g only 1 is HTTP Only.
NOTE I've search the entire organization code base in github and there is no reference in the code to the Old Token.
They fact that this behavior happens at different points in the code depending on which controller method I call, makes me think that this is happening on a seperate thread.
Since there is no reference to the Cookie name it makes me think IIS is modifying the cookie, but this is even more perplexing because I didn't think IIS had access to the HttpContext.Current, because I can see the cookie while still debugging and not After.
How can a cookie be added to a response, when there is no reference to the cookie name in the code, and it occurs during an No-Op statement in debugger?
EDIT
I've removed all filters and modules from the application (Except for adding default json formatters), and I navigate to a page that doesn't exist, and still the old token is added to the request
How can this occur?

Related

Form cookie vs Session cookie in C# form authentication

I'm developing a .NET MVC web application in C# which implements form authentication.
I have the below configuration in my web.config file:
<authentication mode="Forms">
<forms loginUrl="~/Home/Register" timeout="10080" name="Test" slidingExpiration="true"/>
</authentication>
<sessionState cookieName="Test" timeout="5040"/>
I have some questions:
Using the same name for session state cookie name and form cookie name is OK or it will cause problems/collisions for the parameters such as timeout?
Setting slidingExpiration="true" causes renewal of timeout automatically or it requires calling some special function on the backend?
I have read the second comment of this answer: https://stackoverflow.com/a/17813200/1080355. So I set the form auth cookie time out twice of session time out. I'm doing it in the right manner?
Setting same name for both cookies will cause issues, please avoid it, set unique names for both cookies
Cookie will be renewed automatically but of course only upon a request. As long as there are no requests from the browser, there's nothing to renew. Renewal consists in just issuing a new cookie that overwrites the old one.
Edit: Not sure why this is not clear. Maybe this will help: browser makes a request, server finds out that cookie is valid but it's about to expire. So the server issues a new cookie. Formally, it's the forms authentication module that does so, automatically,.
Forms cookie timeout and session state timeout are completely unrelated and there's no rule that would make one dependant on the other.

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.

ASP.NET Form Authentication auth cookie is always persistent

I am trying to implement remember me functionality in login for my project using Asp.Net Form Authentication. The problem is once user logs in, he remains logged in even when the browser is closed and reopen. It seems that the Auth cookie is always persistent irrespective of whether user have checked remember me option or not.I have no idea what am i suppose to do??Can anyone guide me through??
I guess normally this line of code is enough to achieve what i want to:
FormsAuthentication.SetAuthCookie(model.Username, model.RememberMe);
This could be controlled by the timeout attribute in the Web.config
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
It would be helpful if you add the authentication mode in Web.config as shown by #Matt. Anyway, if you observe the cookies issued with Remember Me toggle on & off, you'll noticed the following:-
Remember Me ✕ : Auth Cookie Expires attribute: Session
(Session cookie)
Remember Me ✓ : Auth cookie Expires attribute: { UTC Time } (Persistent cookie)
Session cookie will last as long as the browser remains active. Threfore the cookie will be disposed only after you close the browser window (not tab) as opposed to persistent cookie.
You can know more about the concept of cookies & browser behaviour at below:-
Why Doesn't Closing A Tab Delete A Session Cookie?
HTTP Cookie Wikipedia

ASP.NET Site Authentication Cookie sharing

I've got 2 MVC3 Internet websites. One (Site1) uses Windows authentication and is in the Local Intranet Zone. The second (Site2) is publicly available and uses Forms Authentication. Both sites are in the same Domain, but have a different sub-domain. I want to share authentication cookies between the two. In order to do this, they need identical settings in the web config. Sometimes this works, most of the time it doesn't. If anyone hits Site1 from outside our network, they get a 403 error, which is good. If a network user hits Site1, they're allowed in based on their network credentials. I then check their user's roles with the code below.
var userName = string.Empty;
var winId = (WindowsIdentity)HttpContext.User.Identity;
var winPrincipal = new WindowsPrincipal(winId);
if(winPrincipal.IsInRole("SiteAdmin")) {
FormsAuthentication.SetAuthCookie("siteadmin", false);
userName = "siteadmin"; //This is a Forms Auth user
}
else if(///I check for other roles here and assign like above)
Once I've checked the roles, I forward them onto Site2, creating a cookie for them if the user is in one of the roles determined in the if...statement above.
if(!string.IsNullOrEmpty(userName)) {
//Add a cookie that Site2 will use for Authentication
var cookie = FormsAuthentication.GetAuthCookie(userName, false);
cookie.Domain = FormsAuthentication.CookieDomain; //This may need to be changed to actually set the Domain to the Domain of the TVAP site.
HttpContext.Response.Cookies.Add(cookie);
}
//Network users not found in roles will simply be forwarded without a cookie and have to login
HttpContext.Response.RedirectPermanent(tvapUrl);
I've set up in the web.config a matching MachineKey (validationkey, decryptionkey and validation) for each site.
They also both have the same authentiation settings, with the exception of the mode. So my config for this looks like this.
<authentication mode="Forms">
<forms loginUrl="~/Account/LogOn" name=".ASPXFORMSAUTH" protection="All" path="/" domain="mydomain.com" enableCrossAppRedirects="true" timeout="2880" />
</authentication>
I think my problem is that the 'authentication' mode is different for each one, so Site2 won't use the authentication cookie from site1. This is just a guess though. Is there anyway I can figure out the issue?
According to this article, what I have going here should work. And there have been times where I think it's worked, but it's hard to tell, as I may have cookies cached and their getting reused. I'm hoping someone can see something I'm missing here, or has an alternative solution.
UPDATE
I checked my authentication cookie on Site2 after logging in normally and found the Domain wasn't set, so I've removed that line of code.
Also, I read about cookies expiring when the date isn't set, so I set an Expire Date on my cookie before sending with the request.
So, with those two changes, here's where I'm at.
It works on Chrome and Firefox, but not with IE. Not sure. I'm going to do some additional testing from another machine and another user so I know I haven't got any residual cookies sitting around.
I determined my problem was not setting the Expires property of my cookie. According this Microsoft article, cookies won't be written to the client unless the Expires property is set.
"If you do not set the cookie's expiration, the cookie is created but it is not stored on the user's hard disk. Instead, the cookie is maintained as part of the user's session information. When the user closes the browser, the cookie is discarded. A non-persistent cookie like this is useful for information that needs to be stored for only a short time or that for security reasons should not be written to disk on the client computer. For example, non-persistent cookies are useful if the user is working on a public computer, where you do not want to write the cookie to disk."
In this case, I needed the cookie to be written to disk since I was doing a server transfer to another site, thereby ending the session for that user. I'm not 100% sure that this was the fix, but it is working now, so I'm assuming that.

FormsAuthentication.FormsCookiePath

Q1
I’ve read that when setting the timeout of an authentication cookie, we should keep in mind that the longer the cookie persists, the greater the chance of a cookie being stolen and misused.
A) But assuming we secure our application against replay attacks by enabling SSL for the entire application, and since forms authentication module also encrypts authentication data in authentication cookie, then I would think there is no chance of this cookie being misused and thus cookies being persisted for longer periods of time should not present any security risks?!
Q2
FormsAuthentication.FormsCookiePath specifies where authentication cookie is stored. Default value is ‘/’.
A) Assuming default value ’/’ is used, where is cookie saved then?
B) Is this option only used for persistent cookies?
thanx
2A The cookie path is the path on the server the cookie relates to, not the path where the cookie is store.
From http://www.quirksmode.org/js/cookies.html
The path gives you the chance to specify a directory where the cookie is active. So if you want the cookie to be only sent to pages in the directory cgi-bin, set the path to /cgi-bin. Usually the path is set to /, which means the cookie is valid throughout the entire domain.
This script does so, so the cookies you can set on this page will be sent to any page in the www.quirksmode.org domain (though only this page has a script that searches for the cookies and does something with them).
You are using ASP.Net. Also see the "CookieLess" Session and Authenication options e.g.
http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.formscookiepath.aspx If you are worried about cookies. This uses a URL session ID instead to track your session.
You can also use a SQL Server to track session state or a State server.
e.g.
<sessionState mode="SQLServer" sqlConnectionString="SQLSessionDB" cookieless="false" timeout="65" cookieName="MSESSID"/>
1A. SSL encrypts transport. Hence your cookies will be less likely to be stolen on route to the client or back. That doesn't mean a malicious program on the client computer can't steal it. This is very unlikely though.

Categories