Silverstripe: MemberAuthenticator::authenticate() fails when password has hash sign - silverstripe

I have following piece of code in -
public function apilogin(){
$auth = array(
"Email" => $this->requestParams["email"],
"Password" => $this->requestParams["pwd"]
);
$log = MemberAuthenticator::authenticate($auth);
if($log){
//login successful
}else{
//Error in logging in
}
}
The Problem
This method works well except when password has hash "#" sign. I checked multiple times. It works if login is correct and password doesnot have hash sign. But it miserably fails if password has hash even if password is correct.
I m aware of the fact that, its likely for security reason hash is escaped (as it treats as comment)
Is there any fix for this? Thanks

Related

How to read symfony fetched data from database

I am very new to symfony and got knowledge in php. On my project my end result of db query is $user.\
if i use print_r($user) i get this result
xxx\xxxx\Article Object ( [username:xxxx\xxxx\Article:private] => asdfasdf [passsword:xxxx\xxxx\Article:private] => [usertype:xxxx\xxxx\Article:private] => gaeafsdfa)
how can i fetch the username to check against a specific user and if condition passes change password to other.
All i need to how to read the username and how to set the password.
I found the answer
I got to call as
$user->getUsername(); // to see the user name
$user->setPassword($generatedPassword); // to update the password.

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);
}

Meteor functionality to check for existing user in Meteor.users?

