thomaspb's avatar

Error while testing routes using auth middleware

Install clean Lumen 5.2

Uncomment the dollowing in bootstrap/app.php

$app->routeMiddleware([
    'auth' => App\Http\Middleware\Authenticate::class,
]);
$app->register(App\Providers\AuthServiceProvider::class);

Add middleware

$app->get('/', function () use ($app) {
    return $app->version();
})->middleware('auth');

Run phpunit and .... BOOM. Returns infinite loop errors

HPUnit 4.8.21 by Sebastian Bergmann and contributors.

PHP Fatal error:  Maximum function nesting level of '256' reached, aborting! in /Users/thomaspb/Desktop/bug-error/vendor/illuminate/container/Container.php on line 700
PHP Stack trace:
PHP   1. {main}() /Users/thomaspb/.composer/vendor/phpunit/phpunit/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /Users/thomaspb/.composer/vendor/phpunit/phpunit/phpunit:47
PHP   3. PHPUnit_TextUI_Command->run() /Users/thomaspb/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:100
PHP   4. PHPUnit_TextUI_TestRunner->doRun() /Users/thomaspb/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:149
PHP   5. PHPUnit_Framework_TestSuite->run() /Users/thomaspb/Desktop/bug-error/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:440
PHP   6. PHPUnit_Framework_TestSuite->run() /Users/thomaspb/Desktop/bug-error/vendor/phpunit/phpunit/src/Framework/TestSuite.php:747
PHP   7. PHPUnit_Framework_TestCase->run() /Users/thomaspb/Desktop/bug-error/vendor/phpunit/phpunit/src/Framework/TestSuite.php:747
PHP   8. PHPUnit_Framework_TestResult->run() /Users/thomaspb/Desktop/bug-error/vendor/phpunit/phpunit/src/Framework/TestCase.php:724
PHP   9. PHPUnit_Framework_TestCase->runBare() /Users/thomaspb/Desktop/bug-error/vendor/phpunit/phpunit/src/Framework/TestResult.php:612
...
...
...

If I run the controller from browser works fine. The problem exists only in phpunit tests.

Do you know anything about this problem?

0 likes
10 replies
bobbybouwmann's avatar

I think you have mistake in your code... When I run this I get this error

[1]    1947 segmentation fault  ./vendor/bin/phpunit

So I have been digging into this (I never played with the updated Lumen before), but I figured it out pretty quick. For authentication you need to uncomment the AuthServiceProvider statement in bootstrap/app.php

Documentation: Note: Before using Lumen's authentication features, you should uncomment the call to register the AuthServiceProvider service provider in your bootstrap/app.php file.

Next you need some way on how you want to authenticate the user. Note that Lumen is really only for API's and microservices so there are not much helpers here. If you open the AuthServiceProvider you can see that they give an example here.

If you comment $this->actingAs($user); your tests do pass ;)

thomaspb's avatar

I have already tryed it many times.. I have already read many times the documentation. Pull the changes and run the phpunit.

bobbybouwmann's avatar

It's working fine for me after I did what I told you... How does your AuthServiceProvider look like? You need to do some logic there!

thomaspb's avatar

Hello,

Can you please clone the GitHub repo I have provided? There is no $this->actingAs($user); in this version, but the loop error keeps occurring.

Can you please push your working example on github/bitbucket/anywhere so that I can see what goes wrong on mine?

The problem seems to happen just by adding the Auth middleware on any route.

pkazak's avatar

So, I tried this and it checks out. I have located the problem in the following line of the Authenticate Middleware...

    if ($this->auth->guard($guard)->guest()) {
        return response('Unauthorized.', 401);
    }

This if is causing the loop to occur. Is there another way to check if the user is a guest?

pkazak's avatar

Hello guys, Can someone provide a working example of Authentication on Lumen 5.2? Or point me to the right direction so that I can find it out on my own?

I have even tried authenticating the user the hard way (Auth::login(User::find(1)); in my controller and I got back on my server log the same infinite error loop which in my case stops at 256 loops.

Anyone, please!?

bogdanghervan's avatar

Lumen v5.2.4 here.

I'm also getting the "Maximum function nesting level reached" error, but only if I have Xdebug enabled. Here's how it looks for everyone else without Xdebug:

$ ./vendor/bin/phpunit 
PHPUnit 4.8.21 by Sebastian Bergmann and contributors.

Segmentation fault (core dumped)

I've done some debugging and my preliminary findings show that the custom authentication guard added in the boot method of AuthServiceProvider fails to be properly registered with the authentication manager (AuthManager) when a request is dispatched via ->call() or the other convenience request helpers in a PHPUnit test.

Auth::viaRequest('api', function() {
    // custom authentication code
});

Later in the request lifecycle, the Authenticate middleware attempts to retrieve said guard, which AuthManager fails to resolve. Illuminate\Auth\AuthManager::resolve is where everything falls apart: it attempts to call "createApiDriver" (which doesn't exist) and the __call method tries to resolve the guard once more and it enters an infinite loop.

Does anyone have a setup that works?

I'll keep looking and report back if I get it to work.

1 like
bogdanghervan's avatar

So I took this further and eventually suspected that calling viaRequest on the Auth facade might register the callback on the wrong AuthManager instance which the internal PHPUnit-dispatched request doesn't know anything about.

Going back to the documentation I noticed that the AuthManager is retrieved in a different way than what you get in a fresh Lumen v5.2.4 project.

Docs:

$this->app['auth']->viaRequest('api', function ($request) {
    // Return User or null...
});

Fresh Lumen project:

Auth::viaRequest('api', function ($request) {
    // some more code commented out for brevity
});

Retrieving the instance from $this->app['auth'] makes it a little better, in that it doesn't enter an infinite loop anymore (I can see the request successfully pass through the Authenticate middleware onto the route). However, now I can only retrieve the authenticated user via Auth::user() inside my routes ($request->user() returns NULL).

Please or to participate in this conversation.