Search code examples
symfonysecurityphpunitfosrestbundle

Unit test on REST with basic http authentication is always 401 Unauthorized


I'm making a REST api with basic http authentication.

The authentication works as expected in a browser and Postman, status 200 Ok and controller behaving fine if the credentials are entered right, 401 Unauthorized otherwise.

The problem is that I'm struggling to make the phpunit test to successfully authenticate, it always returns a 401 Unauthorized code and I can't get why.

security.yml:

security:
providers:
    in_memory:
        memory:
            users:
                test:
                    password: testpass
                    roles: 'ROLE_TEST'

encoders:
    Symfony\Component\Security\Core\User\User: plaintext

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    default:
        anonymous: ~
        http_basic: ~

access_control:
    - { path: ^/api/test, roles: ROLE_TEST }

ApiControllerTest.php

namespace ApiBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\HttpFoundation\Response;

class ApiControllerTest extends WebTestCase
{
    public function testIndex()
    {

        $client = static::createClient();

        $crawler = $client->request(
            'GET',
            '/api/test/hello/unittestname',
            array(),
            array(),
            array(),
            array('PHP_AUTH_USER' => 'test', 'PHP_AUTH_PW' => 'testpass'));

        $this->assertSame(Response::HTTP_OK, $client->getResponse()->getStatusCode());

    }
}

launching the test :

1) ApiBundle\Tests\Controller\ApiControllerTest::testIndex
Failed asserting that 401 is identical to 200.

Solution

  • Depends on documentation base authentication credentials should be passed in $_SERVER. The same point is mentioned in Symfony documentation ("More about the request() Method" section).

    Put the credentials into fifth argument - server parameters.

    $crawler = $client->request(
        'GET',
        '/api/test/hello/unittestname',
        [],
        [],
        ['PHP_AUTH_USER' => 'test', 'PHP_AUTH_PW' => 'testpass']
    );