I'm using cookies to pass user information for authentication as seen in this question. Everything was working fine, until our team upgraded our computers and are now on windows 10. Now my cookie is not found in global.asax.cs's Application_PostAuthenticateRequest.
Here's my code trying to send the cookie:
private void AddUserDataToCookies(User user)
{
var serializeModel = new WebUserSerializeModel
{
FirstName = user.Person.FirstName,
MiddleName = user.Person.MiddleName,
LastName = user.Person.LastName,
CredentialNumber = user.CredentialNumber,
Roles = user.Roles.Select(role => role.Name).ToList(),
Permissions = user.Permissions.Select(perm => perm.PrimaryKey).ToList()
};
var userData = new JavaScriptSerializer().Serialize(serializeModel);
var authTicket = new FormsAuthenticationTicket(1, user.CredentialNumber, DateTime.Now, DateTime.Now.AddMinutes(15), false, userData);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
Secure = true,
HttpOnly = true
};
Response.Cookies.Add(cookie);
var requestCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
}
The cookie shows up in request cookie. But when I try in my global.asax, it doesn't. My global asax code is below.
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
try
{
var authTicket = FormsAuthentication.Decrypt(cookie.Value);
if (authTicket != null)
{
var serializer = new JavaScriptSerializer();
var serializeModel = serializer.Deserialize<WebUserSerializeModel>(authTicket.UserData);
var user = new WebUser(serializeModel.FirstName, serializeModel.LastName)
{
MiddleName = serializeModel.MiddleName,
CredentialNumber = serializeModel.CredentialNumber,
Roles = serializeModel.Roles,
Permissions = serializeModel.Permissions
};
HttpContext.Current.User = user;
}
}
catch (CryptographicException ex)
{
Logger.Error("Error while decrypting cookie post authentication.", ex);
FormsAuthentication.SignOut();
HttpContext.Current.User = null;
}
}
}
Does anyone have any ideas why changing to Windows 10 may have causes this issue? I'm somewhat new to ASP.NET and web development in general.
EDIT - by removing Secure = true when creating my cookie I was able to get it to work. I'm investigating why this is the case before I add an answer and I welcome any insights.
As mentioned in my edit, the problem was that Secure was set to true when creating my cookie but I did not have SSL enabled when running locally, unlike, I guess, on my old workstation. The code in my controller currently looks like:
private void AddUserDataToCookies(User user)
{
var serializeModel = new WebUserSerializeModel
{
FirstName = user.FirstName,
MiddleName = user.MiddleName,
LastName = user.LastName,
CredentialNumber = user.CredentialNumber,
Roles = user.Roles,
Permissions = user.Permissions
};
var userData = new JavaScriptSerializer().Serialize(serializeModel);
var authTicket = new FormsAuthenticationTicket(1, user.CredentialNumber, DateTime.Now, DateTime.Now.AddMinutes(FormsAuthentication.Timeout.Minutes), false, userData, FormsAuthentication.FormsCookiePath);
var encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
HttpOnly = true,
Secure = true
};
if (Request.IsLocal)
{
cookie.Secure = false;
}
Response.Cookies.Add(cookie);
}
Leaving Request.IsLocal is a bit ugly but it's good enough for now until we decide if we want to implement SSL for everyone locally.
At least it was an easy fix.
Related
I have created a Website in ASP.Net MVC5 and used a login function in it, it works fine on localhost but when I uploaded the site server,
Server redirects me to the login page on each click.
Below is login Function
public ActionResult DoLogin(string username, string password)
{
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
{
var user = new UserRepository().GetAll()
.Where(u => u.UserName.ToUpper() == username.Trim().ToUpper()
&& u.Password == password).SingleOrDefault();
if (user != null)
{
FormsAuthentication.SetAuthCookie(user.UserName,true);
var authTicket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, user.Roles);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(authCookie);
Session["Name"] = user.Name;
return RedirectToAction("Index", "Student");
}
}
ViewBag.ErrorMessage = "User Name or Password is incorrect";
return View("Login");
}
then I added the below function in Global.asax.cs File.
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null && !authTicket.Expired)
{
var roles = authTicket.UserData.Split(',');
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
}
}
}
After that I have added [Authorize(Roles = "Admin")] before each Controller (Not before methods in Controller) I want to Restrict access to.
Now, whenever I login, It redirects me to Index Method of Student controller, after that I click on some other link it again takes me to the Login page. Sometimes it takes me to clicked link without taking me to Login Page. Whats the Problem with my code? it works fine on localhost.
You are assigning the auth ticket twice;
if (user != null)
{
//FormsAuthentication.SetAuthCookie(user.UserName,true); Remove it
var authTicket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddHours(24), true, user.Roles);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(authCookie);
Session["Name"] = user.Name;
return RedirectToAction("Index", "Student");
}
Also, I suggest you to don't store the roles in cookie because if the user role has been removed or added new one, you can't update them. So,
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null && !authTicket.Expired)
{
var roles = authTicket.UserData.Split(',');//fill it from database and it could be better to use cache mechanism for performance concern
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
}
}
}
I am trying to add an option to my web page, so that when a user logs in to have a 'remember me' option. To implement this I am trying to store the user data (name+password) in a cookie, but it's not working at the moment.
My code to store the cookie is:
int timeout = 525600;
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(model.UserName, true, timeout);
string encrypted = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encrypted);
cookie.Expires = System.DateTime.Now.AddMinutes(timeout);
System.Web.HttpContext.Current.Response.Cookies.Add(cookie);
FormsAuthentication.SetAuthCookie(model.UserName, true);
Request.Cookies.Add(cookie);
and on my logIn controller my code looks like:
HttpCookie cookie = System.Web.HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
if (cookie != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
var userName = ticket.UserData;
}
The problem is that the userData cookie is always empty. What am I missing?
Try this.
Creating/Writing Cookies
Way 1
`HttpCookie StudentCookies = new HttpCookie("StudentCookies");
StudentCookies.Value = TextBox1.Text;
StudentCookies.Expires = DateTime.Now.AddHours(1);
Response.Cookies.Add(StudentCookies);`
Way 2
Response.Cookies["StudentCookies"].Value = TextBox1.Text;
Response.Cookies["StudentCookies"].Expires = DateTime.Now.AddDays(1);
Way 3
Response.Cookies["StudentCookies"]["RollNumber"] = TextBox1.Text;
Response.Cookies["StudentCookies"]["FirstName"] = "Abhimanyu";
Response.Cookies["StudentCookies"]["MiddleName"] = "Kumar";
Response.Cookies["StudentCookies"]["LastName"] = "Vatsa";
Response.Cookies["StudentCookies"]["TotalMarks"] = "499";
Response.Cookies["StudentCookies"].Expires = DateTime.Now.AddDays(1);
Reading/Getting Cookies
string roll = Request.Cookies["StudentCookies"].Value;
Deleting Cookies
if (Request.Cookies["StudentCookies"] != null)
{
Response.Cookies["StudentCookies"].Expires = DateTime.Now.AddDays(-1);
Response.Redirect("Result.aspx"); //to refresh the page
}
reference here
I am having my controller action that calls a private method that handles a cookie. The problem is that the cookie is not being created at all. I read multiple posts on SO but I haven't found an answer as I think that my handling cookies in this code is correct.
Is there any web.config setting that I need to check in regards to cookies? I also tried different browsers.
I debugged the code and I can see that the cookie is actually set in the code but as soon as I load the page and have a look at cookies the cookie is not there.
private ABHomeModel HandleWhiteBoxCookie(ABHomeModel model)
{
var whiteBox = _whiteBoxService.GetActiveWhiteBox();
if (model.WhiteBox != null)
{
const string cookieName = "whiteBox";
var whiteBoxCookie = HttpContext.Request.Cookies.Get(cookieName);
if (whiteBoxCookie != null)
{
var displayedTimes = Convert.ToInt32(whiteBoxCookie.Value);
if (displayedTimes < 2)
{
displayedTimes++;
var cookie = new HttpCookie(cookieName, displayedTimes.ToString())
{
Expires = new DateTime().AddMonths(1),
Secure = false
};
HttpContext.Response.Cookies.Set(cookie);
ViewBag.IsWhiteBoxActive = true;
}
else
{
ViewBag.IsWhiteBoxActive = false;
}
}
else
{
var cookie = new HttpCookie(cookieName, "1")
{
HttpOnly = true,
Domain = Request.Url.Host,
Expires = DateTime.Now.AddMonths(1),
Secure = false
};
HttpContext.Response.Cookies.Add(cookie);
ViewBag.IsWhiteBoxActive = true;
}
model.WhiteBox = whiteBox;
}
return model;
}
My colleague found the issue. It is in regard to setting the domain. As soon as we removed this line:
Domain = Request.Url.Host,
The cookies started working and are now being created.
The full updated code of the method:
private ABHomeModel HandleWhiteBoxCookie(ABHomeModel model)
{
var whiteBox = _whiteBoxService.GetActiveWhiteBox();
if (whiteBox != null)
{
const string cookieName = "whiteBox";
var whiteBoxCookie = HttpContext.Request.Cookies.Get(cookieName);
if (whiteBoxCookie != null)
{
var displayedTimes = Convert.ToInt32(whiteBoxCookie.Value);
if (displayedTimes < 2)
{
displayedTimes++;
var cookie = new HttpCookie(cookieName, displayedTimes.ToString())
{
HttpOnly = true,
Secure = false
};
HttpContext.Response.Cookies.Set(cookie);
ViewBag.IsWhiteBoxActive = true;
}
else
{
ViewBag.IsWhiteBoxActive = false;
}
}
else
{
var cookie = new HttpCookie(cookieName, "1")
{
HttpOnly = true,
Expires = DateTime.Now.AddMonths(1),
Secure = false
};
HttpContext.Response.Cookies.Add(cookie);
ViewBag.IsWhiteBoxActive = true;
}
model.WhiteBox = whiteBox;
}
return model;
}
I am creating a cookie and storing the value of username after succesfull login. How can I access the cookie when the website is opened. If the cookie exist I want to fill the username text box from the cookie value. And how to decrypt the value to get the username. I am doing server side validation by getting the userdetails from the database. I am using vs 2010 with c#
FormsAuthenticationTicket tkt;
string cookiestr;
HttpCookie ck;
tkt = new FormsAuthenticationTicket(1, txtUserName.Value, DateTime.Now,
DateTime.Now.AddYears(1), chk_Rememberme.Checked, "User Email");
cookiestr = FormsAuthentication.Encrypt(tkt);
ck = new HttpCookie(FormsAuthentication.FormsCookieName, cookiestr);
if (chk_Rememberme.Checked)
{
ck.Expires = tkt.Expiration;
ck.Path = FormsAuthentication.FormsCookiePath;
Response.Cookies.Add(ck);
}
cookie is created with name as .YAFNET_Authentication and content is encrypted
Webconfig:
<forms name=".YAFNET_Authentication" loginUrl="Home.aspx"
protection="All" timeout="15000" cookieless="UseCookies"/>
You may use Request.Cookies collection to read the cookies.
if(Request.Cookies["key"]!=null)
{
var value=Request.Cookies["key"].Value;
}
FormsAuthentication.Decrypt takes the actual value of the cookie, not the name of it. You can get the cookie value like
HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value;
and decrypt that.
add this function to your 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;
}
then you can use HttpContext.Current.User.Identity.Name to get username. hope it helps
HttpCookie cook = new HttpCookie("testcook");
cook = Request.Cookies["CookName"];
if (cook != null)
{
lbl_cookie_value.Text = cook.Value;
}
else
{
lbl_cookie_value.Text = "Empty value";
}
Reference Click here
In my application I use form authentication. My Authenticaton code is below:
public static void Authenticate(bool redirectToPage, ISecurityUser user, params string[] roles)
{
FormsAuthentication.Initialize();
GenericIdentity id = new GenericIdentity(user.UserName);
ExtendedPrincipal principal = new ExtendedPrincipal(id, user, roles);
//ExtendedPrincipal principal = new ExtendedPrincipal(id, user, new string[] { "1" });
string compressedPrincipal = ConvertPrincipalToCompressedString(principal);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddMinutes(30), true, compressedPrincipal, FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
//cookie.HttpOnly = false;
//cookie.Expires = DateTime.Now.AddMinutes(30);
HttpContext.Current.Response.Cookies.Add(cookie);
if (redirectToPage)
{
HttpContext.Current.Response.Redirect(FormsAuthentication.GetRedirectUrl(user.UserName, true));
}
}
The user object contains FirmID and DealerID properties. After I login to application, I can replace FirmID and DealerID from the app. After changing process this code is runned:
public static void RefreshIdentitiy(ISecurityUser user)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
ExtendedPrincipal principal = ConvertCompressedStringToPrincipal(ticket.UserData);
principal.BindProperties(user);
FormsAuthenticationTicket newticket = new FormsAuthenticationTicket(
ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration,
ticket.IsPersistent, ConvertPrincipalToCompressedString(principal), ticket.CookiePath);
cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(newticket));
HttpContext.Current.Response.Cookies.Add(cookie);
}
My problem is that: When I open the app from second page, cookie of second page crushes the first page's. So FirmID and DealerID of first page is also changed.
When I open app from second page, I don't want cookie to crush another. What can I do about this issue?
you should do something like this on all your pages:
if(Request.Cookies[FormsAuthentication.FormsCookieName]!=null)
{
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
cookie.HttpOnly = false;
cookie.Expires = DateTime.Now.AddMinutes(30);
HttpContext.Current.Response.Cookies.Add(cookie);
}
Edit
My aim is to make sure you are not overwrite your cookies every time you go to a new page