cartalyst / sentinel

A framework agnostic authentication & authorization system.
BSD 3-Clause "New" or "Revised" License
1.52k stars 240 forks source link

Sentinel::guest() always returns true. #504

Closed jelledijkstra97 closed 5 years ago

jelledijkstra97 commented 5 years ago

Your Environment

Expected behaviour

I expect the auth middleware to use my signed in user.

I have a Laravel 6.0 app thats uses Sentinel for authentication. I can succesfully log in however after redirecting to my home page a auth middleware redirects me back to the login page. After log in a new row is inserted in the persistences table and inside my session a variable called 'cartalyst_sentinel' is stored with the same value as the persistence row.

When I call Sentinel::findByPersistenceCode with the session code inside the middleware, the current user is returned, however one line later Sentinel::guest() returns true.

Auth controller:

<?php namespace Schedules\Http\Controllers;

use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Illuminate\Http\Request;
use Lang;
use Laracasts\Flash\Flash;
use Log;
use Illuminate\Support\Facades\Session;
use Activation;

/**
 * Class AuthController
 * @package Schedules\Http\Controllers
 */
class AuthController extends Controller
{
    /**
     * AuthController constructor.
     */
    function __construct()
    {
        $this->middleware('guest', ['except' => 'getLogout']);
    }

    /**
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function getLogin()
    {
        return view('auth.login');
    }

    /**
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function postLogin(Request $request)
    {
        $credentials = $request->except(['_token']);

        if (empty($credentials['email']) || empty($credentials['password'])) {
            Flash::error(Lang::get('auth.messages.empty_fields'));
            return redirect('login');
        }

        if (Sentinel::authenticate($credentials, true)) {
            log::debug("Succesfully logged in");
            Log::debug(Sentinel::getUser()); // This prints the correct user
            return redirect('/');
        } else {
            Flash::error(Lang::get('auth.messages.invalid_login'));
        }

        return redirect('login');
    }

    /**
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function getLogout()
    {
        Sentinel::logout(null, true);

        return redirect('login');
    }

}

Auth middleware:

<?php namespace Schedules\Http\Middleware;

use Cartalyst\Sentinel\Laravel\Facades\Sentinel;
use Closure;
use Illuminate\Contracts\Auth\Guard;
use Log;
use Session;

class Authenticate {

    /**
     * The Guard implementation.
     *
     * @var Guard
     */
    protected $auth;

    /**
     * Create a new filter instance.
     *
     * @param  Guard $auth
     */
    public function __construct(Guard $auth)
    {
        $this->auth = $auth;
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $user = Sentinel::findByPersistenceCode(Session::get('cartalyst_sentinel'));
        Log::debug($user); // This prints the correct user

        if (Sentinel::guest())
        {
            if ($request->ajax())
            {
                return response('Unauthorized.', 401);
            }
            else
            {
                return redirect()->guest('login');
            }
        }

        return $next($request);
    }

}

In both parts the correct user is printed to my log. But after that Sentinel::guest() returns true.

How can this be?

suwardany commented 5 years ago

Try to import

use Cartalyst\Sentinel\Sentinel;

and then replace

public function __construct(Guard $auth)

with

public function __construct(Sentinel $auth) and make use of it instead of the facade.

if ($this->auth->guest()) {
...
jelledijkstra97 commented 5 years ago

Thanks for the reply!

Unfortunately this did not solve my problem. The docs say to use Cartalyst\Sentinel\Laravel\Facade\Sentinel right?

Here's my kernel.php, maybe that gives a clue.

<?php

namespace Schedules\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \Schedules\Http\Middleware\TrustProxies::class,
        \Schedules\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \Schedules\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \Illuminate\Session\Middleware\StartSession::class,
            \Schedules\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \Schedules\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => 'Schedules\Http\Middleware\Authenticate',
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \Schedules\Http\Middleware\RedirectIfAuthenticated::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    ];

    /**
     * The priority-sorted list of middleware.
     *
     * This forces non-global middleware to always be in the given order.
     *
     * @var array
     */
    protected $middlewarePriority = [
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Schedules\Http\Middleware\Authenticate::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];
}

Any other suggestions?

suwardany commented 5 years ago

What do you have in the RedirectIfAuthenticated class?

jelledijkstra97 commented 5 years ago
<?php

namespace Schedules\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use Sentinel;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        if (Sentinel::check())
        {
            return redirect('/');
        }

        return $next($request);
    }
}
brunogaspar commented 5 years ago

Can't reproduce this issue:

Try to reproduce the problem in a fresh Laravel installation, if it occurs, push the exact code to a public repository and link it here please.

Going to close it for now as it seems a problem on your application.