ASP.NET user login best practices - asp.net

I want to make a login system using ASP.NET (MVC).
On the internet, I found some bad examples that involved SQL in Click events. Other information pointed to the ASP.NET built-in membership provider.
However, I want to roll my own. I don't want to use the built-in membership provider, as it only seems to work on MS SQL, and I don't like the idea of having a few foreign tables in my database.
I could probably think of something, but I need a few pointers in the right direction. It does not have to be high-security, but just regular common-sense security.
And I have a few direct questions:
A lot of systems seem to have the Session ID stored in a user table. I guess this is to tie a session to a user to prevent hijacking. Do check this every time a user enters a page? And what do I do if the session expires?
Hashing, salting, what does it do? I know of MD5 hashing and I have used it before. But not salting.
Best practices for cookies?

I dont know about best practices but I can tell you what I do. Its not hitech security but it does the job.
I use forms authentication. I receive the password secured with ssl via a textbox on the login page. I take that password and hash it. (Hashing is like one way encryption, you can get hash code that cant be reversed back to the password). I take that hash and compare it to the users hash in the database. If the hash's match i use asp.nets built in authentication handling, which handles cookies for me.
The FormsAuthentication class has methods available to do this fo you, such as SetAuthCookie and RedirectFromLogin. they will set the cookie and mark them as authenticated. The cookie asp.net uses is encrypted. I cant speak for its security level though, but its in fairly common use.
In my class i do the password check and use formsauth to handle the rest:
if(SecurityHelper.LoginUser(txtUsername.Text, txtPassword.Text))
{
FormsAuthentication.RedirectFromLoginPage(txtUsername.Text, true);
}

You can implement your own membership provider using the ASP.NET infrastructure, see MSDN docs for MemberShipProvider class.

The built in provider works well. It does actually work with MySQL, although I found it not to be as straight forward as the MS SQL version. If you can use then do, it'll save you hours of work.
If you need to use another data store then I concur with axel_c, if I was going to roll my own then I'd write a membership provider as per MS specification. It will make the code more maintainable for any developers following you.

Salting is the practice of adding a unqiue string of characters to whatever is being hashed. Suppose mySalt = abc123 and my password is passwd. In PHP, I would use hashResult = md5(mySalt + password).
Suppose the string is intercepted. You try to match the string, but you end up matching gibberish because the password was salted before encrypted. Just remember that whatever you use for salt must be continuous throughout the application. If you salt the password before storage, you must compare the hashed, salted password to the DB.

You can use the built in SQL membership provider - and you could set up a dedicated "user access" database if you don't want the .Net membership tables within your database - just specify that in the connection string.
THe advantage with the provider model is at the application level, the code is independent of what particular authentication store you have used.
There are a good series of tutirials on the asp.net site:
link text

A disadvantage of the Membership Provider by microsoft is that you can't use it in a domain driven approach. If you want to, you can create your own user object with your own password hash and still use the authentication cookies provided by Microsoft. Using these authentication cookies means that you don't have to manage the session IDs yourself.
public void SignIn(User user)
{
FormsAuthentication.SignOut();
var ticket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now.AddMinutes(30), expires, alse, null);
var encryptedTicket = FormsAuthentication.Encrypt(ticket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
{
Expires = ticket.Expiration
};
httpContextProvider.GetCurrentHttpContext().Response.Cookies.Add(authCookie);
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
I use my own user object and tables.
I store my passwords hashed in the usertable with a unique salt per user.
This is secure, easy to implement and it will fit in your design.
Your database table won't be polluted by Microsofts membership provider crap.

I would avoid the whole issue and use openid. There is a library available that you can use directly.
Here is a link to a blog post about putting this in place

Related

Retrieve Password in ASP.NET Identity System

How to retrieve password back in original form in Asp.Net Identity System from PasswordHash column?
You don't.
The whole idea behind hashing algorithms is that they're one way processes. With some work you could swap out hashing for encryption of passwords, but A) if you've used the default (which is a hashing algorithm) and you've already got users in the database, you aren't getting those passwords back, and B) there are good security reasons passwords are hashed instead of encrypted.
If you just need to reset the password for the user and you have access to the source code, there's plenty of ways to do this. This SO Q&A is a good start.
Actually what i have to do is: In Admin module of my project i have to show existing users with their credentials ie username/email and their password......so reset password wont work.

Change Username ASP.net MVC 3 Membership

I am running a ASP.net MVC 3 web application, and using the Membership Provider. I would like to know if its possible to allow the user (or administrator) to change an existing accounts username? I have not found a way to do this. The username is not an email address, but is validated on its uniqueness prior to my attempt at assigning the new name.
Any help would be appreciated!
The membership provider does not provide a method to update the username. You will either need to extend the membership providers UpdateUser method or directly interact with the membership tables to allow this change. However you approach this, keep in mind a few items
On update, you will need to check uniqueness of the username much like what happens when a user is created.
If the user is logged in and changes their username, you will either need to force them logout and log back in or reissue the AuthenticationTicket cookie. The reason being, if they change their username, then the authTicket cookie stored username and the actual username not longer match. If you use HttpContext.Identity.User.Name to query your datastore or check authorization to content, you will no longer return any results as that username no longer exists.

