Laravel 5.4 Set All Authentication Routes Except Logout Route - Using Custom Logout Route/Controller

10,452

Solution 1

Robinson, thanks for reaching out to me on Twitter for help on this answer. I actually think this is a great question and hope this question finds its way up Google ranks for future devs to find and maybe spark a little discussion in the community.

How can I prevent the logout route from being produced with Auth::routes() command?

Long story short... you can't. If you want to use the Auth::routes() shorthand, then it is an all-or-nothing type of command. You can view the actual source code behind that command here for Laravel v5.5 (although it hasnt changed since version 5.2 I believe), and viewing the actual code behind the shorthand command you can see that it accepts no parameters such as the ['except' => 'logout'] array that you have come to expect with other route helper commands in Laravel. There are no hidden, undocumented secrets here to make this command do anything unique, by inspecting the source code we can see that it isn't setup to do anything other than return a pre-set list of routes.

It literally just outputs a set of routes with no logic (decision making) at all. This command is just a shorthand method that prevents you from having to write all those routes yourself.

With that being said, there is no reason that you HAVE to use this shorthand. You can manually make all of these routes yourself. Look at the source code I linked above or run php artisan r:l (another shorthand for route:list for any noobs reading this) and copy the same output into your routes file. This allows you to skip over or modify any routes to your liking.

This is what the routes would look like if you want to add them without the shorthand command. Make sure to delete that command and paste these in instead. Whichever commands you want to delete or modify can easily be done so like any other route. I took this from the Laravel source code, so it is 100% EXACTLY the same as the shorthand command creates, including the order of the routes (and technically the comments too).

// Authentication Routes...
Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController@login');
Route::post('logout', 'Auth\LoginController@logout')->name('logout');

// Registration Routes...
Route::get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
Route::post('register', 'Auth\RegisterController@register');

// Password Reset Routes...
Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset');

So if you wanted to copy this code block and add it to your routes file, it would give you the exact same results (and does the same thing behind the scenes) as the shorthand Auth::routes() command does. Now you can customize or remove any of the commands that you want.

How do I change the logout route into a GET route?

So now that we discussed how you work with authentication scaffolding routes, lets answer the meat and potatoes behind your question. You are looking to make the logout command accessible via a GET request (as opposed to a POST request which is how Laravel sets it up by default.

Easy enough, there are two ways to do this:

1) Copy all the routes and change the logout route to a GET request

This is easy enough, delete the Auth::routes() shorthand and then copy the routes I posted above and paste it into your routes file in the same location that your Auth::routes() used to be. Then on the third route of our new authentication routes, we find the logout one. Simply change it from Route::post() to Route::get() and leave everything else the same.

Your routes file will look like this now: You could just copy and paste this below and go about your business now.

// Authentication Routes...
Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController@login');
Route::get('logout', 'Auth\LoginController@logout')->name('logout');

// Registration Routes...
Route::get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
Route::post('register', 'Auth\RegisterController@register');

// Password Reset Routes...
Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset');

2) The second option is to add a GET version in addition to your Auth::routes() shorthand.

This would ultimately make the logout route accessible via both a GET and a POST request. They both link to the same method, so they do the same thing and work in the same way and now you can logout as either a POST or GET request.

The resulting code of this option would be this:

Auth::routes();
Route::get('logout', 'Auth\LoginController@logout');

Note that I omitted the name from the second line. It is already named thanks to the Auth::routes() command. So you don't need to name it again. The logout name will still work though. So you can still use <a href="{{ route('logout') }}">Logout</a> in your blade files and the route name will work regardless of whether you are using it as a GET or POST request.

So there you go, a long winding journey into the world of Auth::routes() shorthand command.

Solution 2

In Laravel 6.x, some Authentication Routes have changed. You can use the following line of code to exclude the register route.

Auth::routes(['register' => false]);

However, since you're requiring that the register route still remains intact, you would have to do what the other person that answered this question has done, and define all the routes manually. However, their answer hasn't been updated to the current version of Laravel. So here is an updated list of all the routes as of version 6.x.

// User Authentication Routes
Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
Route::post('login', 'Auth\LoginController@login');
Route::post('logout', 'Auth\LoginController@logout')->name('logout');

// User Registration Routes
Route::get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
Route::post('register', 'Auth\RegisterController@register');

// User Password Reset Routes
Route::get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');
Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update');

// User Verification Routes
Route::get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
Route::get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::post('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');
Share:
10,452
J. Robinson
Author by

J. Robinson

I started working with HTML 4, then moved on to CSS, and now I'm currently a back-end Developer for my own company.

Updated on June 05, 2022

Comments

  • J. Robinson
    J. Robinson almost 2 years

    So for some reason I thought I came across the answer to this question before, but for the life of me I can't find the answer again, either through Google or StackOverflow. This might just be a rubber duck question and I'm sorry if it is, but I hope this question will be of some use to someone someday with this same issue.

    Let's assume we're starting with a fresh installation of Laravel 5.4. I run the php artisan make:auth command in my terminal and it sets up the Authentication Scaffolding for me. Now in my /routes/web.php file I see the following line:

    Auth::routes();

    Which is awesome and the route list has all the Authentication routes listed including the logout route defined. (Typed php artisan r:l to double check) Now I want to set a custom logout route for the user using the a custom Logout Controller. Now, I thought that there was a method you could chain onto a group of resource routes called 'except()' but for the life of me I can't find any information in the documentation about this method. I don't know if this method even exists let alone know what to pass it.

    I'm assuming that the Auth::routes() generation can use the except method like in a resource route, but I'm not entirely sure how to implement it?

    So the question is simple. How do I include all authentication routes except the logout route, and then i'll define the logout route using the following line.

    Route::get('logout', 'LogoutController@userLogout')->name('logout');

    Sorry if this is a duplicate entry, I've used the search bar for the past hour and nothing is answering my question.

    Edit: I did more research into Resource Routes and realized that it's not a method that I chain onto the route, but rather an array with a key value pair. See code below (Ripped from laravel docs).

    Route::resource('photo', 'PhotoController', ['except' => [
        'create', 'store', 'update', 'destroy'
    ]]);
    

    However when I pass the array into the routes() method (see code below) the logout route is still there in the route list. However no error is being thrown upon the php artisan r:l command.

    // User Authentication Routes
    Auth::routes(['except' => 'logout']);
    

    EDIT: After much digging around it seems like it is not possible to do this type of functionality. I have submitted an issue to the laravel/framework github repo requesting the feature be added in 5.5.

    Exclude route from Laravel authentication

    https://github.com/laravel/framework/issues/20904