Laravel API: display error message for invalid token? - laravel

I set up a simple api authentication with a hashed token as explained in the laravel doc
// app/Http/Controllers/Api/Blog/PostController.php
class PostController extends Controller
{
...
public function show($post)
{
if (!$post = Post::select('title', 'slug', 'content')->find($post)) {
return response()->json([
'message' => 'Ressource not found.'
], 404);
}
return response()->json($post);
}
...
}
// routes/api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::group(['middleware' => 'auth:api'], function () {
Route::apiResource('posts', PostController::class);
});
Now, in Postman if I send a request along with a valid token:
https://example.com/myapp/public/api/posts/5?api_token=tLcCDe6jCiYhuhUtVWwmnCbddSY7w9m4GIp6UXahyojW5O2YXPTpc4A7XRYV
I get the expected data in JSON format.
Now if I modify the token on purpose in order to simulate an invalid token, the request is redirected to the login page and I get the HTML code of the page in Postman with a 200 OK status.
But what I want is to display a 401 error message in JSON instead.
How can I do that ?

Related

Laravel Passport How to show custom error message when invalid token is supplied

I am trying to create an API with Laravel passport, and I have to protect some routes so that only authenticated users can access these routes.
Route::post('register', [ApiAuthController::class, 'register']);
Route::post('login', [ApiAuthController::class, 'login']);
Route::middleware('auth:api')->group(function () {
Route::post('/task', [ApiControllerTaskController::class,'store']);
});
Now hereafter login, I got an access token, and I used this access token like this.
Everything is working fine here, but I want to show an invalid token error message when I removed the bearer token. Instead, I got this.
Make sure you added the Content-type : application/json in your headers in Postman before sending your request
This worked for me, If your laravel version is >= 8.* add this code to your Handler.php witch located in App/Exceptions/Handler.php
public function render($request, Throwable $e)
{
if ($e instanceof AuthenticationException) {
return response()->json($e->getMessage());
}
return parent::render($request, $e);
}
If you need more help, leave me a commment. I hope I can help:)
//this worked for me (laravel 5.5) App\Exceptions\Handler.php (CTRL render)
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson() || $request->header('Authorization')) {
$response = ['status' => false, 'message' => 'Invalid token supplied'];
return response()->json($response, 401);
}
return redirect()->guest(route('login'));
}

Is possible to customize passport scope message in Laravel?

I'm creating an API with an authentication system using passport. I'm also using token scopes, for user permissions and everything is working fine.
My problem is, when a route e reached by an user without permission to access that route a 403
INVALID SCOPE(S) PROVIDED error page is returned. I would like to send some JSON message instead this error, but is not working.
My code:
File api.php
Route::post('/products/create', [BooksController::class, 'create'])->middleware(['auth:api',
'scope:create']);
Route::put('/products/update/{id}', [BooksController::class, 'update'])-
>middleware(['auth:api', 'scope:edit']);
Route::delete('/products/delete/{id}', [BooksController::class, 'destroy'])-
>middleware(['auth:api', 'scope:delete']);
File BooksController.php
public function destroy(Request $request)
{
if ($request->user()->tokenCan('delete')) {
return response()->json(['success' => "Destroy reached"], 200);
} else {
return response()->json(['error' => "You cannot reach this route"], 400);
}
}
File AuthServiceProvider.php
public function boot()
{
$this->registerPolicies();
Passport::tokensCan([
'edit' => 'can edit books',
'create' => 'can add books',
'delete' => 'can delete books',
]);
Passport::routes();
}

Getting invalid signature error when I send GET request in postman with authorization

I have an email verification method, when I register the user it sends the email normally, I want to test the route email/verify/{id}, that triggers when the user clicks the verification link, but I'm having issues with the postman request, it says that I have an invalid signature when I send the authorization token, it throws a different error if i remove it (403, Unauthorized)
My route
Route::prefix('auth')->group(function () {
Route::group(['middleware'=>'auth:api'], function(){
Route::get('user', 'Auth\AuthController#user');
Route::get('email/verify/{id}', 'Auth\VerificationController#verify')->name('verification.verify');
Route::get('email/resend', 'Auth\VerificationController#resend');
});
});
VerificationController
public function verify(Request $request){
if ($request->route('id') == $request->user()->getKey() &&
$request->user()->markEmailAsVerified()){
event (new Verified($request->user()));
}
return response()->json('verified');
}
public function resend(Request $request){
if ($request->user()->hasVerifiedEmail()){
return response()->json('already_verified', 422);
}
$request->user()->sendEmailVerificationNotification();
return response()->json([
'notified'
]);
}
public function __construct(){
$this->middleware('auth:api');
$this->middleware('signed')->only('verify');
$this->middleware('throttle:6,1')->only('verify', 'resend');
}
I'm sending the request in postman like this:
I don't know if I'm doing the request wrong or there is something wrong with my code. Any clue?
you have signed middleware which require another of GET parameter.
you can get the signed url by this laravel function
URL::signedRoute('verification.verify', []); and use that url in postman
Edit for summary:
must set env.APP_URL to have same port for the signedRoute function to works

How can I access data through API URL using custom token authorization in laravel

I have created a custom function in middleware which return the data after header token validation. It works fine and I can access the data using postman (Please check the attached screenshot below taken from postman). This is the code in middleware:
public function handle($request, Closure $next)
{
$token = $request->header('APP_KEY');
if ($token != 'XXXX') {
return response()->json(['message' => 'API Key not found!'], 401);
}
return $next($request);
}
The problem I am facing now, I can not get the data from browser URL. I have tried http://127.0.0.1:8000/api/?APP_KEY=XXXX

Token Based Logout - Laravel

For Logout function what Request should be Pass ? ( Access Token or any User Details?)
API Route
Route::group([
'middleware' => 'auth:api'
], function() {
Route::post('logout', 'api\LoginController#logout');
});
Controller function
public function logout(Request $request)
{
$request->user()->token()->revoke();
return $this->loggedOut($request);
}
Send just your Access Token to request. As midleware knows that given token belong to which user.
Postman request example:

Resources