jerik
jerik

Reputation: 5767

Test basic auth

I want to test my basic auth protected pages. The test for unauthorization works fine. But I struggle on the authorized login, as I do not know how to set the headers on in the test.

I could not find a hint, how to set headers on $this->call(). The only information I could find was:

$this->call($method, $uri, $parameters, $cookies, $files, $server, $content);

and there are the headers missing.

How do I easily test basic auth on laravel. Concrete: How do I set the basic auth header for the test request?

What I currently have:

class ExampleTest extends TestCase {
    public function test401UnauthorizedOnMe() { 
        $response = $this->call('GET', '/api/me');
        $this->assertResponseStatus( 401);
    }

    public function testCorrectLoginOnMe() { 
        // http://shortrecipes.blogspot.de/2009/12/testing-basic-http-authentication-using.html
        //send header with correct user and password i.e.
        ////YWRtaW46YWRtaW4xMg== is equal to base64_encode( "admin:admin12")
        $this->request->setHeader( 'Authorization','Basic YWRtaW46YWRtaW4xMg==');
        $response = $this->call('GET', '/api/me');
        $this->assertResponseStatus(200);
    }
}

I tried $this->$request->setHeader(); but with this I only get an error:

1) ExampleTest::testCorrectLoginOnMe
ErrorException: Undefined property: ExampleTest::$request

Upvotes: 8

Views: 9416

Answers (4)

svikramjeet
svikramjeet

Reputation: 1945

    $encoded_details = base64_encode('admin:admin12');
    $headers =  [
        'HTTP_Authorization' => 'Basic '. $encoded_details
    ];
    $response = $this->withHeaders($headers)->json('GET', '/api/me');

Just another solution which worked for me

Upvotes: 1

alexkb
alexkb

Reputation: 3356

Basic Auth is usually achieved with a header key of 'Authorization'. For convenience, I have the following method in my base TestCase class:

protected function withBasicAuth(User $user, $password = 'password'): self
{
    return $this->withHeaders([
        'Authorization' => 'Basic '. base64_encode("{$user->email}:{$password}")
    ]);
}

Then in any of my test cases I can run a HTTP test with a user authenticated over basic auth like so:

$user = User::factory()->create();
$this->withBasicAuth($user)
    ->get('/');
    ->assertStatus(Response::HTTP_OK);

Note: the default password for a user created from the factory is 'password'.

Upvotes: 1

BatManMightBeReal
BatManMightBeReal

Reputation: 61

protected function basicAuthenticate($detailsEncoded, $user, $password): self
{
    $_SERVER['HTTP_AUTHORIZATION'] = $detailsEncoded;
    $_SERVER['PHP_AUTH_USER'] = $user;
    $_SERVER['PHP_AUTH_PW'] = $password;

    return $this;
}


$response = $this->basicAuthenticate($detailsEncoded, $user, $password)->get($url);
$response->assertStatus(200);

Upvotes: 1

jerik
jerik

Reputation: 5767

Found the solution with HTTP authentication with PHP. This can be used in the $server parameter of $this->call().

Here's my working function:

public function testCorrectLoginOnMe() {
    // call( $method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
    $this->call('GET', '/api/me', [], [], [], ['PHP_AUTH_USER' => 'admin', 'PHP_AUTH_PW' => 'admin12']);
    $this->assertResponseStatus( 200 );
}

Upvotes: 9

Related Questions