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.
Related
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?
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 Web Forms applications.
I checked our company's legacy code, the way they do login is like this:
when user is validated against database with (username, password), they set a session:
Session["authenticated"] = "true";
Every page other than login.aspx is inherited from a class named SecurePage. In SecurePage's OnInit() method, it checks
if (Session["authenticated"] != null)
if true, means authenticated, otherwise means not. So basically the way to do authentication is to see if there is a session named authenticated.
This seems the most crude and intuitive way of doing authentication... I want to ask: is this safe?
Another thing I feel strange is that in the web.config, they have this:
<authentication mode="Windows" />
Shouldn't it be
<authentication mode="Forms" />
since these are web applications? Users credentials are stored in database and these users are outside clients (not internal users).
A slight different version also does this after user is validated against database:
FormsAuthentication.SetAuthCookie( username, true );
what does this do? Besides this statement in login.aspx, I don't see any other pages have any code related to auth cookie. Do we need to set auth cookie by ourselves in code or does .NET framework handle this for us already?
Still another version have the following:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(login, false, 60);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
Response.Cookies.Add(cookie);
what does this do? Do we need to set this cookie by ourselves in code? or does .NET framework handle this for us already?
These web appliations were developed a long time ago, though I am not sure when. I suspect it is .NET 1.0 era? From my understanding since .NET 2.0,
it has this ASP.NET membership thing, and we can just use <authentication> and <authorization> tags in web.config (and subfolder web.config) to achieve the goal of authentication and authorization. Isn't it? Can anyone give me a history of ASP.NET framework authentiation mechanism? (membership -> simple memebership -> Identity?)
<authentication mode="Windows" />
Above should be used mostly in intranet website, because it's like saying use the computer(windows pc) authentication to access the resource. However, this will never work, since inherited class has a method to validate session key value for a login.
You should make sure that the code redirects user to login page in case the session key is not found. That means, in the else section of below code, you should take users to login page to try again. Which I am sure is happening.
if (Session["authenticated"] != null)
{ /*user is authenticated*/ }else{ /*redirect to login*/ }
Its is recommended to use <authentication mode="Forms" /> if the website is accessible over the internet. Other benefit of using this setting is that you can set default and login page.
Finally, FormsAuthenticationTicket is a class with property and values that are used when working with Forms authentication to identify authenticated users.
Read through msdn article to know more about asp.net membership.
https://msdn.microsoft.com/en-us/library/yh26yfzy%28v=vs.140%29.aspx
We are using the Simple Membership Provider with ASP.NET MVC 4, and we're using the Facebook Client to provide Facebook login support (similar to http://www.asp.net/mvc/overview/getting-started/using-oauth-providers-with-mvc).
We have gotten this working, but the session always times out within a day, and we want the login to be persistent, so the user can login and use the service just once.
In the out-of-the-box ExternalLoginCallback function, I am attempting to set the createPersistentCookie parameter to true, but it won't keep the login alive. Here is the call I am making:
OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: true)
Am I going to have to set the Forms Authentication cookie manually in order to accomplish a persistent login? Or is there another way of doing this while still taking advantage of the out-of-the-box Facebook login functionality?
The ASPXAUTH cookie is used to determine if a user is authenticated. You can track expiration time with firebug or any other web debug tool. In your project the cookie is set in ExternalLoginCallback. Here is example screen setting cookies' expiration timeout.
All what I had to do to make it work was to use SSL, and change cookie timeout in web.config. Here is example with timeout set to 1 minute. Don't forget to mark requireSSL on true.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="1" requireSSL="true"/>
</authentication>
But in your case i believe the problem is with short live access token from facebook(default around 2h). In case if the problem is with access token here is link how to extend lifetime of access token.
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.