Storing Check Box Selection in Cookies - c#

I have programmed a Remember Me check box to store the username and password in cookies if the box is checked. My problem is, that if they check it and then re-launch the application the username and password auto fill, but the checkbox does not stay checked.
I have not figured out a way to do this yet...
I will post my code below:
if (!IsPostBack)
{
if (Request.Cookies["UserName"] != null && Request.Cookies["Password"] != null)
{
userNameTxtBox.Text = Request.Cookies["UserName"].Value;
passwordTxtBox.Attributes["value"] = Request.Cookies["Password"].Value;
}
}
if (chkBoxRememberMe.Checked)
{
Response.Cookies["UserName"].Expires = DateTime.Now.AddDays(30);
Response.Cookies["Password"].Expires = DateTime.Now.AddDays(30);
}
else
{
Response.Cookies["UserName"].Expires = DateTime.Now.AddDays(-1);
Response.Cookies["Password"].Expires = DateTime.Now.AddDays(-1);
}
Response.Cookies["UserName"].Value = myUserName
string passwordEncrypted = Crypto.Sha256(myPassword);
Response.Cookies["Password"].Value = passwordEncrypted;
The above code works as it should. But I have a remember me check box that if it is checked I would like to save it to the cookies and leave it checked until the user unchecks it....
Any ideas?

