FormsAuthentication authCookie is null only for some users - c#

I am experiencing a strange problem with asp.net forms authentication. This problem only occurs for 3 users out of 30+ users that have successfully logged in. I am using very basic auth code that I have used many times and have never seen this problem. After the users successfully authenticates and the auth cookie is created, cookie added, and response.redirect to FormsAuthentication.GetRedirect(userid, false) is called. The Application_AuthenticateRequest method in Global.asax is hit.
// Extract the forms authentication cookie
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (null == authCookie)
{
// There is no authentication cookie.
return;
}
So immediately after a "good" cookie is saved and the redirect occurs the cookie is null. I have run the code through the debugger and the cookie is only null on these 3 users. But the cookie looks the same as the cookie for the many users that login successfully.
Any ideas? This is standard code that should just work.

Are you sure the "good" cookie is saved and exits to the response? It is possible in FormsAuthentication for a good cookie to be added to the header but the response is killed on the way out by some other system error (w3wp.exe crashing for instance) so a new response is generated without the cookie and the redirect occurs anyway.
In my own experience with a problem similar to this, I had a custom Principal class that was crashing after authentication (and cookie creation) and instead of writing an appropriate cookie, removed the cookie from the response entirely.

Related

Update session cookies after authentication

We have two factor authentication in place to login into our system.
User has to login using username/password.
In the next page, user has to answer security questions to successfully login into our application.
We are creating multiple sessions upon user successfully authenticated in step #1. This session information will be used across the application.
I have used below peace of code to handle session fixation issue:
When user browse the application login page, I am deleting the sessionid in the session-cookie using below code in the page load.
if(!IsPostBack)
{
HttpContext.Current.Session.Clear();
HttpContext.Current.Session.Abandon();
HttpContext.Current.Session.RemoveAll();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));
}
The above code will empty the sessionid in the session cookie. Now when user enter the appropriate credentials asp.net will create new session id automatically, so browser will get new session upon successful authentication. If user entered wrong credentials then using above code i am resetting the sessionid again so the new sessionid will automatically generated up on successful authentication.
This approach worked fine for single factor authentication and session fixation was no more a defect in security reports. But with multi factor authentication still it is an issue. I couldn't use above code to reset the cookie sessioid in the page where i am verifying the security answers as the application loosing all the session variables created in step #1.
As a work around in #2, after answering security questions successfully I have tried to save session values in the temporary object and reset the sessioid in the cookie and reassigning the object to session variables again, but sessionid is not regenerating at this point of time so i coudln't re save the session and application started throwing the exceptions wherever those session variables being accessed.
Below is the event triggered up on successful authentication in step #2 page
private void Sucess()
{
login = Session.logininfo
HttpContext.Current.Session.Abandon();
HttpContext.Current.Session.RemoveAll();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));
Session.logininfo = login;
Response.Redirect("New.aspx", true);
}
May i know is there any better way to update the session cookies in this case.

Differentiate between expired session and new user in asp.net core 2.0

I'm using the standard Authentication middleware in my Startup.cs file like this:
services.AddAuthentication("auth")
.AddCookie("auth", options =>
{
options.LoginPath = new PathString("/account/index");
options.AccessDeniedPath = new PathString("/account/forbidden");
options.SlidingExpiration = true;
});
I want to be able to display a "Your session has expired" message on my login page once the user is redirected there because of an expired session. And obviously not have it there when a new user is visiting the page.
By the looks of it, the Authentication middleware simply checks for a 401 passed from another middleware and changes it to a 302 to my desired location, leaving me no chance of differentiating between those two.
Can I achieve this differentiation by using the standard .net core 2.0 libraries, or should I go for a custom implementation instead?
If you want to detect whether or not the user was logged in, you could set a second unrelated Session cookie saying that the user HAD a session. Do not store any other information in the cookie. Let's call this a 'Flag' cookie.
When the user logs in, you create both a session cookie and a flag cookie. The session cookie can expire whenever you set it to, and the flag cookie should never expire. Lets say after 30 days, you are automatically logged out of your account - the session cookie should expire. Because you still have the flag cookie but not the session cookie, you can check on each page if you have the flag cookie when no session cookie is present.
If the Flag cookie exists but the actual session cookie does not, you can redirect to the login page and inform them that their login session has expired. I'd be sure to delete the cookie once you get there too so that every time they load a page they aren't redirected to login. This means the message will only show once to the user so they can still try visiting other pages on the site afterwards without being redirected should they want to browse (for example the homepage) but not want to log back in. If they attempt to access an authenticated page, they should be prompted for credentials again

Forms Authentication SSO Logout Issue due to duplicate cookie

