I'm new to Laravel and i'm getting this error: Call to undefined method App\Models\User::createToken()
Laravel Framework 8.34.0
PHP 7.4.3
My Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
class UserController extends Controller
{
private $sucess_status = 200;
public function createUser(Request $request){
$validator = Validator::make($request->all(),
[
'first_name' => 'required',
'last_name' => 'required',
'phone' => 'required|numeric',
'email' => 'required|email',
'password' => 'required|alpha_num|min:5'
]
);
if($validator->fails()){
return response()->json(["validattion_errors"=>$validator->errors()]);
}
$dataArray = array(
"first_name"=>$request->first_name,
"last_name"=>$request->last_name,
"full_name"=>$request->first_name . " " . $request->last_name,
"phone"=>$request->phone,
"email"=>$request->email,
"password"=>bcrypt($request->password),
);
$user = User::create($dataArray);
if(!is_null($user)){
return response()->json(["status" => $this->sucess_status, "success" => true, "data" => $user]);
}else {
return response()->json(["status" => "failed", "success" => false, "message" => "User not created"]);
}
}
public function userLogin(Request $request){
$validator = Validator::make($request->all(),
[
'email' => 'required|email',
'password' => 'required|alpha_num|min:5'
]
);
if($validator->fails()){
return response()->json(["validation_errors"=>$validator->errors()]);
}
if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){
$user = Auth::user();
$token = $user->createToken('token')->accessToken;
return response()->json(["status" => $this->sucess_status, "success" => true, "login" => true, "token" => $token, "data" => $user]);
} else{
return response()->json(["status" => "failed", "success" => false, "message" => "Invalid email or password"]);
}
}
public function userDetail(){
$user = Auth::user();
if(!is_null($user)){
return response()->json(["status" => $this->sucess_status, "success" => true, "user" => $user]);
}else {
return response()->json(["status" => "failed", "success" => false, "message" => "No user found"]);
}
}
}
My Auth.php:
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
I had run the php artisan passport: install command 3 times
because I forgot to save the file with the settings and I thought it would be necessary to run the code again after saving the file
And returned me this:
Encryption keys already exist. Use the --force option to overwrite them.
Personal access client created successfully.
Client ID: 3
Client secret: JoZbAGCSOZ6t0hn7YnnT6PdN4EMUUZa7H1vU6Sk2
Password grant client created successfully.
Client ID: 4
Client secret: yAxjrBnvPWCiAdXod5FmJDQTNDmneRoO1LtM6B0x
cristiansto in Laravel/API/todoList
❯ php artisan passport:install --force
Encryption keys generated successfully.
Personal access client created successfully.
Client ID: 5
Client secret: 8CtWyvXIwapZnfO5dTGDsyF0iXvJsxNyiZeUksTL
Password grant client created successfully.
Client ID: 6
Client secret: 9jThPxOfgNxJINFKIbDz0WU5yYEup0pIkboEJLr0
cristiansto in Laravel/API/todoList
I dont know if this is the cause.
What could it be?
the method createToken is in HasApiTokens trait, you should use it In your User Model
:
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens;
}
I discovered the issue, i had to put
use Laravel\Passport\HasApiTokens; inside the User.php
and then
use HasFactory, Notifiable, HasApiTokens;
It works on me
Laravel Framework 8.83.5
PHP 7.4.19
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
....
}
HasFactory and Notifiable are default User Model, just add HasApiTokens so it becomes:
use HasApiTokens, HasFactory, Notifiable;
Related
Greetings to all I have a problem with my Laravel 8 code I'm getting
"ErrorException Undefined index: password" from vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php:159
I use custom model and I set up in config/auth.php to use my Client model not a User model and when I try Auth::attempt($credentials) it's failed and give me that error here is my code
Client.php Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Client extends Authenticatable
{
use HasFactory;
protected $table = 'clients';
protected $primaryKey = 'client_id';
public $incrementing = true;
protected $fillable = ['client_firstName', 'client_lastName', 'client_email', 'client_phoneNumber', 'client_password', 'client_isAdmin', 'client_created_at', 'client_updated_at'];
public $timestamps = true;
const CREATED_AT = 'client_created_at';
const UPDATED_AT = 'client_updated_at';
}
config/auth.php
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
ClientController.php
public function signIn(Request $request){
if($request->isMethod('POST')){
$validator = Validator::make($request->all(), [
'signin_email' => 'required|string|email:rfc,dns|bail',
'signin_password' => 'required|string|bail',
], [
'signin_email.required' => 'The email address field is required.',
'signin_email.email' => 'You must provide an a valid email address.',
'signin_password.required' => 'The password field is required.',
]);
if($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}else{
$credentials = [
'client_email' => $request->signin_email,
'client_password' => $request->signin_password,
];
if(Auth::attempt($credentials)) {
return redirect()->to('dashboard');
}else{
return redirect()->back()->withErrors("Sorry, the passed email address or password is incorrect, try again!")->withInput();
}
}
}else{
return view('signIn');
}
}
I have found a solution I will need to add to my model getAuthPassword, also I need to change app/auth.php and ClientController.php
Client.php Model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Client extends Authenticatable
{
use HasFactory;
protected $table = 'clients';
protected $primaryKey = 'client_id';
public $incrementing = true;
protected $fillable = ['client_firstName', 'client_lastName', 'client_email', 'client_phoneNumber', 'client_password', 'client_isAdmin', 'client_created_at', 'client_updated_at'];
public $timestamps = true;
const CREATED_AT = 'client_created_at';
const UPDATED_AT = 'client_updated_at';
public function getAuthPassword(){
return $this->client_password;
}
}
app/auth.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'clients',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'clients',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'clients' => [
'driver' => 'eloquent',
'model' => App\Models\Client::class,
'table' => 'clients',
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'clients' => [
'provider' => 'clients',
'table' => 'clients',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
ClientController.php
public function signIn(Request $request){
if($request->isMethod('POST')){
$validator = Validator::make($request->all(), [
'signin_email' => 'required|string|email:rfc,dns|bail',
'signin_password' => 'required|string|bail',
], [
'signin_email.required' => 'The email address field is required.',
'signin_email.email' => 'You must provide an a valid email address.',
'signin_password.required' => 'The password field is required.',
]);
if($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}else{
$credentials = [
'client_email' => $request->signin_email,
'password' => $request->signin_password,
];
if(Auth::attempt($credentials)) {
return redirect()->to('dashboard');
}else{
return redirect()->back()->withErrors("Sorry, the passed email address or password is incorrect, try again!")->withInput();
}
}
}else{
return view('signIn');
}
}
I try to make login using Auth, its work seems fine but when I check the stored/logged-in data user is different.
here's the code in authController
public function auth(Request $request)
{
$rules = [
'username' => 'required|string',
'password' => 'required|string'
];
$msg = [
'username.required' => 'wajib isi username',
'username.string' => 'not username',
'password.required' => 'wajib isi password',
'password.string' => 'string password',
];
$validator = Validator::make($request->all(), $rules, $msg);
if($validator->fails()){
return redirect()->back()->withErrors($validator)->withInput($request->all());
}
$data = [
'userid' => $request['username'],
'password' => $request['password']
];
Auth::attempt($data);
if(Auth::check()){
dd(Auth::user());
return redirect('dashboard');
}else{
Session::flash('error', 'ada yang salah ops!');
// return redirect('login');
}
}
when I 'dd(Auth::user());' after Auth::check() the data is correct, example
Then I check it on the dashboard page with the following code in adminController
public function dashboard()
{
dd(Auth::user());
return view('admin/masterdata/blank');
}
It's given me this result
and here's my User model look like
class User extends Authenticatable
{
protected $table = 'tbl_user';
protected $primaryKey = 'userid';
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'nama', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
UPDATE
and here is my config/auth.php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/
'password_timeout' => 10800,
];
Is the words users in config/auth.php mean the users model?
Is something wrong with my code or something I miss?
Thanks in advance.
try this other way as you have userid and password to check for login
use Illuminate\Support\Facades\Hash;
public function auth(Request $request)
{
$rules = [
'username' => 'required|string',
'password' => 'required|string'
];
$msg = [
'username.required' => 'wajib isi username',
'username.string' => 'not username',
'password.required' => 'wajib isi password',
'password.string' => 'string password',
];
$validator = Validator::make($request->all(), $rules, $msg);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput($request->all());
}
$user = User::where('userid', $request['username'])->first();
if (!$user) {
return redirect()->with('error', 'user not found.');
}
if (Hash::check($request['password'],$user->password);) {
auth()->login($user);
return redirect('dashboard');
} else {
Session::flash('error', 'ada yang salah ops!');
}
}
then try in adminController.php
public function dashboard()
{
dd(Auth::user());
return view('admin/masterdata/blank');
}
here i used auth()->login($user); to login valid user
For some reasons I getting error on downloadHistorys() relationship method OneToMany:
My models User and DumpDownloadHistory:
<?php
namespace App\Models;
use App\Models\DumpDownloadHistory;
use App\Models\Groups;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
protected $fillable = ['email', 'full_name', 'name', 'mobile', 'phone', 'fax', 'downloadPrice', 'tokens', 'dailyDownloads', 'added_by', 'groups_id', 'status', 'user_about','admin_note', 'password', 'last_access', 'last_ip'];
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function downloadHistorys(){
return $this->hasMany(DumpDownloadHistory::class);
}
}
<?php
namespace App\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
class DumpDownloadHistory extends Model
{
protected $fillable = ['user_id', 'dataset', 'user_ip', 'downloadCost'];
protected $table = 'dump_download_histories';
protected $primaryKey = 'id';
public function user(){
return $this->belongsTo(User::class);
}
}
My models are placed in App\Models folder. I added my models instance to the controller. I getting an error when I try to call my methods. Any help will be helpful.
auth()->user()->downloadHistorys()->create([
'user_id' => auth()->user()->id,
'dataset' => $id,
'user_ip'=> request()->ip(),
'downloadCost' => auth()->user()->downloadPrice
]);
P.S. I not using a schema builder for the database. I have connected to an existing MySQL database.
Edited
config/auth.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false,
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];
Looks like
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
this section is wrong. If you want to use App\Models\User model as your authentication, change model to App\Models\User.
And change your App\Models\User model like this
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable {}
I'm trying to implement Laravel passport for two tables, so one would be default User and second one would be for Devices.
I created in the config the Guard for the new model and if I try to register the devices its writing to the Device table everything but, right now if I try to login it gives me this error:
Symfony\Component\Debug\Exception\FatalThrowableError: Argument 2 passed to Illuminate\Auth\SessionGuard::__construct() must implement interface Illuminate\Contracts\Auth\UserProvider, null given, called in /Users/petarceho/laravel/api/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php on line 127 in file /Users/petarceho/laravel/api/vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php on line 99
I'm new to Laravel so sorry for not able to explain it well, but can I use Laravel passport for two tables.
Here is my Controller class for Devices :
<?php
namespace App\Http\Controllers;
use App\Device;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class DeviceController extends Controller{
//register
public function signupDevice(Request $request)
{
//cant registed with the same email twice
if(sizeof(Device::where('name','=',$request->query('name'))->get()) > 0)
return response()->json(['name has already been taken'],500);
$request->validate([
'name' => 'required|string',
'password' => 'required|string|confirmed']);
$device =new Device(
[
'name'=>$request->name,
'password'=>bcrypt($request->password)
]);
$device->save();
return response()->json([
'message' => 'Successfully created device!'
], 201);
}
public function login(Request $request)
{
if (Auth::guard('device')->attempt(['name' => request(['name']), 'password' => request(['password'])])) {
$details = Auth::guard('device')->user();
$user = $details['original'];
return $user;}
else {return 'auth fail';}
}
public function login1(Request $request){
//validate the data input
$request->validate([
'name' => 'required|string', // |string|name
'password' => 'required|string',
// 'remember_me' => 'boolean'
]);
$credentials = request(['name', 'password']);
if(!Auth::attempt($credentials))
return response()->json([
'message' => 'Unauthorized'
], 401);
$device = $request->user('device');
// $device = Auth::guard('device')->device();
$tokenResult = $device->createToken('Personal Access Token');
$token = $tokenResult->token;
if ($request->remember_me)
$token->expires_at = Carbon::now()->addWeeks(1);
$token->save();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse(
$tokenResult->token->expires_at
)->toDateTimeString()
],200);
}
}
Here is my config auth.php file.
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
'hash' => false,
],
'device'=>
[
'driver'=>'session',
// 'model'=>App\Device::class,
'provider'=>'devices',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
'devices' => [
'driver' => 'eloquent',
'model' => App\Device::class,
],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
],
],
];
and my routes:
//routes for device auth
Route::group(
[
'prefix'=>'auth/device'
],function ()
{
Route::post('signup','DeviceController#signupDevice');
Route::post('login','DeviceController#login');
});
the App/Device class
the Illuminate\Foundation\Auth\Device looks exactly like User class
<?php
namespace App;
use Illuminate\Foundation\Auth\Device as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
class Device extends Authenticatable{
use Notifiable;//,HasApiTokens;
protected $table ='device';
protected $fillable = [
'name', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
Any idea how to use Laravel passport for Multi auth authentication for two tables ?
I want to add a custom guard to Laravel that uses Passport but with different model (not User), but when I try to set the user for this guard it is not working.
config/auth.php:
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
'conference' => [
'driver' => 'passport',
'provider' => 'participants',
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'participants' => [
'driver' => 'eloquent',
'model' => App\Models\Participant::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| Here you may set the options for resetting passwords including the view
| that is your password reset e-mail. You may also set the name of the
| table that maintains all of the reset tokens for your application.
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'email' => 'spark::auth.emails.password',
'table' => 'password_resets',
'expire' => 60,
],
],
];
in the controller I am setting the user for the custom guard:
auth()->guard('conference')->setUser($participant);
api.php:
Route::group(['prefix' => '{activity}', 'middleware' => ['auth:conference', 'api']], function () { //
Route::group(['prefix' => 'participant/{participant}'], function () {
Route::any('join', 'API\ConferenceController#join');
});
});
Participant model:
use Laravel\Passport\HasApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Participant extends Authenticatable
{
use Enums, SoftDeletes, RequiresUUID, HasApiTokens, Notifiable;
but I can't access the route I get 401. When I change the provider for the 'conference' guard to be 'users' it works without problem.
What I am missing?
This might help:
My AdminAPI Url: https://example.com/api/login
My Customer API Url: https://example.com/api.customer/login
adding this to any ServiceProvider (I have added in RouteServiceProvider.php before custom route)
// Fix/Support for multiple user with different table by changing provider on api.customer circumstances
Config::set('auth.guards.api.provider', request()->input('provider', starts_with(request()->path(), 'api.customer') ? 'customers' : 'users'));`
and must add your custom provider in providers array in config/auth.php
'customers' => [
'driver' => 'eloquent',
'model' => App\Customer::class,
],
If you just only change User model to 'participants' you can replace provider to 'participants' in api. Multi auth I found a temporary solution, idea comes from https://github.com/laravel/passport/issues/161
and http://esbenp.github.io/2017/03/19/modern-rest-api-laravel-part-4/
Laravel\Passport\Brigde\UserRepository.php file add:
public function getEntityByUserCredentials($username, $password, $grantType, ClientEntityInterface $clientEntity, $provider) {
$provider = config('auth.guards.' . $provider . '.provider');
if (is_null($model = config('auth.providers.' . $provider . '.model'))) {
throw new RuntimeException('Unable to determine authentication model from configuration.');
}
if (method_exists($model, 'findForPassport')) {
$user = (new $model)->findForPassport($username);
} else {
$user = (new $model)->where('email', $username)->first();
}
if (!$user) {
return;
} elseif (method_exists($user, 'validateForPassportPasswordGrant')) {
if (!$user->validateForPassportPasswordGrant($password)) {
return;
}
} elseif (!$this->hasher->check($password, $user->getAuthPassword())) {
return;
}
return new User($user->getAuthIdentifier());
}
League\OAuth2\Server\Grant\PasswordGrant.php 78 line add
$provider = $this->getRequestParameter('provider', $request);
and 94 line add $provider, like:
$user = $this->userRepository->getEntityByUserCredentials(
$username,
$password,
$this->getIdentifier(),
$client,
$provider
);
Write LoginProxy(in fact it should be receive different Model in constructor ) like:
class LoginProxy {
const REFRESH_TOKEN = 'refreshToken';
private $client;
private $user;
public function __construct(User $user, Client $client) {
$this->user = $user;
$this->client = $client;
}
public function attemptLogin($mobile, $password) {
$user = $this->user->where('mobile', $mobile)->first();
if (!is_null($user)) {
return $this->proxy('password', [
'username' => $mobile,
'password' => $password,
]);
}
return response()->json('error for 401', 401);
}
public function attemptRefresh() {
$refreshToken = $this->request->cookie(self::REFRESH_TOKEN);
return $this->proxy('refresh_token', [
'refresh_token' => $refreshToken,
]);
}
public function proxy($grant_type, array $data = []) {
$data = array_merge($data, [
'client_id' => env('PASSWORD_CLIENT_ID'),
'client_secret' => env('PASSWORD_CLIENT_SECRET'),
'grant_type' => $grant_type,
'scope' => '*',
]);
$response = $this->client->post(url('/oauth/token'), [
'form_params' => $data,
]);
$data = json_decode($response->getBody()->getContents());
return response()->json([
'token_type' => $data->token_type,
'access_token' => $data->access_token,
'refresh_token' => $data->refresh_token,
'expires_in' => $data->expires_in,
], 200);
}
public function logout() {
$accessToken = $this->auth->user()->token();
$refreshToken = $this->db
->table('oauth_refresh_tokens')
->where('access_token_id', $accessToken->id)
->update([
'revoked' => true,
]);
$accessToken->revoke();
}
}
in your LoginController, call certain method:
class LoginController extends Controller {
private $loginProxy;
public function __construct(LoginProxy $loginProxy) {
$this->loginProxy = $loginProxy;
}
public function login(LoginRequest $request) {
$mobile = $request->get('mobile');
$password = $request->get('password');
$provider = $request->get('provider');
return $this->loginProxy->attemptLogin($mobile, $password, $provider);
}
public function refresh(Request $request) {
return $this->response($this->loginProxy->attemptRefresh());
}
public function logout() {
$this->loginProxy->logout();
return $this->response(null, 204);
}
Now you can post different provider params to it.