I am using forms authentication for a web site I am building and it works out pretty well except I cannot get the auth cookie to delete or expire. I have tried any number of methods and none of them seem to work. Here is what I create the cookie.
FormsAuthentication.SetAuthCookie(model.userName, false);
HttpCookie cookie = new HttpCookie("user");
Response.Cookies["user"].Value = model.userName;
Now the second cookie isn't an actual authcookie, that is used for some of the inner workings of the site per client request. This next part are various things I have tried to delete the cookie.
FormsAuthentication.SignOut();
Roles.DeleteCookie();
Session.Clear();
//Response.Cache.SetExpires(DateTime.Now);
//foreach (var cookie in Request.Cookies.AllKeys)
//{
// Request.Cookies.Remove(cookie);
//}
//foreach (var cookie in Response.Cookies.AllKeys)
//{
// Response.Cookies.Remove(cookie);
//}
//Session.Abandon();
//// clear authentication cookie
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Path = FormsAuthentication.FormsCookiePath;
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);
HttpCookie cookie = Request.Cookies["user"];
string userName = cookie.Value;
cookie.Expires.AddDays(-30);
//HttpCookie cookie2 = new HttpCookie("ASP.NET_SessionId", "");
//cookie2.Expires = DateTime.Now.AddYears(-1);
//Response.Cookies.Add(cookie2);
//HttpCookie cookie = Request.Cookies["user"];
//cookie.Expires = DateTime.Now.AddDays(-1d);
//HttpCookie user = Request.Cookies["user"];
//role.Expires = DateTime.Now.AddDays(-1d);
//Response.Cookies["user"].Value = null;
Session.Abandon();
I just cut and paste the entire thing in there, some of it is commented out now but at some point and time I have attempted to use each method in that code to remove the cookie. Some of these attempts were just guesses since I have been at this for a while. Last here is the auth section of my web.config
<authentication mode="Forms" >
<forms loginUrl="~/login" timeout="90" name=".ASPXFORMS" />
</authentication>
Any input as to what I am doing wrong is appreciated.
Try calling
FormsAuthentication.SignOut()
Before calling session. I generally place this in a separate method to make it easy to call from multiple places. Something like this:
internal void SignOut(HttpContext context)
{
FormsAuthentication.SignOut();
HttpSessionState session = context.Session;
if(session != null)
{
session.Abandon();
}
}
Related
I have some knowledge on .NET 4.5, but totally new to 4.5.1. As I read, they have a couple of changes so that apps work with Identity, which is nice for scale web apps.
That being said, I need to work on a web app with a basic user/password login system and I'm wondering if this template Individual User Accounts can work, or if I have to go with No Authentication? Please explain your answer.
basic user/password login system
Individual User Accounts will configure ASP.Net Identity for you. In addition, it will also create basic login, logout and other extra templates too. Click on Learn more for more information.
However, if you just need simple FormAuthentication, you want to select No Authentication.
The following is the example of simple FormAuthentication.
Sign-In method
public void SignIn(string username, bool createPersistentCookie)
{
var now = DateTime.UtcNow.ToLocalTime();
TimeSpan expirationTimeSpan = FormsAuthentication.Timeout;
var ticket = new FormsAuthenticationTicket(
1 /*version*/,
username,
now,
now.Add(expirationTimeSpan),
createPersistentCookie,
"" /*userData*/,
FormsAuthentication.FormsCookiePath);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,
encryptedTicket)
{
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL,
Path = FormsAuthentication.FormsCookiePath
};
if (ticket.IsPersistent)
{
cookie.Expires = ticket.Expiration;
}
if (FormsAuthentication.CookieDomain != null)
{
cookie.Domain = FormsAuthentication.CookieDomain;
}
Response.Cookies.Add(cookie);
}
Global.asax.cs
You need this in order to retrieve the username from cookie, and save it in IPrincipal Object.
public class Global : HttpApplication
{
private void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie decryptedCookie =
Context.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket =
FormsAuthentication.Decrypt(decryptedCookie.Value);
var identity = new GenericIdentity(ticket.Name);
var principal = new GenericPrincipal(identity, null);
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = HttpContext.Current.User;
}
}
web.config
Make sure you have authentication tag in web.config.
For example,
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" />
</authentication>
Usage
public ActionResult Index()
{
var username = User.Identity.Name;
return View();
}
I'm having this annoying problem that when i log out from asp mvc web application it's not working to
logging again.
Log out method looks like:
private static void LogOut()
{
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Response.Cookies.Clear();
Response.Redirect("~/Login.aspx");
}
is that cookies does not allow to login again?
You set the cookie expiry date to past to make the cookie invalid.
FormsAuthentication.SignOut();
Session.Abandon();
// clear authentication cookie using expiration date
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);
// clear session cookie, if needed
HttpCookie cookie2 = new HttpCookie("ASP.NET_SessionId", "");
cookie2.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie2);
FormsAuthentication.RedirectToLoginPage();
Forms Authentication Methods
FormsAuthenticationUserData userData = new FormsAuthenticationUserData(member.Id, member.Role, member.Gender);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, member.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, userData.Serialize());
string encTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
faCookie.Expires = DateTime.Now.AddHours(25);
Response.Cookies.Add(faCookie);
string redirectUrl = FormsAuthentication.GetRedirectUrl(member.UserName, false);
Response.Redirect(redirectUrl, true);
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
try
{
WebIdentity identity = new WebIdentity(authTicket.Name, authTicket.UserData);
WebPrincipal currentMember = new WebPrincipal(identity);
Context.User = currentMember;
}
catch
{
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
Response.End();
}
}
}
the user cannot login when client date time is greater than server date time (make cookie null and cannot login)
what is solution?
thanx a lot!
After reading your comment, this is expected behaviour that cannot be changed. The system is doing what it is meant to. You could set the cookie expire later or use a rolling timeout, however, I see no reason for the machine datetime to be out by so far.
This technique avoids using the browser's date/time completely.
Set the FormsAuthentication cookie to never expire, or to expire after 100 years.
Store the actual expiration based on server time in the authenticationTicket.Expiration property. See here.
After the server authenticates a request, it should check the authenticationTicket.Expiration to see if it has expired. I'm not 100% sure the system does this automatically, you may have to hook into the Application_AuthenticateRequest event and do it yourself.
If it has expired, the web server should deny the request; render an HTTP 403 status code and a set-cookie header to remove the cookie at that point.
Im using asp.net 4.0 and Form auth.
To check if a user is authenticated or not, i use User.Identity.IsAuthenticated.
Most of time it works perfect but i dont know how, sometimes it returns false even if user has auth.
My web.config:
<authentication mode="Forms">
<forms name=".xyz" loginUrl="~/" timeout="120" protection="All" path="/" slidingexpiration=true/>
</authentication>
In global.asax:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (authCookie == null)
{
return;
}
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
return;
}
if (authTicket == null)
{
return;
}
string[] roles = authTicket.UserData.Split(new char[] { '|' });
FormsIdentity id = new FormsIdentity(authTicket);
GenericPrincipal principal = new GenericPrincipal(id, roles);
Context.User = principal;
}
and in login page:
FormsAuthenticationTicket authTick = new FormsAuthenticationTicket(1, email.Text, DateTime.Now, DateTime.Now.AddDays(360), true, password.Text, FormsAuthentication.FormsCookiePath);
string encriptTicket = FormsAuthentication.Encrypt(authTick);
HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encriptTicket);
authCookie.Expires = DateTime.Now.AddDays(360);
Response.Cookies.Add(authCookie);
I also use ajax request in every 5 min. to keep session alive and this also reset auth timeout because slidingexpiration value.
I don't know what is wrong with it. sometimes same session and in same minute, it returns false for one page even if it returns true for all the other page. I never got this error but my visitors claim about that problem.
i found the problem. The problem was about difference between www.address.com and address.com.
www version pretend like a sub domain and creates new session and auth. If server redirects to www address when user came without www prefix, error happens. I will try url rewriting to solve it.
When a user logins into my site i create the following authenticate ticket:
// Create the authentication ticket
var authTicket = new FormsAuthenticationTicket(1, // Version
userName, // Username
DateTime.UtcNow, // Creation
DateTime.UtcNow.AddMinutes(10080), // Expiration
createPersistentCookie, // Persistent
user.Role.RoleName + "|~|" + user.UserID + "|~|" + user.TimeZoneID); // Additional data
// Encrypt the ticket
var encTicket = FormsAuthentication.Encrypt(authTicket);
// Store the ticket in a cookie
HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) { Expires = authTicket.Expiration });
Then in my Global.asax.cs file i have the following:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
// Get the authentication cookie
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
// If it exists then decrypt and setup the generic principal
if (authCookie != null && !string.IsNullOrEmpty(authCookie.Value))
{
var ticket = FormsAuthentication.Decrypt(authCookie.Value);
var id = new UserIdentity(ticket); // This class simply takes the value from the cookie and then sets the properties on the class for the role, user id and time zone id
var principal = new GenericPrincipal(id, new string[] { id.RoleName });
HttpContext.Current.User = principal;
}
}
protected void Session_Start(object sender, EventArgs e)
{
// If the user has been disabled then log them out
if (Request.IsAuthenticated)
{
var user = _userRepository.Single(u => u.UserName == HttpContext.Current.User.Identity.Name);
if (!user.Enabled)
FormsAuthentication.SignOut();
}
}
So far so good. The problem i have is that if an administrator changes a user's role or time zone then the next time they return to the site their ticket is not updated (if they selected remember me when logging in).
Here's my authentication settings incase it helps:
<authentication mode="Forms">
<forms timeout="10080" slidingExpiration="true" />
</authentication>
<membership userIsOnlineTimeWindow="15" />
I've been reading up on slidingExpiration but as far as i can tell it only increases the expiration time and doesn't renew the contents of the cookie. I'd really appreciate it if someone could help. Thanks
I simply changed my Session_Start to:
// If the user is disabled then log them out else update their ticket
if (Request.IsAuthenticated)
{
var user = _userRepository.Single(u => u.UserName == HttpContext.Current.User.Identity.Name);
if (!user.Enabled)
FormsAuthentication.SignOut();
else
RenewTicket(); // This calls the same code to create the cookie as used when logging in
}
My proposal would be to do another cookie for the remember.
This way session info can be in-memory cookie, while remember me cookie can be set to persist.