Laravel api authenication not working - laravel

I am attempting to use authentication for application through api, but when I set the guard in middleware it does not work and returns 403 exception.
I have this route guard in controller constructor:
public function __construct()
{
$this->middleware('auth:api');
}
Anytime I use Auth::user() the 403 is returned. Is something being missed?

For using Auth::user() make sure your routes are protected by api midlleware()
For using a user u can specify
Auth::gaurd('api')->user();
Hope this helps

Related

Route type delete does not work in Laravel

I have following route and works
Route::post("delete-role", [RoleApiController::class, "Remove"]);
I tested it through postman like this
http://localhost/delete-role?api_token=hcvhjbhjb12khjbjhc876
Now, if I change above route and convert to type delete..
Route::delete("delete-role/{role_id}", [RoleApiController::class, "Remove"]);
it does not work. I get below error. It seems to be the reason that the api_token is missing.
I get same error when trying to update route like below
Route::delete("delete-role/{role_id}/{api_token}", [RoleApiController::class, "Remove"]);
You have to set header of your request as:
"Accept": "application/json"
in postman.
If you don't set the required header for api, Laravel Passport can't understand request as an API client and so it will redirect to a /login page for the web.
Or you can set a middleware to check it in code:
public function handle($request, Closure $next)
{
if(!in_array($request->headers->get('accept'), ['application/json', 'Application/Json']))
return response()->json(['message' => 'Unauthenticated.'], 401);
return $next($request);
}
You have an incomplete details. but I see few issues here.
You seem to be using web routes for your API requests which is a bad set-up
You do not have a route with login name.
based on the error you posted, your request seems to successfully destroyed the token and logged you out, then called the middleware App\Http\Middleware\Authenticate which supposed to redirect your request to login route which does not exist and the reason you are getting that error.
You can see from that Authenticate middleware it will supposed to redirect you to login route for unauthenticated request. thats why you need to use the api routes so you can handle the response manually
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* #param \Illuminate\Http\Request $request
* #return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return route('login');
}
}
}
Also, I'm not so sure about this, but the reason you are not getting the same issue with your POST request is probably because your POST request does not call the Authenticate middleware or whatever in your routes file or class function that calls the authenticate middleware.
But again, just use api routes if you don't want un-authenticated request to automatically redirect your request to login routes which does not exist in your application
The problem is that he doesn't define route ('login'),
add in Exceptions/Handler.php
$this->renderable(function (AuthenticationException $e, $request) {
if ($request->is('api/*')) {
return response()->json(['meassge' => 'Unauthenticated']);
}
});
Then you should use Passport Or Sanctum for auth with Api,
Continue from here https://laravel.com/docs/9.x/passport
Probably, this thread could help you. Route [login] not defined
(OR)
You need to setup auth scaffolding to get login route defined.
Important: your project will be overridden if you setup auth scaffold.
So, I would only recommend doing this if it is a new project or a testing app.
See this for detail doc but install Laravel Breeze would be suffice.
It Appears you have called route('login') without having defined it in your routes, Please remove route('login') from your code or define it in your routes. eg::
Route::get('login', [YourController::class, 'methodName'])->name('login');

Laravel policy always returns 403

