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
Related
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.
This is the code I use to store a cookie after user is authenticated.
var authTicket = new FormsAuthenticationTicket(
1,
Session["UserID"].ToString(), //user id
DateTime.Now,
DateTime.Now.AddDays(1), // expiry
true, //true to remember
"", //roles
"/"
);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(authTicket));
if (authTicket.IsPersistent) { cookie.Expires = authTicket.Expiration; }
Response.Cookies.Add(cookie);
What should I do next to retrieve this cookie when the user visits the site again ?
To get the cookie:
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
To get the ticket inside the cookie:
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
Typical way of doing it-- implement AuthenticateRequest in global.asax.cs...something like this....
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
// Get the forms authentication ticket.
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new MyPrincipal(identity);
// Get the custom user data encrypted in the ticket.
string userData = ((FormsIdentity)(Context.User.Identity)).Ticket.UserData;
// Deserialize the json data and set it on the custom principal.
var serializer = new JavaScriptSerializer();
principal.User = (User)serializer.Deserialize(userData, typeof(User));
// Set the context user.
Context.User = principal;
}
}
...then, whenever any of your code needs to access the current user, just get the context user:
var user = HttpContext.Current.User;
Link
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
On my login page the FormsAuthenticationTicket is set as a persistent cookie with some custom userdata. Now I need to change this custom user data, so it contains one more parameter. When a previously logged in user visit the site the next time, I deserialize this custom userdata in Application_PostAuthenticateRequest but now I won't contain the newly added paramter.
Can I retrieve this paramter, without the user is required to login once again?
And if not, how to tell to the persistent cookie that it needs to be 'updated'?
Cookie set. userId is a new parameter:
CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
serializeModel.FirstName = model.UserName;
serializeModel.userId = model.userId;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string userData = serializer.Serialize(serializeModel);
FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
1,
model.UserName,
DateTime.Now,
DateTime.Now.AddYears(5),
model.RememberMe,
userData);
string encTicket = FormsAuthentication.Encrypt(authTicket);
HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
faCookie.Expires = authTicket.Expiration;
Response.Cookies.Add(faCookie);
return RedirectToAction("Index", "Home");
Cookie retrieval. Userid is the new paramter, and is null for previous logged in users:
HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
JavaScriptSerializer serializer = new JavaScriptSerializer();
CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);
CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
newUser.FirstName = serializeModel.FirstName;
newUser.userId = serializeModel.userId;
HttpContext.Current.User = newUser;
}
Are you using web forms or MVC?
It looks like your setting your HttpContext.Current.User correctly. The problem may be that your by default that your controllers / views still thinks its IPrincipal and not your Custom Principal, So you can't access the new data you set.
You can cast it, or set it in a base controller like below.
// in some controller action
var firstName = ((CustomPrincipal)User).FirstName
[Authorize]
public class BaseController : Controller
{
protected virtual new CustomPrincipal User
{
get { return HttpContext.User as CustomPrincipal; }
}
}
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