Home > Blockchain >  API returns HTML response after API protection using custom guard and passport
API returns HTML response after API protection using custom guard and passport

Time:12-04

I hope you're doing well, I just need some help with my problem, been stuck at it for a while now and I cannot figure out a work around. I implemented another login for the admin in my project and I use a custom guard and custom middleware for it. This works properly without any problem. The problem started when I try to protect the API routes using passport. For the users which uses the auth:api as the API middleware, everything works fine. But in my custom guard, it returns an HTML response(console.log says it returns HTML but it does not output anything in the UI) instead of json. If I remove the route protection it would work again as intended. I hope you can help me with this one. Thank you!

I am using Laravel Passport for the API protection.

This is how it looks like without the API route protection(This is how it should be). enter image description here

This is how it looks like with the route protection enter image description here

This is what console.log returns with route protection. Without it, it returns the response from the first picture.

enter image description here

Here's my code below

AdminMiddleware

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;

class AdminMiddleware
{
    public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard('admin')->check()) {
            return $next($request);
        } else {
            return redirect()->route('admin.login');
        }
    }

Kernel.php

 protected $routeMiddleware = [
        'auth.admin' => \App\Http\Middleware\AdminMiddleware::class,
        'auth' => \App\Http\Middleware\Authenticate::class,
 ];

config/auth.php

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
        'hash' => false,
    ],

    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],
    'adminApi' => [
        'driver' => 'passport',
        'provider' => 'admins',
        'hash' => false,
    ]
],

routes/api.php

Route::group(['middleware' => ['auth.admin:adminApi']], function(){
    Route::get('/fetch-announcements', [AnnouncementController::class, 'showAnnouncement']);
    Route::post('/store-announcements',[AnnouncementController::class, 'storeAnnouncement']);
});

Models/Admin.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class Admin extends Authenticatable
{
    use HasFactory, HasApiTokens;
    protected $fillable =[
        'email',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];
    
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

Get Request

await axios.get('/api/fetch-announcements', {
                headers: {
                    'Accept': 'application/json'
                }
            })
                .then(response => {
                    this.announcements = response.data
                    console.log(this.announcements)
                })
                .catch(err => console.error(err))

EDIT The API returns a 302 code

CodePudding user response:

Just send a header for the request as Accept: application/json.

So you will get the same as JSON.

CodePudding user response:

The API return html response because the middleware that you created before, when the auth check is failing, it will redirect you to admin login page.

First, you should check the API that you called from axios is include the token or not, if not, it will run the else statement.

Next, your middleware will only return redirect page (302) when the auth guard check failed, either in web or api. If you want your API return a json, you may change your middleware just like below code, dont forget add header 'Accept': 'application/json' on your request.

public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard('admin')->check()) {
        return $next($request);
    } else {
        if ($request->wantsJson()) {
            return response()->json([
                "error" => true,
                "message" => "Unauthenticated"
            ], 403);
        }else{
            return redirect()->route("cart.index");
        }
    }
}
  • Related