MVC Login password comparison case sensitive - asp.net

I need to compare the username field and the password field with the one in database, my code does work but the problem is that the comparison is not case sensitive. below is part of my code, I know I must be missing something silly. any help will be appreciated, Thanks
var UserDetail = db.UserTbls.Where(x => x.UserName == UserModel.UserName &&
x.Password == UserModel.Password).FirstOrDefault();
if (UserDetail == null)
{
UserModel.loginErrorMessage = "Wrong Username or Password";
return View("Login", UserModel);
}
else
{
Session["UserId"] = UserDetail.UserId;
return RedirectToAction("Index", "Home");
}

EF to SQL Server will perform string comparisons case-insensitive. To perform a case-sensitive check like you describe:
var users = var UserDetail = db.UserTbls.Where(x => x.UserName == UserModel.UserName).ToList();
var matchingUser = users.SingleOrDefault(x => x.Password == password);
The .ToList() will mean the next expression will be evaluated against Objects, returning all user records with that name. If user names are unique then this should be a SingleOrDefault(). From there the == operation on the password will be case sensitive by default.
However, as mentioned by Stephen, Passwords should always be hashed with a salt and stored, where the HASHES are compared, not plain-text passwords.
I recommend reading up on SHA-1 hashes.

string.Compare method has and overload which you can use for comparing the username and passwords.
As Stephen mentioned, you certainly need to work on implementing proper security measures.

If you want to compare user names ignoring case, this is an option:
x.UserName.Equals(UserModel.UserName, StringComparison.OrdinalIgnoreCase)
If you want to compare user names case sensitive, this is an option:
x.UserName.Equals(UserModel.UserName, StringComparison.Ordinal)
Update:
For anyone coming to this post who see's my answer, I'd like to point to Steve Py's answer which I've upvoted. And, here is a nice related explanation.
(I figured that I might as well leave my answer here in case it's still helpful for people to see different approaches to comparing strings)

Related

How to check password manually in Asp.Net identity 2?

This might actually be more of a conceptual question. In Asp.Net Identity the PasswordHasher generates a different hash for the same string every time you do:
new PasswordHasher.HashPassword("myString");
Now if for some reason I need to manually compare a user's input to the password saved in the database, I will most probably get a different string when I hash the user's entered password, than the one that is stored in the database.
Can someone please explain this to me? Shouldn't hashing the same string result in the same hash and if not, how does Identity itself realize that two different hashes are in fact the same?
PasswordHasher generates different hashes each time because it uses salting technique. This technique secure the hashed password against dictionary attacks. By the way you could use following code to manually verify the password:
if(PasswordHasher.VerifyHashedPassword("hashedPassword", "password")
!= PasswordVerificationResult.Failed)
{
// password is correct
}
var user = _userManager.Users.SingleOrDefault(p => p.PhoneNumber == model.PhoneNumber);
if (user == null)
{
return RedirectToAction(nameof(Login));
}
var result1 = _userManager.PasswordHasher.VerifyHashedPassword(user, user.PasswordHash, model.Password);
if (result1 != PasswordVerificationResult.Success)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}

Best way to compare two authentication tokens

