Authenticate a Request with JWT
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
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:
// ... 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:
// ... 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']
:
// ... 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.
:
// ... 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.
Is there going to be a tutorial on how to use this api from another symfony project to authenticate users?