I am trying to make Laravel using multiple guards - depending on the authentication type.
When I am authenticating via API, I would like to use jwt guard. When I am authenticating through web, I want to use session guard.
My config\auth.php looks like this:
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
//'hash' => false,
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
]
My routes/web.php looks like this:
Route::get('/', 'HomeController#index')->name('home');
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
My routes/api.php looks like this:
Route::post('login', 'AuthController#login');
Route::get('logout', 'AuthController#logout');
Route::post('refresh', 'AuthController#refresh');
Route::get('me', 'AuthController#me');
What I am getting is that API authentication works fine, while the web doesn't. I have debugged and it seems like it is always checking the jwt guard.
Can someone help me, how can I set the guard on a route if that is possible or on Auth::routes() call?
I have solved it by switching default to web routes.
Then I updated the code for app/Http/Controllers/AuthController.php to use the specific api auth wherever I was using the auth method:
auth('api')->attempt($validator->validated()) and 'expires_in' => auth('api')->factory()->getTTL() * 60
Related
I have created two guards.Admin and Manager. To create authentication for admin I have followed https://blog.pusher.com/laravel-jwt/ this blog and it worked well. For my 2nd guard authentication middleware route manager not working. It says Manager not found.So I put only admin in group route and for manager I have declared the guard inside of auth method but It still not working. It can't find my model to store so I had to post the row data inside phpmyadmin manually and checked the login if it works or not but it's still not working. Returns the error part.
Api.php
Route::post('/manager/register', [App\Http\Controllers\ManagerUserController::class,'register']);
Route::post('/manager/login', [App\Http\Controllers\ManagerUserController::class,'authenticate']);
Route::get('open', [ManagerDataController::class,'open']);
Route::group(['middleware' => ['jwt.verify']], function() {
Route::get('user', [ManagerUserController::class,'getAuthenticatedUser']);
Route::get('closed', [ManagerDataController::class,'closed']);
});
Route::group(['middleware'=>'admin'],function($router){
Route::post('/admin/register', [App\Http\Controllers\AdminUserController::class,'register']);
Route::post('/admin/login', [App\Http\Controllers\AdminUserController::class,'authenticate']);
Route::get('open', [AdminDataController::class,'open']);
Route::group(['middleware' => ['jwt.verify']], function() {
Route::get('user', [AdminUserController::class,'getAuthenticatedUser']);
Route::get('closed', [AdminDataController::class,'closed']);
});
managerController:
public function authenticate(Request $request)
{
$credentials = $request->only('username', 'password');
if (! $token = auth()->guard('manager')->attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 400);
}
return response()->json(compact('token'));
}
auth.php
'defaults' => [
'guard' => 'admin',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'jwt',
'provider' => 'admins',
],
'manager' => [
'driver' => 'jwt',
'provider' => 'managers',
],
]
Another problem is if I set web for default guard then admin guard not working but if I put admin as default guard then it works. It this work like this then how can I use multi jwt authentication cause theres only single default guard exists!
My laravel app has multiple route handlers including web, api, admin, and a new one that's misbehaving: "advisor".
The web, api, and admin routes all work as expected.
For the advisor routes POST requests work as expected, but GET calls return the client-app.blade.php html file. Not authorized or 404, just that html file.
I have the advisor routes added in the map function just like the web and api routes are:
protected function mapAdvisorRoutes()
{
Route::prefix('advisor')
->middleware('advisor')
->namespace($this->namespace)
->group(base_path('routes/advisor.php'));
}
The auth guards are setup as follows (AWS Cognito authentication is working properly on POST):
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
'advisor' => [
'driver' => 'cognito',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
]
],...
The issue is that the advisor GET calls are not executing the controllers or even middleware. advisor POST calls are authenticating and working as expected. Here are some example advisor routes:
Route::group(['prefix' => 'v1'], function () {
Route::group(['middleware' => 'auth:advisor'], function () {
Route::get('get-test', function () {
// ISSUE: is not returned
return 'advisors get test';
});
Route::post('post-test', function () {
return 'advisors post test - works as expected';
});
});});
My client-side app is sending the auth and accept headers - Authorization: Bearer {token} and Accept: "application/json"
Any idea what would cause the response to an api call to be the client-app.blade.php file?
Or why would laravel treat the POST vs GET calls differently?
Thanks!
As is often the case, writing out the problem helped me realize what was causing the problem.
The order of route mapping in RouteServiceProvider.php matters.
Changing this:
$this->mapApiRoutes();
$this->mapWebRoutes();
$this->mapAdvisorRoutes();
to this solved the problem:
$this->mapApiRoutes();
$this->mapAdvisorRoutes();
$this->mapWebRoutes();
The following line in web.php was causing the index or client-app.blade.php file to be returned.
Route::get('/{any}', 'ClientAppController#index')->where('any', '.*');
So my /advisor GET request was never getting to the advisor route logic.
Phew!
I am using laravel 5.6. I tried to use JWT. That's why I made some modification followed by https://jwt-auth.readthedocs.io/en/develop/quick-start/ . Now jwt is working properly.I checked it by postman. But when I try to use laravel basic login with email and password it does not work. Thanks in advance
I also made change on
'defaults' => [
'guard' => 'api',
'passwords' => 'users',
],
...
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
is because you are telling laravel to use jwt as driver and the laravel basic login use session as driver, if you want to have both you may need to put this
'web' => [
'driver' => 'session',
'provider' => 'users',
],
and especify the guard that you will use for the login
if (Auth::guard('web')->attempt($credentials)) {
//
}
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.