Avoid Multiple calls to GetUser when using ASP.NET Membership

I am using ASP.NET Membership in an ASP.NET MVC 3 Web application project.
I have installed the ASP.NET Membership tables using Aspnet_regsql.exe and now my main userTable has a foriegn key called "userID" which points to the "UserId" of aspnet_Users.
This "userTable" is connected to many tables. So for every operation now I require the "UserId" from aspnet_User using the username with which the user has logged in.
For this I use
MembershipUser user = Membership.Provider.GetUser(username, true);
now for each and every operation I have to make this call and get user.ProviderUserKey to continue with my other operations.
I am thinking there has to be a better way to do this. Is any any built in way to do this ?
The ASP.NET Membership Provider isn't intended to provide the ProviderUserKey... perhaps you could use the username instead? You can always easily access that through Context.User.Identity.Name.
I always use:
Guid userId = (Guid)Membership.GetUser().ProviderUserKey;
You get the user information once and put it in forms authentication cookie with user data encrypted.
For subsequent calls you use Context.Identity for the user information
You can keep the relevant information around in the cache, for example in a Dictionary<string, Guid> where the key is the user name (which you can lookup using HttpContext.Current.User.Identity.Name or Thread.CurrentPrincipal.Identity.Name), and the ProviderUserKey is the value.
Build this dictionary either on-demand or initialize it once, and put it in the ASP.NET Cache, Session or Application (of course watch our for serialization and concurrency issues).

Using a Membership Provider for Private Site

I can't be the first person to have this problem, I must be missing an easy solution. I have inherited a non-public ASP.NET site secured using a forms authentication with a SqlMembershipProvider to secure the site. Everything is working fine with the users the developer manually added to the database.
I need to add an administrative page to allow priviliged users to add and alter user accounts. The membership provider makes it really easy to build one, but the problem I'm having with the SqlMembershipProvider now is the question/answer requirement. The administrator needs to be able to reset the other users' passwords to a temporary password and create a new user account (also with a temporary password). Reseting a password requires either the answer for the user's question or their current password.
I could of course just put in something like "question" and "answer" for all accounts and it would work, but I'm concerned about security risks of doing this. Perhaps I'm being too paranoid though. Creating a custom membership provider, in addition to being a lot of work, doesn't solve this problem because the membership provider base has the same requirements.
Thank you.
Reseting a password requires either the answer for the user's question or their current password
If you are currently not using the question/answers , you can override this in the web.config
requiresQuestionAndAnswer="false"
After that you can do:
string requesteduserGUIDstring = "some GUID";
Guid UserID = new Guid(requesteduseridstring.ToUpper());
MembershipUser mu = Membership.GetUser(UserID);
mu.ChangePassword(mu.ResetPassword(), tbNewPassword.Text);
If you are using the question/answers, you can add a second provider to your web.config and set only for that provider the same overrule and use that provider ONLY for the reset password functionality,

asp.net membership provider api. usability. best-practice

Membership/Role/Profile providers API appeared in early days of asp.net
Nearly everytime I can't live with standard API & have to add some extra functionality (for sorting, retrieving e.t.c.). I also have to use different database structure often (with foreign key to some tables for example) or think about performance improvements.
These considerations forced teams I took part in to build own providers but I can't stand to implement providers API (because we don't use 70% of standard functionality at least). Moreover, providers that were built for exact projects were rarely reused.
I wonder if someone found swiss-knife early-days-API providers implementation that is usefull for any kind of project without refactoring...
Or do you use your own implementations of early-days-API's
Or may be you abandon standard architecture and use lightweight implementations ?
Thank you in advance
I too have found that oftentimes I don't need all the functionality exposed in the standard MembershipProvider bases. These days, I tend to write my own lightweight methods for authenticating and authorising users.
I typically follow these as a rough guide:
Set authentication mode to Forms in web.config
Custom class to authenticate a user and retrieve roles for associated UserId
Login form to manually issue FormsAuthenticationCookie (see example below)
Configure web.config elements in subdirectories to prohibit access to roles
The following is an example of code you can use to create the FormsAuthenticationTicket yourself, using your own lightweight methods to authenticate and authorise your users:
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
data.AccountId.ToString(),
DateTime.Now,
DateTime.Now.AddHours(24),
rememberMe,
data.ToString());
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
if (rememberMe)
cookie.Expires = DateTime.Now.AddDays(30);
HttpContext.Current.Response.Cookies.Add(cookie);
This is just a rough idea but remember it's entirely up to you whether you use the MembershipProviders as is, whether you implement your own, or whether you choose to ditch them altogether and build your own, providing just the functionality you require. I often choose the latter, simply because a lot of the applications I write are upgrades from legacy systems which already have membership databases in place etc.
Hope this helps.

Resources