BorisTheTripper's avatar

How do I customize the "auth" middleware logic?

I'd like to add some custom logic to the auth middleware, namely I want to flash a message when an unauthenticated user is redirected to the login page. What's the best approach in Laravel 11?

FWIW below is a description of what I've tried:

I've tried creating my own middleware that runs before the auth middleware, but that never works for some reason:

    public function handle(Request $request, Closure $next): Response
    {
        Log::debug('MyCustomMiddleware');
        Log::debug($request->url());

        $routeMiddleware = $request->route()->middleware();
        if (Auth::guest() && in_array('auth', $routeMiddleware)) {
            session()->flash('message', 'you are not logged in');
        }

        return $next($request);
    }

I then try to attach the mw like so:

Route::get('/bookmarks', [PostBookmarkController::class, 'index'])
    ->middleware(['auth', MyCustomMiddleware::class]); // I've tried reversing this array too

But my middleware always logs out the /login, and never the /bookmarks.

0 likes
19 replies
wing5wong's avatar

How about overriding the unauthenticated method in App\Http\Middleware\Authenticate ?

    protected function unauthenticated($request, array $guards)
    {
        session()->flash('message', 'Login first');
        throw new AuthenticationException(
            'Unauthenticated.', $guards, $this->redirectTo($request)
        );
    }
BorisTheTripper's avatar

@wing5wong What precisely do I do w/ this middleware to make it override the default?

I have run php artisan make:middleware Authenticate, and a standard empty middleware has been created. This doesn't override anything yet, nor does adding extends \Illuminate\Auth\Middleware\Authenticate to the class definition.

Next thing I did was to append this custom Authenticate::class in ./bootstrap/app.php, but this just adds another near copy of the standard "auth" mw to the middleware chain, which in my scenario just causes the login endpoint to get hit repeatedly ad infinitum.

I've also tried $middleware->replace('auth', Authenticate::class); and $middleware->replace(\Illuminate\Auth\Middleware\Authenticate::class, Authenticate::class);, but to zero avail.

🔔 UPDATE: just made it work with $middleware->alias(['auth' => Authenticate::class]); – is that how I was supposed to do it from the beginning? or did I just hack my way into what could have been done much more easily?

For context, here's what my custom mw looks like:

<?php

namespace App\Http\Middleware;

use Illuminate\Auth\AuthenticationException;
use Log;

class Authenticate extends \Illuminate\Auth\Middleware\Authenticate
{
    protected function unauthenticated($request, array $guards)
    {
        session()->flash('message', 'Login first');
        Log::debug('hello...');
        throw new AuthenticationException(
            'Unauthenticated.',
            $guards,
            $this->redirectTo($request)
        );
    }
}
1 like
wing5wong's avatar

@BorisTheTripper Apologies - i was actually working on a non11 project when giving this advice, but yes you have figured it out.

Extend the default, and override the existing method, and alias your new middleware is fine back to the original auth

jlrdw's avatar

I want to flash a message when an unauthenticated user is redirected to the login page.

There should be no such thing. Any user is unauthenticated until they login.

Sorry if question confused me.

wing5wong's avatar

@jlrdw This happens after attempting to access an auth protected route while not logged in.

1 like
martinbean's avatar

I want to flash a message when an unauthenticated user is redirected to the login page

@boristhetripper You don’t need this, as if the user is redirected back to the login page due to their credentials being invalid, then there will already be an error message in the default error bag:

<form action="{{ route('login') }}" method="POST">
    @csrf
    <div>
        <label for="email">Email</label>
        <input id="email" name="email" type="email" value="{{ old('email') }}">
        <!-- Show any login-related errors -->
        @foreach($errors->get('email') as $error)
            <div class="invalid-feedback">{{ $error }}</div>
        @endforeach
    </div>
    <div>
        <label for="password">Password</label>
        <input id="password" name="password" type="password">
    </div>
    <button type="submit">Log in</button>
</form>
BorisTheTripper's avatar

@martinbean idk about the standard Laravel + Blade setup, but I'm using Inertia, and props.errors is always an empty object in the scenario I describe in the OP.

martinbean's avatar

@BorisTheTripper So take a step back. If the credentials were invalid, you’d be redirected back with errors in the session, Inertia or not. That’s just how Laravel’s authentication component works out of the box. So what else have you changed around authentication to break that default behaviour?

wing5wong's avatar

@martinbean i don't think the question is relating to invalid credentials. At this point no credentials have been entered, simply the userr tried to access a page that required authentication, and was redirected to login Now he wants to add a message explaining why this redirect occurred that is displayed to the user.

martinbean's avatar

@wing5wong That doesn’t make any sense. If the user tried to do something, but then ends up on a log in page, then it’s pretty clear they need to log in. Why do they need a message saying, “You’re on a log in page. You need to log in”? 😄

wing5wong's avatar

@martinbean Id assume the flash message is going to include some additional context.

Even for simple things like this I have seen people get confused around what has actually happened. Many users somehow dont grasp the concept that they are 'logged in' or 'logged out' - they just know the app is working or not working.

EmilKaminski's avatar

@martinbean In Laravel 11, if user input data is not validate then it redirect back. But props.error is empty.. Why?

Also, After Login successfully, I redirect to other route with flash session. but It does not persist. Could you please let me know how to solve it?

EmilKaminski's avatar

@jlrdw Thanks suggest me, But I already post for this problem, and didn't get any answer unfortunitely. Could you help me?

EmilKaminski's avatar

@martinbean Oh.. I am sorry. I wasn't intend to hijack the this thread or insulting @kodyxgen . I was wanted the expert's help, sorry if I was distrub the this thread. Hope everyone understand me and help me please to resolve the problem.

Snapey's avatar

@boristhetripper

So what you are saying is, a logged in user has their session expire. They dont know this, and when they click on a navigation button (etc) the auth middleware redirects them to the login page.

Now the user is confused. They were looking at the site as they normally experience it, they clicked to do something and ended up at login.

To prevent their confusion, you want to show something on the login page as explanation.

Personally, I would look at the 'intended' property in the login controller or view and if set, show your message.

How you do this exactly depends on your starter kit

Please or to participate in this conversation.