Buy

We already added a denyAccessUnlessGranted() line to ProgrammerController::newAction(). That means this endpoint is broken: we don't have an API authentication system hooked up yet.

Open up ProgrammerControllerTest() and find testPOST(): the test for this endpoint:

256 lines tests/AppBundle/Controller/Api/ProgrammerControllerTest.php
... lines 1 - 6
class ProgrammerControllerTest extends ApiTestCase
{
... lines 9 - 15
public function testPOST()
{
... lines 18 - 34
}
... lines 36 - 254
}

Rename this to testPOSTProgrammerWorks() - this will make its name unique enough that we can run it alone:

262 lines tests/AppBundle/Controller/Api/ProgrammerControllerTest.php
... lines 1 - 6
class ProgrammerControllerTest extends ApiTestCase
{
... lines 9 - 15
public function testPOSTProgrammerWorks()
{
... lines 18 - 40
}
... lines 42 - 260
}

Copy that name and run it:

./vendor/bin/phpunit --filter testPOSTProgrammerWorks

Instead of the 201, we get a 200 status code after being redirected to /login. I know we don't have our security system hooked up yet, but pretend that it is hooked up and working nicely. How can we update the test to send a token?

Sending a Token in the Test

Well, first, we'll need to create a valid token. Do that the same way we just did in the controller: $token = $this->getService() - which is just a shortcut we made to fetch a service from the container - and grab the lexik_jwt_authentication.encoder service. Finally, call encode() and pass it ['username' => 'weaverryan']:

262 lines tests/AppBundle/Controller/Api/ProgrammerControllerTest.php
... lines 1 - 6
class ProgrammerControllerTest extends ApiTestCase
{
... lines 9 - 15
public function testPOSTProgrammerWorks()
{
$data = array(
'nickname' => 'ObjectOrienter',
'avatarNumber' => 5,
'tagLine' => 'a test dev!'
);
$token = $this->getService('lexik_jwt_authentication.encoder')
->encode(['username' => 'weaverryan']);
... lines 26 - 40
}
... lines 42 - 260
}

And we have a token! Now, how do we send it to the server? Well, it's our API, so we can do whatever the heck we want! We can set it as a query string or attach it on a header. The most common way is to set it on a header called Authorization. Add a headers key to the Guzzle call with one header called Authorization. Set its value to the word Bearer, a space, and then the $token.:

262 lines tests/AppBundle/Controller/Api/ProgrammerControllerTest.php
... lines 1 - 6
class ProgrammerControllerTest extends ApiTestCase
{
... lines 9 - 15
public function testPOSTProgrammerWorks()
{
... lines 18 - 26
// 1) Create a programmer resource
$response = $this->client->post('/api/programmers', [
'body' => json_encode($data),
'headers' => [
'Authorization' => 'Bearer '.$token
]
]);
... lines 34 - 40
}
... lines 42 - 260
}

Weird as it might look, this is a really standard way to send a token to an API. If we re-run the test now, it of course still fails. But we're finally ready to create an authentication system that looks for this token and authenticates our user.

Leave a comment!

  • 2016-12-19 weaverryan

    Hey Nicholas!

    Hmm, are you sure? Since we're using the Guzzle client in this tutorial, we should be able to send the raw HTTP header names (i.e. Authorization) and not need to prefix them. But, something may have changed. Are you possibly using the Symfony built-in Client instead? I'm trying to figure out what the difference is :).

    Cheers!

  • 2016-06-09 Vlad

    Thank you! That was it. I needed to add the firewall configs. I'll check the entry point chapter. Thanks again.

  • 2016-06-08 weaverryan

    Just saw this message :). What behavior *are* you getting? Ultimately, the /login redirection is caused by the "form_login" system in the firewall. It's possible that you don't have that (or have some other behavior). Check out the entry point chapter, but let me know if you have questions - the "entry point" idea can be tricky.

  • 2016-06-08 weaverryan

    Hi Vlad!

    That's explained a few chapters from here - it's caused by what's called an "entry point": https://knpuniversity.com/s...

    Hope that helps!

  • 2016-06-08 Vlad

    I'm following this tutorial and working on parallel project and for some reason I don't get the /login redirection. What am I missing?

  • 2016-06-08 Vlad

    Where is the /login redirection covered? How does it happen?
    Thanks