HttpContext.Current.User.Identity.Name is lost - asp.net

I'm using ASP.NET forms authentication in my web application.recently i found a strange behavior. everything was working fine in production environment.with .net 4.0 and IIS 7.in the login user enter username and password and logged in then suddenly HttpContext.Current.User.Identity.Name is lost.this does not happen every time only in some occasions.i have unable to reproduce the issue in my development environment.i have checked if(HttpContext.Current.User.Identity.IsAuthenticated) it's also true authentication ticket user data is not empty also.only HttpContext.Current.User.Identity.Name is empty.plz help
code in Login button
protected void LoginButton_Click(object sender, EventArgs e)
{
try
{
dtUserDetails = new DataTable();
if (UserRepositoryBL.ValidateUser(txtUserName.Text.Trim(), Password.Text.Trim(), out dtUserDetails))
{
AuthUser au = new AuthUser();
if (dtUserDetails.Rows.Count > 0)
{
DataRow DR = dtUserDetails.Rows[0];
au.UserID = Convert.ToInt32(DR["UserID"].ToString());
au.UserNo = DR["UserNo"].ToString();
au.UserName = DR["UserName"].ToString();
au.Password = DR["Password"].ToString();
}
string userData = au.ToString();
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
2, // Version number
txtUserName.Text.Trim(), // Username
DateTime.Now, // Issue date
DateTime.Now.AddMinutes(60), // Expiration date
false, // Persistent?
userData // User data
);
string eticket = FormsAuthentication.Encrypt(ticket);
if (Request.Cookies[txtUserName.Text] != null)
{
//HttpCookie myCookie = new HttpCookie(txtUserName.Text);
//myCookie.Expires = DateTime.Now.AddDays(-1d);
Request.Cookies[txtUserName.Text].Expires = DateTime.Now.AddDays(-1d);
Request.Cookies.Remove(txtUserName.Text);
}
HttpCookie cookie = new HttpCookie("SiteCookie", eticket);
// HttpCookie cookie = new HttpCookie("SiteCookie", eticket);
cookie.Expires = DateTime.Now.AddMinutes(60);
FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
// cookie.Path = FormsAuthentication.FormsCookiePath;
FormsAuthentication.RenewTicketIfOld(ticket);
Response.Cookies.Add(cookie);
BasePage.ActivityLog("User Login", txtUserName.Text.Trim(), true, Request.RawUrl);
string url = FormsAuthentication.GetRedirectUrl(txtUserName.Text, false);
Response.Redirect(url);
// FormsAuthentication.RedirectFromLoginPage(LoginUser.UserName, false);
}
else
{
FailureText.Text = "Your login attempt was not successful. Please try again.";
}
}
catch (Exception ex)
{
throw ex;
}
}
web.config
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" timeout="60" cookieless="UseCookies" defaultUrl="~/Landing.aspx" protection="All"/>
</authentication>
<authorization>
<deny users="?" />
</authorization>

Your session time is limited to 60 minutes. Does the problem only occur for people with an expired session? Might explain why you can't reproduce this on your development machine because you simply don't wait that long?

Related

Authentication changes in .NET 4.5.1

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

ASP.NET Formauthentication.Signout() not working

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

User.Identity.IsAuthenticated returns false sometimes

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.

asp.net login control - set user auth ticket expiration date

I wanna to overide expiration date of user auth ticket on login.aspx.
This code doen't work properly, because after 1 minute user is still authenticated.
private int loginExpire = 1;
protected void Login_LoggedIn(object sender, EventArgs e)
{
HttpCookie authCookie = Response.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket oldAuthTicket = FormsAuthentication.Decrypt(authCookie.Value);
var newAuthTicket = new FormsAuthenticationTicket(
oldAuthTicket.Version,
oldAuthTicket.Name,
DateTime.Now,
DateTime.Now.Add
(TimeSpan.FromMinutes(loginExpire)),
oldAuthTicket.IsPersistent,
oldAuthTicket.UserData,
FormsAuthentication.FormsCookiePath);
string encryptedTicket = FormsAuthentication.Encrypt(newAuthTicket);
authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Current.Response.Cookies.Set(authCookie);
FormsAuthentication.RedirectFromLoginPage(GetDestinationPage(lgUserLogin.UserName), false);
}
web.config
<authentication mode="Forms">
<forms loginUrl="~/Account/Login.aspx" requireSSL="false" timeout="1" slidingExpiration="true" protection="All"/>
</authentication>
Edit the forms element for authentication section in web.config: set timeout="1" and slidingExpiration="false"
Or instead of RedirectFromLoginPage method use code below:
String returnUrl;
if (Request.QueryString["ReturnURL"] == null)
{
returnUrl = "/Default.aspx"; //your default page url
}
else
{
returnUrl = Request.QueryString["ReturnURL"];
}
Response.Redirect(returnUrl);

ASP.NET Updating the FormsAuthenticationTicket

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.

Resources