If the checkbox should be checked by default any time the cookie is present, then I imagine you can just set its checked state here:
if (Request.Cookies["UserName"] != null && Request.Cookies["Password"] != null)
{
userNameTxtBox.Text = Request.Cookies["UserName"].Value;
passwordTxtBox.Attributes["value"] = Request.Cookies["Password"].Value;
chkBoxRememberMe.Checked = true; // <-- here
}
Note that there are probably a couple of problems you're overlooking here...
If you always check the checkbox by default when the cookie is present, you don't give the user any way to uncheck the checkbox. The user would need to manually delete the cookie from their browser, which isn't a very great user experience. (Not to mention many users won't be aware of how to do that.)
Storing a user's password in plain text is grossly irresponsible. Please stop doing that immediately. Instead, generate some kind of unique token to identify the user and store that token in the cookie. The server-side code would then validate the token against known tokens associated with known users. Never, ever store the user's password in plain text anywhere.

Not only is what you're doing terribly bad in terms of security, you're also reinventing the wheel.
ASP.Net already supports out of the box Forms authentication, a default membership provider, properly encrypted/hashed authentication cookies and even a logon control with a remember me checkbox!
You would add the control to your ASP.Net logon page with markup something like this:
<asp:Login ID="LoginControl1" runat="server" CreateUserUrl="Register.aspx"
VisibleWhenLoggedIn="False" TextLayout="TextOnTop" RememberMeSet="True">
(We've set the DisplayRememberMe property to true. This instructs the logon control to display the "Remember me next time" check box and the membership provider to send the persistent authentication cookie to the user's browser upon successful logon.)
Before you start trying that however you should probably read "Walkthrough: Creating a Web Site with Membership and User Login" on MSDN.

Related

MVC logout all active sessions after same user login

I have c# mvc web application.There is simple login page according to email and password. Now I have a need like that:
When a user login to the system, all active sessions that same email address will logout.
How can I achieve this?
You can use Session.Abandon() or Clear() to abandon the current session, but if there are multiple people logged in with the same address, this will not address that.
You'd have to build that detection in; for instance, you could update a flag on the table that represents your users and then in the other user's sessions periodically check the table if they were re-logged in. OR when a user logs in, create a token in a database table with an expiration date; associate that token to a user in a cookie. When logged out or logging back in, you could invalidate the token associated to that email address, and each user, when they attempt to access the application, could be rejected by your application checking whether the token is expired.
The Abandon method should work (MSDN):
Session.Abandon();
If you want to remove a specific item from the session use (MSDN):
Session.Remove("YourItem");
If you just want to clear a value you can do:
Session["YourItem"] = null;
If you want to clear all keys do:
Session.Clear();
If none of these are working for you then something fishy is going on. I would check to see where you are assigning the value and verify that it is not getting reassigned after you clear the value.
Simple check do:
Session["YourKey"] = "Test"; // creates the key
Session.Remove("YourKey"); // removes the key
bool gone = (Session["YourKey"] == null); // tests that the remove worked

how to create a cookie which can store list/Array

In my current project I have to show a Popup(Welcome Info) every time he/she login to the site. In the Popup user have a option(Onclick CheckBox) to hide the Popup for 30days.
I'm achieving this by saving a UserUniqueId to cookie(Which should be an array/list) when he/she click checkBox on popup. As Below
var UniqueId = "xxx";
var uIDCookies = [];
// looping to get all the values that are stored in cookie
$.each($.cookie(), function(i, v) {
uIDCookies.push(i);
});
// if current userUID not found in cookie then showing popup
if (($.inArray(UniqueId, uIDCookies)) === -1) {
//show popup
} else {
// hide popup
}
// create cookie and set expire time
$('.checkBox').on('click', function () {
var date = new Date();
var minutes = 3;
date.setTime(date.getTime() + (minutes * 60 * 1000));
$.cookie(UniqueId, { expires: date, path: '/' });
//hide popup
});
No matter what I'm looping through all cookie values that are stored on client browser so, I feel that there could be a better way to achieve this. Suggestions Please..!!
You are saving the cookie with the UniqueID as the name. Just check if that cookie already exists directly:
if (! $.cookie(UniqueId) ) {
//show popup
} else {
// hide popup
}
This sounds very suspiciously like a very bad design choice, but to answer the question as asked, just serialise the array and convert the string to Base64. Then you can parse it back out again afterwards.
As mentioned in the OP's comments though, there are very few edge cases where this is necessary in the scenario you have mentioned. Also, don't set or get cookies in jQuery. Use your serverside language to gather and set cookie information whereever possible, and send it to the page where needed. Don't use cookies where it would be better to use a data store. You have no control over the cookie information once it has been set, and so they can be a security vector into your application.
Cookies are stored per profile, per browser, per user, per computer, and so aren't always the best way to store this info. Instead, consider adding two columns to your user profile table, DisplayWelcomeMessage as a boolean, and SuppressWelcomeMessageExpiry as a DateTime. That way, the info is set per user, not per cookie. It allows the application to be more scalable, as it gives the user the option to turn it back on before the expiry runs out.

EnableCrossAppRedirects - Where is the cross-domain feature documented?

Here an interesting feature of ASP.NET FormsAuthentication explained in this SO answer: How do you pass an authenticated session between app domains
Quick summary; you can create two ASP.NET websites with the same encryption keys. WebsiteA can create a formsauth token, and redirect to WebsiteB with the token in the querystring (or POST body). Switch on EnableCrossAppRedirects in WebsiteB and ASP.NET detects the token and creates the formsauth cookie. In code:
FormsAuthentication.RedirectFromLoginPage("alice", true);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket("Alice", true, 30);
string encrypted = FormsAuthentication.Encrypt(ticket);
Response.Redirect("http://siteb.dev/Secure/WebForm1.aspx?" + FormsAuthentication.FormsCookieName + "=" + encrypted);
Sounds like a great feature, but where is it documented? I'd feel a bit uneasy using a undocumented feature.
Where I've looked - no mention of this feature in any of the MSDN reference. I thought maybe RedirectFromLoginPage would build a redirect like my code above, it doesn't.
EnableCrossAppRedirects - "is checked within the RedirectFromLoginPage method when the redirect URL does not point to a page in the current application. If EnableCrossAppRedirects is true, then the redirect is performed"
Forms Authentication Across Applications - some advice on setting the machine keys so that a cookie created on a sub-domain, nothing about EnableCrossAppRedirects
forms Element for authentication
Having looked at reflector there is a (somewhat undocumented) feature of forms Authentication. When EnableCrossAppRedirects is enabled .NET will, in addition to looking for the auth cookie, attempt to extract the forms authentication "cookie" from either the form post or the query string. This code is embedded in the FormsAuthentication class in the ExtractTicketFromCookie method, where it can clearly been seen trying to find the authentication cookie in the request data.
if (FormsAuthentication.EnableCrossAppRedirects)
{
text = context.Request.QueryString[name];
if (text != null && text.Length > 1)
{
if (!cookielessTicket && FormsAuthentication.CookieMode == HttpCookieMode.AutoDetect)
{
cookielessTicket = CookielessHelperClass.UseCookieless(context, true, FormsAuthentication.CookieMode);
}
try
{
formsAuthenticationTicket = FormsAuthentication.Decrypt(text);
}
catch
{
flag2 = true;
}
if (formsAuthenticationTicket == null)
{
flag2 = true;
}
}
if (formsAuthenticationTicket == null || formsAuthenticationTicket.Expired)
{
text = context.Request.Form[name];
if (text != null && text.Length > 1)
{
if (!cookielessTicket && FormsAuthentication.CookieMode == HttpCookieMode.AutoDetect)
{
cookielessTicket = CookielessHelperClass.UseCookieless(context, true, FormsAuthentication.CookieMode);
}
try
{
formsAuthenticationTicket = FormsAuthentication.Decrypt(text);
}
catch
{
flag2 = true;
}
if (formsAuthenticationTicket == null)
{
flag2 = true;
}
}
}
}
Therefore if you enable EnableCrossAppRedirects on both applications, then the first application is authorised to redirect to the external site, and the second application will automatically read in the authentication cookie from the request. You just need to engineer it so that the return login URL either posts the cookie data or sends it in the querystring. You also need to be sure that either the machine keys are synchronised, or that the cookie is encrypted using the external apps machine key (by the first app). It seems by default .NET will send the encrypted authentication cookie in the querystring for you and asume your machine keys are in sync (see MSDN quote below).
Here's some more info on MSDN .
If the CookiesSupported property is true, and either the ReturnUrl
variable is within the current application or the
EnableCrossAppRedirects property is true, then the
RedirectFromLoginPage method issues an authentication ticket and
places it in the default cookie using the SetAuthCookie method.
If CookiesSupported is false and the redirect path is to a URL in the
current application, the ticket is issued as part of the redirect URL.
If CookiesSupported is false, EnableCrossAppRedirects is true, and the
redirect URL does not refer to a page within the current application,
the RedirectFromLoginPage method issues an authentication ticket and
places it in the QueryString property.
There is a big warning about the impact on security. EnableCrossAppRedirects is a security setting which prevents ASP.NET login controls from redirecting to an external return URL (another web application). With this setting enabled it can be exploited in some forms of attack - a user is sent to the official login page, but on login is redirected to a different application which they may believe is the same. This is why it's disabled by default.
One way to help mitigate this when enabling the feature is as follows:
To improve security when using cross-application redirects, you should
override the RedirectFromLoginPage method to allow redirects only to
approved Web sites.
You also need to ensure the redirect request is served over SSL to protect the "cookie" in transit, as anyone intercepting would be able to gain control of the account.

InitializeCulture change language of domain

I have a MasterPage with a combo with languages, the thing is that I would like to assign a default language the moment a user starts the application, after that the user can change between languages. What I understand is that I have to override InitializeCulture method on all of the pages, the problem is, where I can save the selected language? When I use Cache["Culture"] all of the user that starts the application shares the same Cache and overrides the value for all the users logged in.
How can I do that? or how can I save data for a single user's thread when it's not logged in?
Thanks in advance for any help.
use the Session object for data specific to sessions, if you need to persist the choice beyond the session you will need to store it with whatever user data you have
Session["Culture"] = yourculturevar;
If you want to save information locally to a user's computer (as opposed to saving something in a database on the server for logged in users), you can use cookies.
Setting a Cookie
private void SetLanguageCookie(string language)
{
HttpCookie cookie = new HttpCookie("UserSelectedLanguage", language);
// Optionally set expiration for cookie
cookie.Expires = DateTime.Now.AddDays(30);
}
Retrieving a Cookie
private string GetLanguageCookie()
{
HttpCookie cookie = Request.Cookies["UserSelectedLanguage"];
return cookie.Value;
}

How can I set up ASP.NET login to allow the UserName or UserId to be retrieved later on in the session?

I'm trying to create a login system for my website, I've created a custom login.ascx and when the user clicks [ Login ] a div pops up with the contents of login.ascx.
Then after the user enters their credentials, they click on the Login button. They get validated and logged in using this code in the login click function:
if( Membership.ValidateUser( userName.Text, password.Text ) )
{
//Here is where I'm not sure what to do
}
else
{
LoginError.Visible = true;
}
So in the section where I'm not sure what to do, I would like the user to get logged in (Not sure if that means creating an authentication ticket or whatnot). What does is the next step to actually log the user in, I don't want them to get redirected anywhere since they are on the correct page already.
I would also like to be able to retrieve their user name or user id later on for use in my web services. So, for this should I do a Session.Add to create a new session value or is there some other way of storing the data that is preferred?
For authenticating the user,
FormsAuthenatication.SetAuthCookie(username, false/*true if you want to remember the user's login*/);
This logs the user in. You can later use
Page.User.Identity.Name
to retrieve username of the current user and
Page.User.Identity.IsAuthenticated
to check if the user is logged in.
There's no need to store it in Session. Just use:
FormsAuthentication.SetAuthCookie
to send an authentication ticket to the client. Then use HttpContext.Current.User.Identity to retrieve it later.
I find using the membership provider is useful, I would recommend it
Scott Guthrie posted great blog on this
http://weblogs.asp.net/scottgu/archive/2006/05/07/ASP.NET-2.0-Membership-and-Roles-Tutorial-Series.aspx

Categories