so I made a policy and whatever I do the Web page returns 403. im very new to laravel so most likely im missing something :)
I made a model by
php artisan make:model exercise | (I know I'm supposed to capitalize models but it was a typo)
Controller:
php artisan make:controller ExercisesController
Policy:
php artisan make:policy ExercisePolicy -m exercise
I registered policy in AuthServiceProvider.php (Also tried as 'App\Models\exercise'=>'App\Policies\ExercisePolicy'):
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
exercise::class => ExercisePolicy::class,
];
In ExercisesController.php this is the function in which I use authentication:
public function create(\App\Models\User $user)
{
$this->authorize('create', $user);
return view('exercises/create');
}
And in policy this is how my create function looks like
public function create(User $user)
{
return $user->admin == true;
}
The route:
Route::get('/exercises/create', [App\Http\Controllers\ExercisesController::class, 'create']);
I tried putting die("Policy is called); and trying to just return true from the policy create function to check if it gets to that but it still returned 403 , at this point I'm pretty sure that the policy itself is not being called as it also returns 403 on default
If anyone could help thanks in advance!
The call to authorize is using the second argument to figure out what Policy to use. Since the second argument is $user it would be looking for a Policy for the User model which you have not defined. To use the Policy for the exercise model you would have to pass the class name so it would know what Policy to use:
$this->authorize('create', exercise::class);
Though you should correct your typo and rename the exercise.php file to Exercise.php and the classname to Exercise.
Laravel 8.x Docs - Authorization - Writing Policies - Methods without Models
Laravel 8.x Docs - Authorization - Authorization Actions using Policies - Via Controller Helpers - Actions That Don't Require Models
I had this same issue and what I learnt was that Policies would work only on authenticated route.
Make sure your request is authenticated while implementing policies.

Testing Laravel Sanctum acting as results in bad method call

I'm trying to test an authenticated API route which only an authenticated user can post to a specific route.
Looking at the Laravel Sanctum docs, I can use the code below to create and authenticate a user:
Sanctum::actingAs(
factory(User::class)->create(),
['*']
);
When I try replicate this, I get an error running the test
BadMethodCallException: Call to undefined method App\User::withAccessToken()
My test code is as follows:
public function an_authenticated_user_can_add_a_client()
{
$user = Sanctum::actingAs(
factory(User::class)->create(),
['*']
);
dd($user);
// $this->post('/api/clients', $this->data());
}
api.php
Route::middleware('auth:sanctum')->group(function () {
//Clients
Route::get('/clients/{client}','ContactsController#show');
Route::post('/clients','ContactsController#store');
Route::patch('/clients/{client}','ContactsController#update');
Route::delete('/clients/{client}','ContactsController#destroy');
});
I don't have the method withAccessToken() in my User class and can't see where this method is coming from or specified anywhere.
Any help would be greatly appreciated.
Laravel Sanctum for SPA uses normal session authentication so the default actingAs method works fine. The actingAs method in Sanctum is meant to use for api tokens. Hope it helps.
Your User model is missing the HasApiTokens trait, that gives the function you are missing to the User model. Also described in the documentation, under the section Issuing API Tokens.
use Laravel\Sanctum\HasApiTokens;
class User {
use HasApiTokens;
}

having anonymous user on laravel

I'm using Laravel 5.8. And I have created a custom Guard that is using jwt. That I use as a middleware for authenticating users.
I have some routes that need to have different responses based on being an authenticated user or an unauthenticated user. what do you suggest me to do? what is the best practices to implement this?
I can define a custom guard which its check function always returns true.and returning an integer like -1 for unauthenticated user while the user is not authenticated.but it does not sound a clean way of implementing this.
Depending on how you want to set this up, you can just use the Auth facade helpers in your controller method to see whether a user is authenticated or not:
// SomeController.php
public function index(Request $request)
{
if(Auth::guest()) {
return response()->json('i am a guest');
} else {
return response()->json('im not a guest');
}
}
or use any of the related methods:
// Inverse of `Auth::guest()`
$isLoggedIn = Auth::check();
$loggedInUser = Auth::user();
https://laravel.com/api/5.8/Illuminate/Auth/GuardHelpers.html

Multiple auth controller middleware Laravel

I'm trying specify which functions are able to each user but the problem is when I pass more than one authenticated user to middleware in my controller.
Here are my controller. I'm trying allow just one method for the users but at that piece of code, the second line don't work out. Just show a response for not authorized (401).
public function __construct()
{
$this->middleware('auth:admin');
$this->middleware('auth:web')->only('listAll');
}
Someone have some idea how to solve it ?
I tried use:
public function __construct()
{
$this->middleware('auth:admin')->except('listAll');
$this->middleware('auth:web')->only('listAll');
}
Works but it means that will be allowed for all users...

Resources