Laravel 8 shows 419 error even added csrf and session is not saved if disabled csrf

Published

Background

I created a custom auth middleware to check if user is already logged
in. If logged user visit login page, it redirects him to dashboard. If
non-logged user visit dashboard page, it redirects him to the login
page. I use LaravelLocalization as multi language plugin.

Problem

During testing, everything works fine. I could login, session is
saved, no 419 errors. However, when I come back to try to login again,
I meet 419 page expired error. I read many post about this and most of
them advise to add different form of @csrf into the form which seems I
already did. Then I tried to disable the csrf verification by add
$except = ['*'] in VerifyCsrfToken.php. Then 419 is gone but
session is not working. After I login, it successfully redirect to the
dashboard but after refresh, the session is lost and redirect to the
login page again. The problem could temporarily solved by php artisan cache:clear

Please advise. I don’t even know where to start debug.

Middleware/CustomAuth.php

<?php

namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use McamaraLaravelLocalizationFacadesLaravelLocalization;


class CustomAuth
{
    /**
     * Handle an incoming request.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  Closure  $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {



        if(!(session()->has('logged_affiliate')) 
            &&  $request->path() != 'user-login' 
            && $request->path() != 'user-register' 
            && $request->path() != LaravelLocalization::getCurrentLocale()."/user-login" 
            && $request->path() != LaravelLocalization::getCurrentLocale()."/user-register" 
            
            ){

            return redirect(LaravelLocalization::localizeUrl("/user-login"))->with('fail',__('word.login_first'));
        }

        if(session()->has('logged_affiliate') 
            && ( 
                $request->path() == 'user-login' 
                || $request->path() == 'user-register' 
                || $request->path() == LaravelLocalization::getCurrentLocale()."/user-login"  
                || $request->path() == LaravelLocalization::getCurrentLocale()."/user-register" 
                )
            
            ){

            return redirect(LaravelLocalization::localizeUrl("/affiliate"));
        }

        // if(session()->has('logged_advertiser') && ( $request->path() == 'user-login' || $request->path() == 'user-register' )){
        //     return redirect('/advertiser');
        // }

        return $next($request);
    }
}


Route

Then in the route file I wrap those routes in ['middleware'=>['CustomAuth']

<?php

use IlluminateSupportFacadesRoute;


Route::prefix(LaravelLocalization::setLocale())->middleware(['localeSessionRedirect', 'localizationRedirect'])->group(function () {



    //other route


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


        Route::get('/user-login',[AppHttpControllersUserController::class,'showLogin']);
        Route::get('/user-register',[AppHttpControllersUserController::class,'showRegister']);

        //this is the user dashboard
        Route::get('/affiliate',[AppHttpControllersUserController::class,'showAffiliateDashboard']);



        Route::get('/affiliate/website-list',[AppHttpControllersUserController::class,'affiliate_website_list']);

        //some similar routes

        
    });

    //submit form
    Route::post('/check',[AppHttpControllersUserController::class,'checkLogin'])->name('checkLogin');
    Route::post('/user-register',[AppHttpControllersUserController::class,'createAccount'])->name('create_account');
    Route::post('/affiliate-add-website',[AppHttpControllersUserController::class,'affiliate_add_website'])->name('affiliate_add_website');
    Route::post('/affiliate-edit-website',[AppHttpControllersUserController::class,'affiliate_edit_website'])->name('affiliate-edit-website');

    Route::get('/logout',[AppHttpControllersUserController::class,'logout'])->name('logout');
    Route::post('/license/check',[AppHttpControllersUserController::class,'affiliate_use_license'])->name('affiliate_use_license');



    //other route


});

View and form
Then the user login form, I added @csrf

   <form action="{{ LaravelLocalization::localizeUrl("/check") }}" method="POST">
                                @csrf

                                <div class="form-group">
                                    <label>{{ __('word.username') }}</label>
                                    <input type="text" class="form-control" name="username" value="{{  old('username') }}">
                                    <span class="text-danger">@error('username'){{  $message }} @enderror</span>
                                </div>
                                <div class="form-group">
                                    <label>{{ __('word.password') }} ({{ __('word.password_hint') }})</label>
                                    <input type="password" class="form-control" name="password">
                                    <span class="text-danger">@error('password'){{  $message }} @enderror</span>
                                </div>
                                <div class="mt-4">
                                    <div class="row">
                                        <div class="col-12">
                                            <button type="submit" class="btn btn-outline-primary btn-block btn-lg submit-btn">
                                                <i class="spinner fa fa-spinner fa-spin" aria-hidden="true"></i>  {{ __('word.signin') }}
                                            </button>
                                        </div>
                                    </div>
                                </div>
                                @if(Session::get('fail'))
                                    <div class="alert alert-danger mt-3">
                                        {{ Session::get('fail') }}
                                    </div>
                                @endif
                            </form>

Controller

This is UserController to check credential. If checked correct, save into session $request->session()->put('logged_affiliate',$user->username);

  public function checkLogin(Request $request)
    {

        $request->validate(
            [
                'username' => ['required'],
                'password' => ['required'],
                // 'user_type' => ['required'],
            ],
            [
                'username.required' => __('word.username_required'),
                'password.required' => __('word.password_required'),
                // 'user_type.required' => __('word.user_type_required'),
            ],
        );

        $user = User::where('username',$request->username)->first();
        
        if(!$user){
            return back()->with('fail',__('word.no_such_user'));
        }else{
            if(Hash::check($request->password,$user->password)){
                if($user->user_type == 'affiliate'){
                    $request->session()->put('logged_affiliate',$user->username);

                    return redirect(LaravelLocalization::localizeURL('/affiliate'));
                }elseif($user->user_type == 'advertiser'){
                    $request->session()->put('logged_advertiser',$user->id);
                    return redirect(LaravelLocalization::localizeURL('/advertiser'));
                }else{
                    return back()->with('fail',__('word.something_wrong'));
                }

            }else{
                return back()->with('fail',__('word.wrong_password'));
            }
        }
    }


    //Affiliate Dashboard Pages
    public function showAffiliateDashboard()
    {

        $lang = CommonController::get_lang();
        $affiliate_data = CommonController::get_affiliate_data();
        
        $ads = CommonController::get_ads();

        $user_data = User::where('user_type','affiliate')->where('username', session('logged_affiliate'))->first();
        $user_websites = Affiliate::where('affiliate_id',session('logged_affiliate'))->get();

        $active_level_1 = Affiliate::where('affiliate_id',session('logged_affiliate'))->where('active',1)->where('level',1)->count();
        $active_level_2 = Affiliate::where('affiliate_id',session('logged_affiliate'))->where('active',1)->where('level',2)->count();


        return view('users.affiliateDashboard',compact(
            'lang','affiliate_data','ads',
            'user_data','user_websites',
            'active_level_1','active_level_2',
        ));
    }

Source: Laravel

Published
Categorised as caching, csrf, laravel, php, session Tagged , , , ,

Answers

Leave a Reply

Still Have Questions?


Our dedicated development team is here for you!

We can help you find answers to your question for as low as 5$.

Contact Us
faq