0
votes

I'm using Laravel passport for API authentication, with api provider 'user' and web provider 'admin'. However, my API login URL keeps using the default provider for web instead of its own provider.

config/auth.php:

'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'admin',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'user',
            'hash' => 'false',
        ],
    ],


'providers' => [
        'admin' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],

        'user' => [
           'driver' => 'eloquent',
           'model' => App\Models\User::class,
         ],
    ],

User Model:

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
  
  use \App\Http\Traits\UsesUuid, HasApiTokens,Notifiable;
  
  protected $table = 'user';
  protected $primaryKey = 'user_id';

  protected $fillable =
   ['user_id',
   'user_fname',
   'user_lname',
   'user_email',
   'password',
   'user_contact',
   'user_token' ];

   protected $hidden = [
    'password', 'remember_token',
  ];

  protected $casts = [
    'email_verified_at' => 'datetime',
  ];

  public function setPasswordAttribute($password)
  {
      $this->attributes['password'] = bcrypt($password);
  }


}

Admin Model:

<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class Admin extends Authenticatable
{
    use Notifiable;

  protected $table = 'admin';
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password',
    ];


    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime'
    ];
    
}

API Auth Controller:

public function login(Request $request){

      $credentials = request(['user_email', 'password']);
      
      if(!auth()->attempt($credentials)){
        return response()->json([
          "message"=>"Invalid credentials"
        ], 201);
      }

      $accessToken = auth()->user()->createToken('authToken')->accessToken;

        return response()->json([
          "message"=>"Login successful",
          "user"=>auth()->user(),
          "access_token"=>$accessToken
        ], 201);

    }

Login route:

Route::post('/login', 'AuthController@login');

My error is the login route uses the default Admin model instead of the User model specified for the API provider giving me this error:

Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'user_email' in 'where clause' (SQL: select * from `admin` where `user_email` = [email protected] limit 1) 

I have seen a similar error here https://laracasts.com/discuss/channels/laravel/changing-the-model-provider-laravel-passport-authenticates-against and tried the fixes suggested here https://github.com/laravel/passport/issues/161#issuecomment-299690583 but they do not work

1
your web guard set to 'provider' => 'admin', that's whyKamlesh Paul
How do I make the api use the 'user' guard assigned to it instead of the 'admin' guard assigned to web?Piwan Samalie
i have added answer please take a lookKamlesh Paul

1 Answers

1
votes

you need to create a user guard as you need users table session driver to call attempt() function

config/auth.php:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'admin',
    ],
    'user' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport',
        'provider' => 'user',
        'hash' => 'false',
    ],
],

then your code should be like this

public function login(Request $request)
{

    $credentials = request(['user_email', 'password']);

    if (!auth()->guard('user')->attempt($credentials)) {
        return response()->json([
            "message" => "Invalid credentials"
        ], 201);
    }

    $accessToken = auth()->guard('user')->user()->createToken('authToken')->accessToken;

    return response()->json([
        "message" => "Login successful",
        "user" => auth()->user(),
        "access_token" => $accessToken
    ], 201);
}

NOTE:- we create new guard because passport driver not allow to use attempt() and web guard you have set admin table so