Laravel | Problem with different cipher bcrypt

1

In the user registry I save the key with bcrypt, and in the authentication I make a return of the password and it gives me a different hash value of how the key is in the database, look:

db key: $ 2y $ 10 $ 5HZ4raSDAB8WHJgG07yXU.1.9t2M / V3rtk ... Login key: $ 2y $ 10 $ .YCEUONOZpy6BVZqP / tI6u ...

In my sentence it gives me false:

    public function store(LoginRequest $request) {

    $correo = $request['correo'];

    $clave = bcrypt($request['clave']);

    return $clave;

    if (Auth::attempt(['correo' => $correo, 'clave' => $clave])) {

       return 'Login correcto'; 

    }else{

        return 'falso';
    }
}

What am I doing wrong?

    
asked by gburu98 05.07.2016 в 21:11
source

2 answers

0

The bcrypt function is only to generate the key, not to compare it.

The easiest thing is that you use 'password' instead of 'password' as the name of the field that contains it.

If you want to change the name of the field you should extend the Laravel core a bit, or use the following code for the comparison:

if (Hash::check('plain-text', $hashedPassword)) {
    // The passwords match...
}

You can see more information in the Laravel documentation: link

Edit to add details explaining the answer:

When you call the attempt method of Laravel, you are using this code located in Illuminate\Auth\SessionGuard :

public function attempt(array $credentials = [], $remember = false, $login = true)
{
    $this->fireAttemptEvent($credentials, $remember, $login);

    $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

    if ($this->hasValidCredentials($user, $credentials)) {
        if ($login) {
            $this->login($user, $remember);
        }

        return true;
    }

    return false;
}

In the code we see that an event is activated and then we call the method retrieveByCredentials() of the provider and a verification by hasValidCredentials() , also as you can see, you are only passing the first argument, $credentials .

Now let's analyze the code of retrieveByCredentials() , located in Illuminate\Auth\EloquentUserProvider :

public function retrieveByCredentials(array $credentials)
{
    if (empty($credentials)) {
        return;
    }

    $query = $this->createModel()->newQuery();

    foreach ($credentials as $key => $value) {
        if (! Str::contains($key, 'password')) {
            $query->where($key, $value);
        }
    }

    return $query->first();
}

What the method does is find the first result of the user model that corresponds to the credentials that we are giving it, it will iterate through the array that we passed BUT if the field we passed is called 'password', It is NOT going to compare, the idea is that the method look for a user who has an email or user name X simply.

I would think that your application fails at this point, you are telling it to compare two fields: mail and password, and when comparing password it does not work for the reasons described in the first part of the answer, before editing.

Returning to our attempt, we will call the method hasValidCredentials() :

protected function hasValidCredentials($user, $credentials)
{
    return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);
}

If the result of the query made in the previous method is not null (which is likely to be the case in this case) and if the result of the method validateCredentials() that we will see below also is true, then the user will log in:

public function validateCredentials(UserContract $user, array $credentials)
{
    $plain = $credentials['password'];

    return $this->hasher->check($plain, $user->getAuthPassword());
}

What validateCredentials does is to simply take the 'password' field (which is not present in your case) from the credentials we pass to it and compare it with the stored key, this method check() you find in Illuminate \ Hashing \ BcryptHasher:

public function check($value, $hashedValue, array $options = [])
{
    if (strlen($hashedValue) === 0) {
        return false;
    }

    return password_verify($value, $hashedValue);
}

Nothing unusual in this method, the documentation of password_verify is on the php website .

Summary:

It is easier to use the password field as a key, otherwise you may need to extend classes or override some of Laravel's methods so that your authentication works or failing to do your own authentication implementation so as not to go through these methods.

The result could be something like this:

public function store(LoginRequest $request) {

    $correo = $request['correo'];
    $clave = $request['clave'];

    if (Auth::attempt(['correo' => $correo, 'password' => $clave])) {
        return 'Login correcto'; 
    } else {
        return 'falso';
    }
}
    
answered by 05.07.2016 / 21:44
source
0

Just remove the bcrypt function for your $ clave variable give a read to your official documentation

Manually Authenticating Users

    
answered by 06.07.2016 в 17:23