Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel middleware 'except' rule not working

I have a controller with the following in the constructor:

$this->middleware('guest', ['except' =>
    [
        'logout',
        'auth/facebook',
        'auth/facebook/callback',
        'auth/facebook/unlink'
    ]
]);

The 'logout' rule (which is there by default) works perfectly but the other 3 rules I have added are ignored. The routes in routes.php look like this:

Route::group(['middleware' => ['web']],function(){

    Route::auth();

    // Facebook auth
    Route::get('/auth/facebook', 'Auth\AuthController@redirectToFacebook')->name('facebook_auth');
    Route::get('/auth/facebook/callback', 'Auth\AuthController@handleFacebookCallback')->name('facebook_callback');
    Route::get('/auth/facebook/unlink', 'Auth\AuthController@handleFacebookUnlink')->name('facebook_unlink');
}

If I visit auth/facebook, auth/facebook/callback or auth/facebook/unlink whilst logged in I get denied by the middleware and thrown back to the homepage.

I've tried specifying the 'except' rules with proceeding /'s so they match the routes in routes.php exactly but it makes no difference. Any ideas why these rules are being ignored, whilst the default 'logout' rule is respected?

Cheers!

like image 573
jd182 Avatar asked Jan 10 '16 21:01

jd182


People also ask

How do you call middleware in Laravel?

Assigning Middleware To Routes If you would like to assign middleware to specific routes, you should first assign the middleware a key in your application's app/Http/Kernel.php file. By default, the $routeMiddleware property of this class contains entries for the middleware included with Laravel.

Where do I register middleware in Laravel?

The middleware can be registered at app/Http/Kernel. This file contains two properties $middleware and $routeMiddleware. $middleware property is used to register Global Middleware and $routeMiddleware property is used to register route specific middleware.

What is guest middleware in Laravel?

A middleware which checks if the current user is logged in and stops them seeing guest pages such as login. If you are logged in then it makes no sense to be able to view the login view, the user gets redirected to the dashboard instead.


2 Answers

You need to pass the method's name instead of the URI.

<?php
    
namespace App\Http\Controllers;
    
class MyController extends Controller {
    public function __construct() {
        $this->middleware('guest', ['except' => [
            'redirectToFacebook', 'handleFacebookCallback', 'handleFacebookUnlink'
        ]]);
    }
}

Since Laravel 5.3, you can use fluent interface to define middlewares on controllers, which seems cleaner than using multidimensional arrays.

<?php

$this->middleware('guest')->except('redirectToFacebook', 'handleFacebookCallback', 'handleFacebookUnlink');
like image 165
Lucas Silva Avatar answered Sep 28 '22 12:09

Lucas Silva


I solved this issue in my Middleware by adding this inExceptArray function. It's the same way VerifyCsrfToken handles the except array.

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class MyMiddleware
{
    /**
     * Routes that should skip handle.
     *
     * @var array
     */
    protected $except = [
        '/some/route',
    ];

    /**
     * Determine if the request has a URI that should pass through.
     *
     * @param Request $request
     * @return bool
     */
    protected function inExceptArray($request)
    {
        foreach ($this->except as $except) {
            if ($except !== '/') {
                $except = trim($except, '/');
            }

            if ($request->is($except)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Handle an incoming request.
     *
     * @param  Request  $request
     * @param Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // check user authed or API Key
        if (!$this->inExceptArray($request)) {
            // Process middleware checks and return if failed...
            if (true) {
              // Middleware failed, send back response
              return response()->json([
                'error' => true,
                'Message' => 'Failed Middleware check'
            ]); 
            }
        }
        // Middleware passed or in Except array
        return $next($request);
    }
}
like image 21
cmac Avatar answered Sep 28 '22 10:09

cmac