I have configured passport authentication for my model 'Member'(members table).Access token created perfectly while login.But i could not authenticate after login apis.
i am getting below error
BadMethodCallException.Call to undefined method Illuminate\Database\Query\Builder::getAuthIdentifierName()
i thing you forgot to put auth:api middleware in routes.
please use authentication middleware like
Route::group(array('middleware' => ['auth:api']), function() {
//your routes;
});
Passport by default uses User model and here you are using Member table. Just check if you have included Model class inside the auth.php file inside config folder.
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Member::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
Or try this https://github.com/santigarcor/laratrust/issues/134#issuecomment-300318982
Related
As I understand it, Passport is used to implement OAuth 2.0 standard support, and as I see it, OAuth 2.0 is an authorization technology and not authentication.
So before authorizing a user to do something, firstly I need to authenticate them. Is there a way for Passport to authenticate a user, or I should use some other means of user authentication? E.g I want to authenticate a user with login and password.
Edit:
I'm a little bit confused by the documentation. It's said:
Passport includes an authentication guard that will validate access tokens on incoming requests. Once you have configured the api guard to use the passport driver, you only need to specify the auth:api middleware on any routes that require a valid access token.
So it means that Passport utilizes guards not to authenticate users but to validate access tokens on routes where these tokens are required. Did I get that right?
Yes, you can use passport tokens for authentication. Make a token for a user and send it as response when a user login. Then apply that authentication to all the routes of that user using laravel guards.(Make sure your model extends Authenticatable and use HasApiTokens) An example for guardians is given below.
In auth.php do the following:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'guardians' => [
'driver' => 'passport',
'provider' => 'guardians',
'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'guardians' => [
'driver' => 'eloquent',
'model' => App\Models\Guardian::class,
],
],
In AuthServiceProvider do this:
public function boot()
{
$this->registerPolicies();
//token will expire in one day
Passport::personalAccessTokensExpireIn(Carbon::now()->addDays(1));
Passport::routes();
}
Then in api.php do this to all the routes you want to authenticate.
Route::group(['middleware' => 'auth:guardians'], function () {
Route::post('/parent', [ParentController::class, 'parentsList'])
->name('parentsList');
});
Your controller code will be like:
$guardian = Guardian::where('email', $request->email)->first();
if (Hash::check($request->password, $guardian->password)) {
//passport package implement here...
$token = $guardian->createToken('Laravel Password Grant Client')->accessToken;
$data=['guardian'=> $guardian, 'token'=> $token];
return Response::json($data,200);
}
else {
$data=['error' => 'Mobile Number/Email or Password entered is incorrect.'];
return Response::json($data, 422);
}
I need to authenticate my web routes and I decided to use this middleware:
Route::group(['middleware' => ['auth:api']], function () {
Route::get('test', 'MainController#home');
Route::get('test1', 'MainController#home1');
});
I edited config/auth.php file to use my guard:
....
'guards' => [
'web' => [
'driver' => 'oauth2',
'provider' => 'users',
],
'api' => [
'driver' => 'oauth2',
'provider' => 'users',
'hash' => false,
],
],
...
I defined oauth2 in the AuthServiceProvider file like this:
Auth::extend('oauth2', function ($app, $name, array $config) {
// Return an instance of Illuminate\Contracts\Auth\Guard ...
return new OAuth2Guard(app(TokenUserProvider::class), $app->make('request'));
});
This code works well. The auth:api middleware is executed and the user is checked.
Now since I need the sessions I wanted to use auth:web middleware, with the same exact code. But If I use it the user is nomore authenticated and he is redirected to the login page.
I do not know why. Both web and api guards use the same driver.
Laravel provide separate file for API routes routes/api.php you can separate web and api routes routes. all API routes will be prefixed with "api". After separating routes just include 'web' middle-ware
I have got a file called
AuthServiceProvider.php
in the Providers directory in Laravel project.
I actually don't understand about how it works and why it's needed
Can anyone explain with details?
Thanks in advance.
AuthServiceProvider is the default guard that Laravel uses to give the service authentication in the system. But if you need you can make your own guards for specific situations, in that case you will have you own AuthServiceProvider.
For eg. In one system that we made, the customer had his own database with it's specific users table, we can't use the default Laraver AuthServiceProvider. Because the table have other fields. So we created our CustomAuthProvider. It's complex, but you need to declare the driver en config/auth.php
...
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
'provider' => 'custom' // Our custom driver
],
...
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'custom', // Our custom driver
],
...
],
...
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => Modules\Pickandroll\Entities\User::class,
],
'custom' => [
'driver' => 'pickandrolluser', //Our Custom Auth Provider
'model' => Modules\Pickandroll\Entities\User::class,
]
],
and the custom module provider we register our custom auth provider
public function register()
{
Auth::provider('pickandrolluser', function ($app, array $config) {
return new PickandrollUserProvider($config['model']);
});
}
and the class PickandrollUserProvider that extends use Illuminate\Contracts\Auth\UserProvider;
I know it's complex but maybe it helps to understand this topic
I am trying to implement oath2 using laravel and passport. however i have managed to make everything up & running. But the problem i am facing is when token expires or without token the url redirects to the laravels login page. I was expecting an unauthorized error message with a status code 401.
oauth2 is implemented using passport. I think laravels default auth is creating the problem.
this is my code in routes
Route::group(['middleware' => 'auth:api'], function () {
Route::get('users', "\App\Http\Controllers\UserController#getUsers");
Route::post('permission/add', "\App\Http\Controllers\UserController#createPermission");
Route::get('permissions', "\App\Http\Controllers\UserController#getPermissions");
Route::get('permission/{param}', "\App\Http\Controllers\UserController#getPermission");
Route::post('role/add', "\App\Http\Controllers\UserController#createRole");
Route::get('roles', "\App\Http\Controllers\UserController#getRoles");
Route::get('user/profile', function () {
// Uses Auth Middleware
});
});
My output when unauthorized
my config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Please, can anybody explain how to implement multiple authentication guards in Lumen framework? Currently, I have two authenticatable models: Users and Clients. I'm using a custom implementation of JWT. A User has client_id and user_id fields in their token payload. While a Client only has client_id. Based on this I need to determine who came to me: client, user or guest (without a token).
auth.php
'guards' => [
'client' => [
'driver' => 'token',
'provider' => 'clients',
],
'user' => [
'driver' => 'token',
'provider' => 'users',
],
],
'providers' => [
'clients' => [
'driver' => 'eloquent',
'model' => App\Client::class,
],
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
AuthServiceProvider.php
public function boot()
{
$this->app['auth']->viaRequest('token', function ($request) {
$access_token = HelperClass::getTokenFromHeader($request->headers->get('Authorization'));
if ($access_token) {
$tokendata = JWT::decode($access_token, getenv('TOKEN_SECRET'), array('HS256'));
if ($tokendata->user_id) {
return User::find($tokendata->user_id);
}
return Client::find($tokendata->client_id);
}
});
}
routes.php
$app->get('/api/{item_id:\d+}', ['middleware' => 'auth:user', 'uses' => 'App\Http\Controllers\ItemController#get']);
I want to allow only Users to access this route, but Clients successfully pass this middleware too: Auth::check() returns true and Auth::user() returns an instance of App\Client 😕
Another situation: what if for some routes I want to allow both: clients and users. For another routes - guests, clients and users.