How does this code look? Pretty solid and efficient? Any way I could do this better?
EDIT: Forgot to mention, I'm checking as a user fills out a signup form, before they hit submit to actually create the account.
Template HTML:
...
<input id="username">
{{#if usernameTaken}}
<div class="error">Username is taken.</div>
{{/if}}
...
Client:
Template.signupPage.events
'blur #username': (e) ->
username = $(e.target).val()
Meteor.call 'userExists', username, (error, result) ->
Session.set 'usernameTaken', result.exists
Template.signupPage.helpers
usernameTaken: ->
return Session.get('usernameTaken')
Server:
Meteor.methods
userExists: (username) ->
check username, String
results = Meteor.users.find
username:
$regex: "^#{username}$", $options: 'i'
return { exists: results.count() > 0 }
On the client-side, there's a potentially confusing interaction here. In the example, "myusername" is taken, but "myusername1" is not.
User types in "myusername" and then blurs the field
Client makes a method call to see if "myusername" is taken
User changes their mind, changes the field to "myusername1" and blurs the field
Client makes a method call to see if "myusername1" is taken
The first method call returns, and "Username is taken" appears
A reasonably long time passes
The second method call returns, and "Username is taken" disappears
If the user doesn't wait for the "reasonably long time", they'll probably think the "Username is taken" refers to "myusername1" and not "myusername".
I'd take some steps against this:
Display "Checking username availability..." while the method call is in progress. Replace it with e.g. "myusername is taken" or "myusername1 is available" when the method returns. Use colour and icons appropriately.
If the method call is in progress and the user types anything in the field, even if they didn't blur the field yet, then hide the "Checking username availability". When the out-of-date method call returns, ignore the result.
If it says "#{username} is (taken|available)" and the user types anything in the field, even if they didn't blur the field yet, then hide that text.
It should work, but the accounts API already have built in duplicate username detection as usernames / emails should be unique.
So you could also rely on Accounts.createUser (see the doc):
Accounts.createUser({username:..., email:..., password:...}, function(error, result){
//you will get an error if the username already exists
});

ASP.NET MVC4 Get email of logged user

I am making asp.net mvc4 web application. I wrote contact form function in my controller which sends feedback from users. I am using System.Net.Mail class.
I am using Simplemembership and I extended UserProfile with string Email property.
How to get logged in user Email? I want to include it it sended message, so I Could answer.
I tried to use:
var em = from m in db.UserProfiles.Where(a => a.UserName.Contains(User.Identity.Name)) select m.Email;
string email = em.ToString();
but in the sent mail I have:
SELECT
[Extent1].[Email] AS [Email]
FROM [dbo].[UserProfile] AS [Extent1]
WHERE [Extent1].[UserName] LIKE #p__linq__0 ESCAPE N'~'
To retrieve a single entry of the database, you have to select the first row returned with the First() method:
string email = db.UserProfiles
.Where(a => a.UserName.Contains(User.Identity.Name))
.First().Email;
Hope it helps !
You already have the correct answer, so I am just throwing this up here for future searchers to see the shorter syntax.
string email = db.UserProfiles
.FirstOrDefault(a => a.UserName.Contains(User.Identity.Name)).Email;
However in your scenario, I would be concerned about User1 receiving emails intended for User11. To prevent this, you need to be more specific in your query
string email = db.UserProfiles
.FirstOrDefault(a => a.UserName == User.Identity.Name).Email;

User verification on the reset password page

I am writing a password-reset page for my website. Here's my idea:
a. User click the "forgot password" link on the login page
b. Redirect to my password-reset page
c. User enter his email address
d. A email message sent to the email address with the link to reset his/her password. The link has security code like ?code="xxxx" in it.
e. User open the link and enter new password, and then click the submit button.
f. My page change user's password.
My question is for step f. In step e, when user opened the link, I could verify his security code and then show the 'new password' and the 'confirm password' fields to user. But when the user clicked the submit button, how could I know this is a real request submited by the user instead of a hacker? Maybe I am wrong, but I think hacker can easily simulate such field data, since there is no validation fields.
There are some idea I can think of to validate the request in step f, but I don't know whether they are right.
1. Add a encrypted cookie in step e and check it in step f?
2. Use a session variable in step e and check it in step f?
3. Add a hidden field in step e and check it in step f?
Are those approaches ok? Which one is better, or is there any better one?
Thanks in advance.
A user entering their username and reset code should log them into the site just as their username and password would. The difference is you then immediately force them to change their password. With this password reset method you're implicitly trusting that the user is the owner of the email account where the code was sent.
Edit:
Ok, so I don't know the first thing about ASP.net.
However, I've handled this problem many times before. Here is a solution of mine in PHP:
<?php
class AuthController extends Zend_Controller_Action
{
public function identifyAction()
{
if ($this->_request->isPost()) {
$username = $this->_getParam('username');
$password = $this->_getParam('password');
if (empty($username) || empty($password)) {
$this->_flashError('Username or password cannot be blank.');
} else {
$user = new User();
$result = $user->login($username, $password);
if ($result->isValid()) {
$user->fromArray((array) $this->_auth->getIdentity());
if ($this->_getParam('changepass') || $user->is_password_expired) {
$this->_redirect('auth/change-password');
return;
}
$this->_doRedirect($user);
return;
} else {
$this->_doFailure($result->getIdentity());
}
}
}
$this->_redirect('/');
}
public function forgotPasswordAction()
{
if ($this->_request->isPost()) {
// Pseudo-random uppercase 6 digit hex value
$resetCode = strtoupper(substr(sha1(uniqid(rand(),true)),0,6));
Doctrine_Query::create()
->update('dUser u')
->set('u.reset_code', '?', array($resetCode))
->where('u.username = ?', array($this->_getParam('username')))
->execute();
$mail = new Zend_Mail();
$mail->setBodyText($this->_resetEmailBody($this->_getParam('username'), $resetCode));
$mail->setFrom('no-reply#example.com', 'Example');
$mail->addTo($this->_getParam('username'));
$mail->setSubject('Forgotten Password Request');
$mail->send();
$this->_flashNotice("Password reset request received.");
$this->_flashNotice("An email with further instructions, including your <em>Reset Code</em>, has been sent to {$this->_getParam('username')}.");
$this->_redirect("auth/reset-password/username/{$this->_getParam('username')}");
}
}
public function resetPasswordAction()
{
$this->view->username = $this->_getParam('username');
$this->view->reset_code = $this->_getParam('reset_code');
if ($this->_request->isPost()) {
$formData = $this->_request->getParams();
if (empty($formData['username']) || empty($formData['reset_code'])) {
$this->_flashError('Username or reset code cannot be blank.');
$this->_redirect('auth/reset-password');
} elseif ($formData['new_password'] !== $formData['confirm_password']) {
$this->_flashError('Password and confirmation do not match.');
$this->_redirect('auth/reset-password');
} else {
$user = new User();
$result = $user->loginWithResetCode($formData['username'], $formData['reset_code']);
if ($result->isValid()) {
$user->updatePassword($result->getIdentity(), $formData['new_password']);
$user->fromArray((array) $this->_auth->getIdentity());
$this->_setLegacySessionData($user);
$this->_flashNotice('Password updated successfully!');
$this->_doRedirect($user);
} else {
$this->_doFailure($result->getIdentity());
$this->_redirect('auth/reset-password');
}
}
}
}
protected function _doFailure($username)
{
$user = Query::create()
->from('User u')
->select('u.is_locked')
->where('u.username = ?', array($username))
->fetchOne();
if ($user->is_locked) {
$lockedMessage = Config::get('auth.lock_message');
if (!$lockedMessage) {
$lockedMessage = 'This account has been locked.';
}
$this->_flashError($lockedMessage);
} else {
$this->_flashError('Invalid username or password');
}
}
}
If you can follow this, it should give you a good idea of what to do. I'll try to summarize:
identifyAction
This is the regular "login" using username and password. It logs the user in and stores their identity in the session.
forgotPasswordAction
This presents the user with a form requesting their username. After entering their username a reset code is generated, stored in their entry in the user table, and they are emailed as well as redirected to the reset password page. This page is unauthenticated, the user is not logged in.
resetPasswordAction
This is where the user is presented with the "resetPassword" form. They must provide their username and the reset code they received via email. This authenticates the user with the given username and reset code, just as if the reset code were a password. If the credentials are valid the user is then redirected to the changePassword action where they are permitted to change their password. The changePasswordAction (not shown) requires the user be authenticated (logged in) either via username/password or username/resetCode
Hope this helps.
If your code that you're emailing is a GUID or some such ID, there is a statistically low chance that someone can guess that code. If you additionally had the link include a hashed version of their email or some other way of linking the code to the user, I think you'd be pretty well safe from malicious input.
I'd be more worried about people being spammed from step c/d, unless you're doing some sort of verification of the email existing currently in your database.

Resources