Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

davewood's avatar

laravel test "remembers" api_token authentication for unauthenticated followup request

I see this behaviour only with the laravel test system, cannot reproduce when i make the same sequence of requests with curl or browser.

  1. get('/api/foo?api_token='.$wrong_token, 401) // ok ... 401
  2. get('/api/foo?api_token='.$correct_token, 200) // ok ... 200
  3. get('/api/foo?api_token='.$wrong_token, 401) // NOTOK ... app returns 200

if i make the same requests with curl from a remote host

  1. curl -X GET -H "Content-type: application/json" -H "Accept: application/json" http://localhost:8000/api/users?api_token=$wrong_token // ok ... 401
  2. curl -X GET -H "Content-type: application/json" -H "Accept: application/json" http://localhost:8000/api/users?api_token=$correct_token // ok ... 201
  3. curl -X GET -H "Content-type: application/json" -H "Accept: application/json" http://localhost:8000/api/users?api_token=$wrong_token // ok ... 401

why does the laravel test environment behaviour differ and "remember" the authentication?

namespace Tests\Unit;
    
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\User;
//(...)
    public function _get($url, $status = 200) {
        $res = $this->json('GET', $url);
        $res->assertStatus($status);
        return $res;
    }
//(...)
        $res = $this->_get('/api/users?api_token=wrong_token', 401);
        $res = $this->_get('/api/users?api_token='.$api_token, 200);
        $res = $this->_get('/api/users?api_token=wrong_token', 401); 

There was 1 failure:

1) Tests\Unit\UserTest::testBasic
Expected status code 401 but received 200.
Failed asserting that false is true.

/home/ratis/ratis-api/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestResponse.php:151
/home/ratis/ratis-api/tests/Unit/UserTest.php:14
/home/ratis/ratis-api/tests/Unit/UserTest.php:21
/home/ratis/ratis-api/tests/Unit/UserTest.php:76
# routes/api.php
Route::namespace('Api')->group(function () {
    Route::post('/users/register', 'UserController@register');
    Route::post('/users/login', 'UserController@login');
});
Route::middleware('auth:api')->group(function () {
  Route::namespace('Api')->group(function () {
    Route::apiResource('users', 'UserController');
    Route::apiResource('akten', 'AkteController');
  });
});
# config/auth.php
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
    ],
0 likes
4 replies
aurawindsurfing's avatar

Hey @davewood

Try using this trait as well:

namespace Tests\Unit;
    
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
use App\User;

use Illuminate\Foundation\Testing\WithoutMiddleware;

It will disable all session data.

Hope it helps!

davewood's avatar

hi aurawindsurfing, thanks for your feedback.

surprisingly that didnt change anything.

I am surprised because I expected an earlier test to fail if middlewares are disabled (im using and testing the auth:api middlware)

furthermore i already disabled the session middleware in my app because i dont need it.

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            // \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            // \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            // \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        
        'api' => [
            'throttle:60,1',                                                                                         
            'bindings',
        ],
    ];

so the question stands why the test behaviour is different from real world behaviour

Please or to participate in this conversation.