I've looked through all other questions on this...
So I set up a userSeeder which autopopulates my User table:
public function run()
{
$users = [
[
"email" => "email#myemail.co.uk",
"fname" => "Nicola",
"sname" => "Elvin",
"password"=>Hash::make("password")
]
];
foreach ($users as $user)
{
User::create($user);
}
}
My table shows this is stored, and password has been hashed.
In my login function:
$credentials = [
"email" => Input::get("email"),
"password" => Input::get("password")
];
if (Auth::attempt($credentials)) {
return Redirect::route("user/profile");
}else{
echo 'wrong';
}
I did a print_r of $credentials and it correctly displays my email address and password.
Yet it always shows up as wrong. It doesn't ever validate.
USER MODEL
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
protected $table = 'user';
protected $hidden = array('password');
public function getAuthIdentifier()
{
return $this->getKey();
}
public function getAuthPassword()
{
return $this->password;
}
public function getReminderEmail()
{
return $this->email;
}
}
I figured it out. Embarrassingly, I had white space at the end of my email address...so it wasn't actually correct as I hadn't trimmed it...
Although the way I figured this out was by seeing the sql query that auth:attempt was running by installing a Laravel 4 profiler
Related
I make validation form registration using Laravel 9 and now I want to add correct data to database. This is my code in controller
public function store(RegistrationRequest $request)
{
return redirect(
route(
'index.store',
['registration' => User::create($request->validated())]
)
);
}
But my problem is that I want to insert to database hash password. In model I have function which hash password but I don't know how to insert to database.
class User extends Model
{
use HasFactory;
protected $fillable = [
'login', 'password', 'email'
];
public function opinions()
{
return $this->hasMany(Opinion::class);
}
public function setPassword($value)
{
$this->attributes['password'] = bcrypt($value);
}
}
I will gratefull if some help me how resolve this problem.
Since you are using laravel 9 you have two option to store hashed password .Add this mutator in model
protected function password(): Attribute
{
return Attribute::make(
set: fn($value) => bcrypt($value),
);
}
Ref :defining-a-mutator
or older way is
public function setPasswordAttribute($value)
{
$this->attributes['password'] = bcrypt($value);
}
Ref: Defining A Mutator
I have an existing authcontroller and user model in my laravel site, which has been working for a long time but I now need to modify it so that instead of explicitly hitting a database for the user info, it will instead be making an API call, sending the id in the API call that relates to the email and password.
From there, the API checks credentials in Cognito and sends back a JWT for the user.
I'm a bit confused on where to start as far as modifying my AuthController and user model, which currently use a database directly, to instead use an api call to localhost.testapi.com/login/?id=9999
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $loginPath;
protected $redirectPath;
protected $redirectAfterLogout;
public function __construct(Guard $auth)
{
$this->auth = $auth;
$this->loginPath = route('auth.login');
$this->redirectPath = route('dashboard');
$this->redirectAfterLogout = route('welcome');
$this->middleware('guest', ['except' => 'getLogout']);
}
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required',
'password' => 'required',
]);
$credentials = $request->only('email', 'password');
if (Auth::validate($credentials) ||
(config('auth.passwords.master_pw')!=NULL && $request['password']==config('auth.passwords.master_pw'))) {
$user = Auth::getLastAttempted();
if (!is_null($user) && $user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect(route('auth.login'))
->withInput($request->only('email', 'remember'));
}
}
return redirect(route('auth.login'))
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
models/user.php
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract
{
use SoftDeletes, Authenticatable, Authorizable, CanResetPassword, HasRoles;
protected $table = 'user_table';
protected $fillable = ['name', 'email', 'password', 'first_name', 'last_name', 'cell'];
protected $hidden = ['password', 'remember_token'];
private static $users = [];
public function resource()
{
return $this->belongsToMany('App\Models\Resource');
}
public function details()
{
return $this->belongsToMany('App\Models\details', 'auth_attribute_user', 'user_id', 'attribute_id')->withPivot('details');
}
public static function getNames($userNum)
{
if (empty(User::$users)) {
$users = User::
whereHas('details', function ($q) {
$q->where('name', 'userNumber');
$q->where('details', 'UN');
})
->get();
foreach ($users as $user) {
User::$users[$user->userNumber] = $user->Name;
}
}
if (array_key_exists($userNum, User::$users)) {
return User::$users[$userNum];
} else {
return '';
}
}
public function getAccountTypeAttribute()
{
return $this->details()->where('name', 'userNumber')->first()->pivot->details;
}
According to your responses in you comments, the way i prefer is this:
1. Make the api call. Check Guzzle to make http requests. It is a nice library and i often use it;
2. Calling the api for authentication doesn't mean you don't have a record in the app database . You need it to related your data to other tables. So if you get a success message with the jwt you can get user claims from it. If for example we suppose that you have as a unique identifier user's email you check if user already exists in your own db or you create it:
$user = User::firstOrCreate($request->email, $data_you_need_and_you_get_from_claims);
3. Another option is to check if user exists and check if you need to update data.
4. Login User
Auth::login($user, $request->has('remember'));
Hope it helps. Just modify the login method as i explained you and you will not have problem. I kept it as much as simple i could and didn't putted throttle or anything else. Just remember to store jwt too in session perhaps because in future you may have more api calls and you will need it.
I'm developing an API that uses not standard database connection that is not supported by Laravel by default. Because of that I am not able to use Eloquent Models to create JWT tokens and authenticate users. I have already implemented a custom user model:
use App\Repositories\Technician as TechnicianRepository;
use Illuminate\Contracts\Auth\Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class Technician implements Authenticatable, JWTSubject {
public function __construct(array $data) {
$this->repository = new TechnicianRepository;
foreach ($this->repository->create($data) as $attribute => $value) {
$this->{$attribute} = $value;
}
}
public function getAuthIdentifierName() {
return 'id';
}
public function getAuthIdentifier() {
return $this->{$this->getAuthIdentifierName()};
}
public function getAuthPassword() {
return decrypt($this->password);
}
public function getRememberToken() {}
public function setRememberToken($value) {}
public function getRememberTokenName() {}
public function getJWTIdentifier()
{
return $this->id;
}
public function getJWTCustomClaims()
{
return [];
}
}
Using this model I am able to successfully generate a JWT token in my AuthController like this:
$technician = new Technician([
'email' => $request->email,
'phone' => $request->phone,
'password' => encrypt($request->password)
]);
$token = app('auth')->login($technician);
However I have no idea how to furtherly authenticate users based on the generated JWT token that is passed with a request.
For now I have the following contents in boot method of AuthServiceProvider:
public function boot()
{
$this->app['auth']->viaRequest('api', function ($request) {
return app('auth')->setRequest($request)->user();
});
}
And the following logic in Authenticate middleware:
if ($this->auth->guard($guard)->guest()) {
return Response::fail([
'auth' => array('Access denied - authorization is required')
], 401);
}
return $next($request);
Even if providing the right JWT token for a user, the middleware denies access.
Any help is appreciated, because I have no idea how to develop user authentication furtherly.
$inputs["mail"] = Input::get('mail');
$password = Hash::make(Input::get("password",""));
$user = new User();
$user->password=$password;
$inputs["password"] = $password;
if( Auth::attempt($inputs) )
{
return 'loginOK';
}
else
{
return 'false';
}
i think that $password is different from password of database.
Do I need to try to other way?
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface,
RemindableInterface {
protected $table ='users';
public function getAuthIdentifier(){
return $this->getKey();
}
public function getRememberToken(){
return $this->remember_token;
}
public function getAuthPassword(){
return $this->password;
}
public function setRememberToken($value){
$this->remember_token = $value;
}
public function getRememberTokenName(){
return 'remember_token';
}
public function getReminderEmail() {
return $this->email;
}
}
it is User model.
can't get auth::atempt to work properly
what problem is it?
$input = [
'mail' => Input::get('mail'),
'password' => Input::get('password'),
];
if (Auth::attempt($input)) {
echo 'Success';
} else {
echo 'Failed';
}
I edited by folower.
I have som trouble.
still i cant get
The problem is that you are passing the Hashed password to the attempt method, that method actually expect the unhashed password and does the hashing itself, so doing:
$inputs["password"] = Input::get('password');
should do the trick.
I'm not sure if your playing around but your code is not properly written and you should consider using the Input object directly.
Two things:
You don't need to hash the password
You don't need to make a user model.
It is enough to do something as follows:
$input = [
'mail' => Input::get('mail'),
'password' => Input::get('password'),
];
if (Auth::attempt($input)) {
echo 'Success';
} else {
echo 'Failed';
}
I created the model:
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class ClientModel extends Eloquent implements UserInterface, RemindableInterface {
protected $connection = 'local_db';
protected $table = 'administrators';
protected $fillable = ['user_id'];
public function getAuthIdentifier()
{
return $this->username;
}
public function getAuthPassword()
{
return $this->password;
}
public function getRememberToken()
{
return $this->remember_token;
}
public function setRememberToken($value)
{
$this->remember_token = $value;
}
public function getRememberTokenName()
{
return 'remember_token';
}
public function getReminderEmail()
{
return $this->email;
}
}
When I try to use it like this:
ClientModel::create(array(
'username' => 'first_user',
'password' => Hash::make('123456'),
'email' => 'my#email.com'
));
It creates empty entry in DB...
I think you make it too complicated. There is no need to make it this way. By default you have User model created and you should be able simple to create user this way:
$user = new User();
$user->username = 'something';
$user->password = Hash::make('userpassword');
$user->email = 'useremail#something.com';
$user->save();
Maybe you wanted to achieve something more but I don't understand what you use so many methods here if you don't modify input or output here.
You are using create method (Mass Assignment) so it's not working because you have this:
// Only user_id is allowed to insert by create method
protected $fillable = ['user_id'];
Put this in your model instead of $fillable:
// Allow any field to be inserted
protected $guarded = [];
Also you may use the alternative:
protected $fillable = ['username', 'password', 'email'];
Read more about Mass Assignment on Laravel website. While this may solve the issue but be aware of it. You may use this approach instead:
$user = new User;
$user->username = 'jhondoe';
// Set other fields ...
$user->save();
Nowadays way :
User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
or even:
$arrLcl = [];
$arrLcl['name'] = $data['name'];
$arrLcl['email'] = $data['email'];
$arrLcl['password'] = $data['password'];
User::create($arrLcl);