I'm developing an API with API-Platform. Authentication is provided by Lexik bundle. First use case are functional. I test my three first use cases with Postman and it works.
- Step1: I access a protected page without token, I have a 401 error as expected.
- Step2: I ask a token.
- Step3: I access a protected page with a token, I received data as expected.
Now I want to install Behat and add features to reproduced my manual test with Postman, but I am not able to configure my JWT token correctly.
I read the official documentation. And here is my two scenarios:
# features/books.feature
Feature: Books feature
Scenario: Listing all books without authentication
When I add "Content-Type" header equal to "application/json"
And I add "Accept" header equal to "application/json"
And I send a "GET" request to "/api/books/"
Then the response status code should be 401
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
And the JSON nodes should contain:
| message | JWT Token not found |
@loginAsAdmin
@logout
Scenario: Listing all books with admin authentication
When I add "Content-Type" header equal to "application/json"
And I add "Accept" header equal to "application/json"
And I send a "GET" request to "/api/books/"
Then the response status code should be 200
And the response should be in JSON
And the header "Content-Type" should be equal to "application/json"
As you can see an screenshot, the first scenario works fine, but not the second, because my functional implementation is returning a 301 http code (redirection!) instead of 200.
Current response status code is 301, but 200 expected. I never had a 301 response with postman...
Here is my method to declare @loginAsAdmin
/**
* FeatureContext constructor.
*
* @param KernelInterface $kernel the kernel to get services.
*/
public function __construct(KernelInterface $kernel)
{
$this->manager = $kernel->getContainer()->get('doctrine.orm.default_entity_manager');
$this->jwtManager = $kernel->getContainer()->get('lexik_jwt_authentication.jwt_manager');
}
/**
* @BeforeScenario @loginAsAdmin
*
* @see https://symfony.com/doc/current/security/entity_provider.html#creating-your-first-user
*
* @param BeforeScenarioScope $scope the scope
*/
public function loginAsAdmin(BeforeScenarioScope $scope)
{
//Test with a fake user
//$user = new User();
//$user->setEmail('admin@example.org');
//$user->setUsername('Admin');
//$user->setRoles(['ROLE_ADMIN']);
//Test with a user in database
/** @var UserRepository $userRepository */
$userRepository = $this->manager->getRepository(User::class);
/** @var User $user */
$user = $userRepository->findOneByEmail('admin@example.org');
$token = $this->jwtManager->create($user);
/** @var RestContext $restContext */
$this->restContext = $scope->getEnvironment()->getContext(RestContext::class);
$this->restContext->iAddHeaderEqualTo('Authorization', "Bearer $token");
}
/**
* @AfterScenario @logout
*/
public function logout() {
$this->restContext->iAddHeaderEqualTo('Authorization', '');
}
I tried to use a virtual user (in comments) I tried to use a user already set in database, it does not change anything.
As soon as I add header to my rest context, it seems to return a redirect answer. The redirection target is the same page : http://127.0.0.1:8000/api/books
I have read this question which is a little different and it seems user does not have response for my case.
What did I wrong?