skip to Main Content

I have a api project with Laravel 11, and i want to make a middleware for admin api.

AdminMiddleware.php (custom middleware)

<?php

namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
use SymfonyComponentHttpFoundationResponse;

class AdminMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  Closure(IlluminateHttpRequest): (SymfonyComponentHttpFoundationResponse)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        $user = Auth::user();

        if (!$user) {
            return response()->json([
                'status' => 'forbidden',
                'message' => 'You need to log in first.'
            ], 403);
        }

        if ($user->authority !== 'admin') {
            return response()->json([
                'status' => 'forbidden',
                'message' => 'You are not an administrator.'
            ], 403);
        }

        return $next($request);

    }
}

bootstrap/app.php (new dir middleware config)

<?php

use AppHttpMiddlewareAdminMiddleware;
use IlluminateFoundationApplication;
use IlluminateFoundationConfigurationExceptions;
use IlluminateFoundationConfigurationMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->alias([
            "is_admin" => AdminMiddleware::class,
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

api.php (api route)

<?php

use AppHttpControllersProductController;
use AppHttpControllersUserController;
use AppHttpMiddlewareAdminMiddleware;
use IlluminateHttpRequest;
use IlluminateSupportFacadesRoute;

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth:sanctum');


Route::prefix('/v1')->group(function () {
    Route::prefix('/admin')->group(function () {
        Route::prefix('/product')->group(function () {
            Route::get('/', [ProductController::class, "index"]);
            Route::post('/', [ProductController::class, "store"]);
            Route::get('/{id}', [ProductController::class, "show"]);
            Route::put('/{id}', [ProductController::class, "update"]);
            Route::delete('/{id}', [ProductController::class, "destroy"]);
        });
        Route::prefix('/user')->group(function () {
            Route::get('/', [UserController::class, "index"]);
            Route::get('/{id}', [UserController::class, "show"]);
            Route::post('/{id}', [UserController::class, "store"]);
            Route::put('/{id}', [UserController::class, "update"]);
            Route::delete('/{id}', [UserController::class, "destroy"]);
        });
    })->middleware("is_admin");

    Route::prefix('/auth')->group(function () {
        Route::post('/signup', [UserController::class, "signup"]);
        Route::post('/signin', [UserController::class, "signin"]);
        Route::post('/signout', [UserController::class, "signout"]);
    });
    Route::prefix('/product')->group(function () {
        Route::post('/', [ProductController::class, "product"]);
    });
});

I’ve just try using aliases and api method in config. but in api method case, all api route affected by the middleware. I’d try to use Route::group([‘middleware’ => ‘is_admin’] and directly in api route by use the AdminMiddleware, and call in the method with middleware(AdminMiddleware::class). ya it’s doesn’t work.

2

Answers


  1. Chosen as BEST ANSWER

    Okay, first of all I want to thank @subha for the solution provided and helped find some problems that are happening in my project. I ended up creating a new project and then moving some of the code to the new project... (I really have a skill issue lol)

    1. solving the route problem. Ive found this video on youtube ( https://www.youtube.com/watch?v=st7DtZA85fw ) this is the work code:
        route::group([
                "middleware" => ["auth:sanctum", "is_admin"]
            ], function(){
            Route::prefix('/admin')->group(function () {
                Route::prefix('/product')->group(function () {
                    Route::get('/', [ProductController::class, "index"]);
                    Route::post('/', [ProductController::class, "store"]);
                    Route::get('/{id}', [ProductController::class, "show"]);
                    Route::put('/{id}', [ProductController::class, "update"]);
                    Route::delete('/{id}', [ProductController::class, "destroy"]);
                });
                Route::prefix('/user')->group(function () {
                    Route::get('/', [UserController::class, "index"]);
                    Route::get('/{id}', [UserController::class, "show"]);
                    Route::post('/{id}', [UserController::class, "store"]);
                    Route::put('/{id}', [UserController::class, "update"]);
                    Route::delete('/{id}', [UserController::class, "destroy"]);
                });
            });
        });
    

    if I use ->middleware("auth:sanctum"); its not work. this dont work too:

    Route::prefix('/admin')->group([
                "middleware" => ["auth:sanctum", "is_admin"]
            ], function(){....
    
    1. solve the api auth problem (after signin. if user access other method, Auth::user() will return null). (this one is a simple problem actually lol) adding Accept: application/json on request header

  2. Since you mentioned in your comment.

    I use middleware so that only user with admin authority can access, but user with null authority can access it. (I’ve also tried dd($user) in middleware before next request but it’s not showing.).

    If you want only the admin authority can access those routes through AdminMiddleware,then you need to put another check for those users who have null authority.

    Because in PHP null is a data-type which has no value.

    If your AdminMiddleware assigned to the routes properly then below code will work.

    Try this in AdminMiddleware.

        public function handle(Request $request, Closure $next): Response
        {
            $user = Auth::user();
    
            if (!$user) {
                return response()->json([
                    'status' => 'forbidden',
                    'message' => 'You need to log in first.'
                ], 403);
            }
    
            if ((is_null($user->authority) || $user->authority !== 'admin')) {
                return response()->json([
                    'status' => 'forbidden',
                    'message' => 'You are not an administrator.'
                ], 403);
            }
    
        return $next($request);
    
    }
    

    Use the above code it will work.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search