Consider the following example: http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html#the-listener
I want to see if the new authenticated token is the same as for the currently logged in user. See below.
try {
$currentToken = $this->securityContext->getToken();
$authToken = $this->authenticationManager->authenticate($token);
// What is the best way to compare these two? Both implement TokenInterface.
if ([compare tokens]) {
// already logged in
return;
}
$this->tokenStorage->setToken($authToken);
return;
} catch (AuthenticationException $failed) {
}
I considered comparing UserInterface->getUsername():
if ($currentToken->getUser()->getUsername() === $authToken->getUser()->getUsername()) {
But wonder if there is a better solution...
I assume both user object aren't the same reference. Because if they are you could compare them using === to check if they are the same.
Given that username is unique than this is one way to check if it is the same user.
But in some systems the username doesn't have to be unique. So comparing the id's might be better since they should alway be unique.
What about leveraging the code they show in the authenticate() function?
$currentUser = $this->userProvider->loadUserByUsername($currentToken->getUsername());
then
$tokenUser = $this->userProvider->loadUserByUsername($authToken->getUsername());
then
if ($currentUser == $tokenUser) {

How to hide information in Firebase?

I have these requirements:
User will log in via email and multiple Oauth providers. I use function like User.findByEmail('1#1.com'). So I need to have permision to see the list of users before being authenticated.
User's email address, geolocation and age should be kept secretly from other users.
My first plan was:
users:{
$user-id:{
// public
".read" : true,
name,
created_at,
private: {
".read" : "auth.email === data.child('email').val()",
age,
email,
geolocation,
}
$piority = email
}
}
Then I realized no, it just doesn't work that way. So would anyone please tell me how to do it correctly? Thanks in advance.
P.S. Firebase really needs a filter/serialize method.
There are really several questions in this post. The first is how to store private data. One simple change you can make is to invert the public/private and user keys--they don't have to be nested in the same user record.
/users/$user_id/...public data...
/private/$user_id/...private data...
This makes securing the data quite a bit simpler.
Another question is regarding duplicate email detection. If we assume you are using simple login here, this is all pretty moot. You can check to see if an email address exists by simply trying to create the account. An error will be returned if the email is already registered.
If that doesn't solve it, you can still check this manually, without providing a list of users' emails. This is typically done with an index. When a new account is created, write something like this:
/email_index/$escaped_email/$userid ($userid is the value)
Now when you want to check if the email is available, you do a read like this:
var ref = new Firebase(URL);
function checkEmail(emailAddress, callback) {
ref.child('email_index/'+escapeEmail(emailAddress)).once('value', function(snap) {
callback(snap.val() !== null);
});
}
function escapeEmail(emailAddress) {
return (email || '').replace('.', ',');
}
checkEmail(EMAIL_ADDRESS, function(exists) {
console.log(EMAIL_ADDRESS + (exists? 'does' : 'does not') + ' exist!');
});
To prevent someone from listing the emails, you do something like this in your (amazingly flexible and really quite sophisticated, even for enterprise apps) security rules:
"email_index": {
// no .read rule here means that the data cannot be listed; I have to know the email address to check it
"$email_address": {
".read": true,
// it can only be claimed once and the value must be my user id
".write": "auth.uid === newData.val() && !data.exists()"
}
}

asp.net membership provider Guid userID

I need (I think) to get the current logged in userID so that I can update one of my tables that uses this userID as a foreign key. The problem is that the userID in the database does not match with this:
Guid currentUser = (Guid)Membership.GetUser().ProviderUserKey;
currentUser.toString();
results in dffaca0c-ae0b-8549-8073-1639985740be
whereas when I look in the database, it is 0CCAFADF0BAE498580731639985740BE
Why are they different values? (I only have one user). I am using an oracle database and provider for asp.net, but shouldn't make any difference.
I believe these are the same values, but the display order is different. Looking at the 2 values:
dffaca0c-ae0b-8549-8073-1639985740be
0CCAFADF-0BAE-4985-8073-1639985740BE
The ordering of bytes for the first 3 segments is of a different order:
0CCA FADF => FADF 0CCA => DFFA CA0C == dffaca0c
0BAE => AE 0B == ae0b
4985 => 85 49 == 8549
As #x0n comments, this looks like a difference in endianness with Oracle. According the this description of the structure, the endianness of the first 8 bytes is system dependent, while the endianness of the last 8 bytes is specifically big endian.
I had the same issue and came up with this which resolved the issue:
public static string TranslateOraceEndianUserID()
{
MembershipUser myObject = Membership.GetUser();
Guid g = new Guid(myObject.ProviderUserKey.ToString());
byte[] b = g.ToByteArray();
string UserID = BitConverter.ToString(b, 0).Replace("-", string.Empty);
return UserID;
}
Or maybe also try using HttpContext.Curent.User to get the current user?
You could always use the Lower Case User Name column to create the foreign Key. It is always unique. Maybe not the best option but it is the simplest and works well. I have used it in several projects.

Storing DotNetOpenAuth information and user info retrieval

This question is a bit of a structural/design question as I'm having trouble working out the best way to perform the task.
In my MVC app, I am using DotNetOpenAuth (3.4) as my login information provider and just using the standard FormsAuthentication for cookies etc.
The current user table in the DB has:
UserId (PK, uniqueidentifier)
OpenIdIdentifier (nvarchar(255))
OpenIdDisplay (nvarchar(255))
Displayname (nvarchar(50))
Email (nvarchar(50))
PhoneNumber (nvarchar(50))
As the UserId is the clear identifier for a user (they should be able to change their OpenId provider at a later date), it is the key that other tables link to (for a user).
This is the current code, that on a successfull authentication, creates a temporary user and redirects to Create Action.
switch (response.Status)
{
case AuthenticationStatus.Authenticated:
FormsAuthentication.SetAuthCookie(response.ClaimedIdentifier, false);
var users = new UserRepository();
if (!users.IsOpenIdAssociated(response.ClaimedIdentifier))
{
var newUser = new DueDate.Models.User();
newUser.OpenIdIdentifer = response.ClaimedIdentifier;
newUser.OpenIdDisplay = response.FriendlyIdentifierForDisplay;
TempData["newUser"] = newUser;
return this.RedirectToAction("Create");
}
And now for the crux of the question:
Is the response.ClaimedIdentifier the correct piece of information to be storing against a user?
Is FormAuthentication.SetAuthCookie the preferred way to forms authentication? Or is there a better way?
When I call SetAuthCookie, there is no data relating to the user except for the ClaimedIdentifier. If I'm consistently referring to their UserId, is a better idea to create the user, then store that UserId in the cookie instead of the ClaimedIdentifier?
If I'm using that UserId in a number of places, how do I either retrieve it from the cookie, or store it somewhere else more logical/useful?
A bit long winded but I've been having trouble trying to work out the best way to do this/
1.Is the response.ClaimedIdentifier the correct piece of information to be storing against a user?
Yes. And make sure the column you store it in the database with is case sensitive. Here is a table schema that demonstrates how to make sure it is case sensitive. This comes out of the DotNetOpenAuth project template's database schema. The "CS" bit of the specified collation stand for Case Sensitive.
CREATE TABLE [dbo].[AuthenticationToken] (
[AuthenticationTokenId] INT IDENTITY (1, 1) NOT NULL,
[UserId] INT NOT NULL,
[OpenIdClaimedIdentifier] NVARCHAR (250) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL,
[OpenIdFriendlyIdentifier] NVARCHAR (250) NULL,
[CreatedOn] DATETIME NOT NULL,
[LastUsed] DATETIME NOT NULL,
[UsageCount] INT NOT NULL
);
2.Is FormAuthentication.SetAuthCookie the preferred way to forms authentication? Or is there a better way?
For MVC apps it definitely is, since you still can return your preferred ActionResult from the method.
3.When I call SetAuthCookie, there is no data relating to the user except for the ClaimedIdentifier. If I'm consistently referring to their UserId, is a better idea to create the user, then store that UserId in the cookie instead of the ClaimedIdentifier?
That sounds like personal preference. But I would typically go with user_id, since it might result in a faster database lookup every time an HTTP request comes in that requires you to look up any user information.
4.If I'm using that UserId in a number of places, how do I either retrieve it from the cookie, or store it somewhere else more logical/useful?
FormsAuthentication does provide a way to store more information in its encrypted cookie than just username, but it is harder than you'd expect to use it. This snippet comes out of DotNetOpenAuth's web SSO RP sample:
const int TimeoutInMinutes = 100; // TODO: look up the right value from the web.config file
var ticket = new FormsAuthenticationTicket(
2, // magic number used by FormsAuth
response.ClaimedIdentifier, // username
DateTime.Now,
DateTime.Now.AddMinutes(TimeoutInMinutes),
false, // "remember me"
"your extra data goes here");
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
Response.SetCookie(cookie);
Response.Redirect(Request.QueryString["ReturnUrl"] ?? FormsAuthentication.DefaultUrl);
Then you can get at that extra data in a future HTTP request with this:
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null) {
var ticket = FormsAuthentication.Decrypt(cookie.Value);
if (!string.IsNullOrEmpty(ticket.UserData)) {
// do something cool with the extra data here
}
}

Resources