kazinix
kazinix

Reputation: 30093

ASP.NET MVC / C# - Linq and hashed password

I'm trying to create authentication where all passwords are hashed and salted. First, for simplicity, I tried without salt, here's my linq:

var CurrentUser = db.Users
    .Single(u => u.UserName == form["username"] && u.Password.SequenceEqual
               (
                   MD5.Create().ComputeHash
                       (
                           Encoding.UTF8.GetBytes(form["password"])
                       )
               )
          );

Unfortunately, this error occurred:

The query operator 'SequenceEqual' is not supported.

Upvotes: 1

Views: 1951

Answers (3)

the_joric
the_joric

Reputation: 12226

Why not to get user by name and then compare it's password with salt? Kind of

var CurrentUser = db.Users
    .FirstOrDefault(u => u.UserName == form["username"]); 
if (CurrentUser == null || !CurrentUser.Password.SequenceEqual(
                   MD5.Create().ComputeHash(
                           Encoding.UTF8.GetBytes(form["password"])))) { ...user of password is incorrect.. }

Upvotes: 0

Steven Robbins
Steven Robbins

Reputation: 26599

It would help to know where you're getting your user records from (i.e. what is "db.Users").

Whatever linq provider your using (EF etc) probably doesn't support using SequenceEqual in a query, so you'll need to grab the user record, then check the password:

var currentUser = db.Users.Single(u => u.UserName == form["username"]);
var hash = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(form["password"]));

var passwordCorrect = currentUser.Password.SequenceEqual(hash);

You may also want to be more explicit in your "u.UserName ==" comparison to make it obvious whether it's case insensitive/ordinal etc.

Edit: Flater's answer will also work fine, but personally I'd rather pull the record back and verify it as you may want to know whether the user actually exists or not (not just whether the username and password are correct) so you can "lock out" accounts or take other (more helpful) action based on a number of incorrect password attempts.

Upvotes: 5

Flater
Flater

Reputation: 13763

LINQ doesn't allow every kind of function/operator in its lambda expressions. It can be quite annoying at times. I would suggest to find a way in which you can store what you want to check against in a variable, then just checking for

... && u.Password = myVariable);

Upvotes: 1

Related Questions