I work for a company that has an app that uses multi-tenancy to serve several customers. Let's call it something like... Really Great Company. Say we've got a customer whose organization is abbreviated as FOO and another that goes by BAR. The first company would visit https://foo.reallygreatcompany.com, and the second https://bar.reallygreatcompany.com. When working on our local machines we use valet to register test sites that we visit in the browser with URLs like http://foo.test and http://bar.test.
I had previously written some Dusk tests before and had them all working, but lately I keep getting an error saying "The user is not authenticated." Here is what one of my tests looks like:
$this->browse(function (Browser $browser) use ($userId) {
$browser->loginAs($userId)
->assertAuthenticated()
->visit(new PublicationsPage())
->openPublicationForm('journal article')
->addNewAuthor([
'first_name' => 'Testy',
'last_name' => 'McTester'
])
->fillOutFormAndSave([
'title' => 'Test New Contact Journal Article'
])
->waitUntilMissing('@subformContainer')
->waitForText('Test New Contact Journal Article');
});
All these tests were working before, but now it seems to be failing with the exception Illuminate\Auth\SessionGuard::login(): Argument #1 ($user) must be of type Illuminate\Contracts\Auth\Authenticatable, null given, called in /Users/steve/code/app/vendor/laravel/dusk/src/Http/Controllers/UserController.php on line 48.
I have seen this Laracasts question that seems related, and I've seen the answer suggested by the OP, but he mentions in his answer
This is assuming you haven't changed the default 'domain' => env('SESSION_DOMAIN'), in your session.php config file.
I tried their solution and nothing changed. Guess whose session config file has been altered that way... That's right, mine just looks like this:
'domain' => null,
Git annotations shows the commit message on that line
use redis for sessions
Using xdebug I can see that the loginAs method appears to be working. Then the test proceeds to the assertAuthenticated method where Dusk visits the _dusk/user route. In the user method of vendor/laravel/framework/src/Illuminate/Auth/SessionGuard.php I can see by walking through with xdebug that $this->user is null, as is the variable $id, so the code attempts to decrypt the "recaller" cookie to get the user object.
public function user()
{
if ($this->loggedOut) {
return;
}
// If we've already retrieved the user for the current request we can just
// return it back immediately. We do not want to fetch the user data on
// every call to this method because that would be tremendously slow.
if (! is_null($this->user)) {
return $this->user;
}
$id = $this->session->get($this->getName());
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
if (! is_null($id) && $this->user = $this->provider->retrieveById($id)) {
$this->fireAuthenticatedEvent($this->user);
}
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
if (is_null($this->user) && ! is_null($recaller = $this->recaller())) {
$this->user = $this->userFromRecaller($recaller);
if ($this->user) {
$this->updateSession($this->user->getAuthIdentifier());
$this->fireLoginEvent($this->user, true);
}
}
return $this->user;
}
! is_null($recaller = $this->recaller()) in that final if statement is where it appears to be failing. $recaller is null, as is $this->user, causing the user function to return null, resulting in the exception message that I mentioned previously:
Argument #1 ($user) must be of type Illuminate\Contracts\Auth\Authenticatable, null given
Does anyone have any ideas on how to fix this? It sounds like maybe I need to change something with redis? I've never really messed with redis before so I'm kind of in the dark here.