I am using forms authentication to handle SSO across *.mydomain.com
Upon login i create a non-persistant cookie with the ticket embedded in it and set it's domain to .mydomain.com.
However the problem is that when i visit any website on the domain, i find there are two cookie with the same name but with different domains. :
1> site1.mydomain.com [1st Forms Auth Cookie] duplicate cookie
2> .mydomain.com[2nd Forms Auth cookie]
The 1st Cookie is not created by me.Also it isn't secure.
Upon logout i successfully clear my 2nd Cookie.
However, the 1st cookie remains and for a user it appears that he is still logged in to site1 . This happpens because i check for the existence of the cookie with the same name and surely the 1st cookie is wrongly assumed to be the Forms Auth Cookie. I cannot check the domain property because in the Request the information about the domain is null .
My issue is how is the second website-specific domain cookie is getting created.
If i cannot avoid this, is there a workaround?
UPDATE : The encrypted value stored by this faulty cookie is updated on each request i make on the website,while the encrypted value in my Auth Cookie remains same
According to MSFT Docs
"The Add method allows duplicate cookies in the cookie collection. Use the Set method to ensure the uniqueness of cookies in the cookie collection."
After renewing my Forms Authentication ticket i was doing :
Response.Cookies.Add(..);
Thus a new duplicate cookie was getting generated.
To fix this do :
Response.Cookies.Set(..);
If you were like me you would have expected ASP.Net to replace the old cookie with the new one.

Where does the application cookie go when created?

I'm playing around with the authentication using Owin according to a blog and when I execute the following, I'm supposed to get an (application) cookie. I'm unsure how to verify that I actually got one. So it very well might be there, somewhere in the memory or on the disk but I'm too ignorant of security issues to determine that.
List<Claim> claims = new List<Claim> { new Claim("Donkey", "Hazaa") };
ClaimsIdentity identity = new ClaimsIdentity(
claims, DefaultAuthenticationTypes.ApplicationCookie);
HttpContext.GetOwinContext().Authentication.SignIn(new AuthenticationProperties
{
AllowRefresh = false,
IsPersistent = false,
ExpiresUtc = DateTime.Now.AddMinutes(1)
});
I can't verify by being able/unable to log in, since this is just a dummy without any backbone yet. The only thing I need to do at this stage is to confirm that something gets somewhere and that it vanishes when a minute has passed. It'd be awesomely awesome if there was an actual cookie file popping up somewhere and then poofing away after a while. Is there such?
Of course it is, but the Cookie is sent to the browser once the authentication was requested and validated. The cookie has the same behavior as in previous version of cookie auth with forms authentication, so is a task for the browser to receive and manage the cookie; on each HTTP request, the browser sends its cookies, which are processed by OWIN to check authentication.
Take the code and implement a simple authorization on memory (like user: abc, pass: 123) and check how the browser receives the cookie. By the way, the only difference between cookie and token validation is that the cookie is automatically sent on every request, whilst on token auth you need to explicitly send the token information on header.
Be aware that cookie authentication is intended for browsers, as mobile applications or other applications that need to connect to your API will not have access to the cookie response, like in a desktop app.
Regards

Invalid token for impersonation - it cannot be duplicated since IIS 7

I have a site where we setup auto-login with windows authentication and if it fails, it asks for username/password to login as form.
The way it's done, we setup the authorization as Form with a specific page (Winlogin.aspx).
Winlogin.aspx is setup with authorization Windows. In the code of Winlogin.aspx.cs, it gets the this.Request.ServerVariables["LOGON_USER"] and creates a FormsAuthenticationTicket with the user's token using request.GetUserToken(), sets a cookie with an encrypted version and sends the browser to the login.aspx page for the Form authorization.
Login.aspx get the cookie, decrypt it and is suppose to set HttpContext.Current.User with a WindowsIdentity created from the user that was sent from Winlog.aspx after authorization has succeeded.
This has been working perfectly on IIS6 for more then a year now
but
we are updating our servers and moving to IIS 7 but now i get a Invalid token for impersonation - it cannot be duplicated.
This is the code that is used
// Extract the roles from the cookie, and assign to our current principal, which is attached to the HttpContext.
FormsAuthenticationTicket winAuthTicket = FormsAuthentication.Decrypt(authCookie.Value);
String token = winAuthTicket.UserData;
IntPtr userToken = new IntPtr(int.Parse(token);
-----> Line that gives error now. <-----
WindowsIdentity identity = new WindowsIdentity(userToken, "NTLM", WindowsAccountType.Normal, true);
HttpContext.Current.User = new WindowsPrincipal(identity);
I have been at it for 2 days trying to figure it out.
Anyone has an idea?
To resolve this you have to use a WindowsIdentity from a token that was not duplicated. So you have to pass HttpContext.User a WindowsPrinciple that was passed a WindowsIdentity that was generated by an original token (not duplicated). I've been trying to figure out a way to bypass this, but it looks like the only way is to store the credentials rather than the identity and Logon (see LogonUser) each time you need a WindowsIdentity.
You are unable to re-use an original token because HttpContext.User is disposed after each request (for security reasons).
I think the problem is, that you cannot reuse the same instance of WindowsPrincipal in another request, because SafeHandle instance, that probably holds some references that are assigned to WindowsPrincipal, had been disposed with the previous request and also you cannot duplicate WindowsIdentity.Token - it has to be regenerated. You have to clone the WindowsIdentity - this will get rid of reference dependencies. Then you can regenerate the web site authentication token by WindowsIdentity.Token or whatever.
I had had the same problem and I have solved it this way.
var user = new WindowsPrincipal(((WindowsIdentity)HttpContext.Current.User.Identity).Clone());
//now assign the user again to the current context's user or do some other stuff like storing the clone to session for future requests...

Categories

Resources