So basically I generate users data after a payment, which it is saved in a table I created, it has a username and a encrypted password with Hash::make() method.
What I wanna do is to login with that data stored in the DB, so I made a guard.
This is the auth.php
file with guards:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'plataforma' => [
'driver' => 'session',
'provider' => 'usuario',
],
],
And these are the providers:
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'usuario' => [
'driver' => 'eloquent',
'model' => App\Models\Usuario::class,
],
This is the model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Usuario extends Authenticatable
{
use HasFactory;
use Notifiable;
protected $guard = 'plataforma';
protected $fillable = [
'nombre_usuario', 'correo', 'clave',
];
protected $hidden = [
'clave', 'remember_token',
];
}
And finally the controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class PlataformaController extends Controller
{
public function login()
{
return view('web.plataforma-login');
}
public function autenticar(Request $request)
{
if (Auth::guard('plataforma')->attempt(['nombre_usuario' => $request->input('nombre_usuario'), 'clave' => $request->input('clave')])) {
return view('web.plataforma');
} else {
dd(Auth::guard('plataforma')->attempt(['nombre_usuario' => $request->input('nombre_usuario'), 'clave' => $request->input('clave')]));
}
}
public function dashboard()
{
return view('web.plataforma');
}
}
So basically the Auth::guard('plataforma')->attempt(...) returns false, I already checked that the values of $request->input(...) are correct, I checked that the encrypted password in the DB is the same as the password that the user enter with Hash::check(), so I don't know what is wrong and I'm so confused...
I spent a lot of time reading other questions with no solutions either, I would be glad if anyone can help me out.
CodePudding user response:
After reading the API, I've come to the conclusion attempt()
is not working to you because you're using a different password column name.
The following is the attempt
function's code from the Illuminate\Auth\SessionGuard
class:
/** * Attempt to authenticate a user using the given credentials. * * @param array $credentials * @param bool $remember * @return bool */ public function attempt(array $credentials = [], $remember = false) { $this->fireAttemptEvent($credentials, $remember); $this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials); // If an implementation of UserInterface was returned, we'll ask the provider // to validate the user against the given credentials, and if they are in // fact valid we'll log the users into the application and return true. if ($this->hasValidCredentials($user, $credentials)) { $this->login($user, $remember); return true; } // If the authentication attempt fails we will fire an event so that the user // may be notified of any suspicious attempts to access their account from // an unrecognized user. A developer may listen to this event as needed. $this->fireFailedEvent($user, $credentials); return false; }
The key functions here are retrieveByCredentials
and hasValidCredentials
Here's retrieveByCredentials
from Illuminate\Auth\EloquentUserProvider
. As you can see, it's excluding the 'password'
key from the query in the foreach.
/** * Retrieve a user by the given credentials. * * @param array $credentials * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function retrieveByCredentials(array $credentials) { if (empty($credentials) || (count($credentials) === 1 && → Str::contains($this->firstCredentialKey($credentials), 'password'))) { ← return; } // First we will add each credential element to the query as a where clause. // Then we can execute the query and, if we found a user, return it in a // Eloquent User "model" that will be utilized by the Guard instances. $query = $this->newModelQuery(); foreach ($credentials as $key => $value) { → if (Str::contains($key, 'password')) { ← continue; } if (is_array($value) || $value instanceof Arrayable) { $query->whereIn($key, $value); } elseif ($value instanceof Closure) { $value($query); } else { $query->where($key, $value); } } return $query->first(); }
Here's hasValidCredentials
from Illuminate\Auth\EloquentUserProvider
. The key function here is validateCredentials
/** * Determine if the user matches the credentials. * * @param mixed $user * @param array $credentials * @return bool */ protected function hasValidCredentials($user, $credentials) { $validated = ! is_null($user) && $this->provider->validateCredentials($user, $credentials); if ($validated) { $this->fireValidatedEvent($user); } return $validated; }
Here's validateCredentials
from the Illuminate\Auth\EloquentUserProvider
class. You can see it's again, using by default 'password'
as the key name. Let's see what getAuthPassword()
looks like.
/** * Validate a user against the given credentials. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param array $credentials * @return bool */ public function validateCredentials(UserContract $user, array $credentials) { → $plain = $credentials['password']; ← return $this->hasher->check($plain, $user->getAuthPassword()); }
And finally getAuthPassword
from the Illuminate\Auth\Authenticatable
class. It's just returning the model's 'password'
attribute.
/** * Get the password for the user. * * @return string */ public function getAuthPassword() { → return $this->password; ← }
Basically, if you want this to work, you need to change a few things about your code.
- Use
password
as the key inattempt()
public function autenticar(Request $request)
{
$attempt = Auth::guard('plataforma')->attempt([
'nombre_usuario' => $request->input('nombre_usuario'),
'password' => $request->input('clave')
]);
if ($attempt) {
return view('web.plataforma');
} else {
dd($attempt);
}
}
- Override your Authenticatable model (Usuario)'s
getAuthPassword
method.
# Usuario model
/**
* Get the password for the user.
*
* @return string
*/
public function getAuthPassword()
{
return $this->clave;
}