I am writing a REST API endpoint in PHP / Symfony 4.0 and I want to use basic authentication, with an in-memory user whose password is blank. When I try to call the endpoint with these credentials, I get a BadCredentialsException saying 'The presented password cannot be empty'.
It appears that the exception is being thrown by the DaoAuthenticationProvider.
How can I configure basic authentication in Symfony to allow an empty password?
Context: I'm setting up basic authentication for a simple endpoint that will be used as a Prismic custom API for an integration field (see https://user-guides.prismic.io/en/articles/1401183-connect-to-a-custom-api). Prismic supports basic authentication for this, where you enter a key which will be used as the username, and the password will be left blank.
I am writing this in PHP / Symfony 4.0, and I have been following the docs at https://symfony.com/doc/current/security.html .
My config/packages/security.yaml file is:
security:
firewalls:
secured_area:
pattern: ^/api/my-endpoint
http_basic: ~
security: true
main:
security: false
providers:
in_memory:
memory:
users:
test:
password: ''
encoders:
Symfony\Component\Security\Core\User\User: plaintext
The full error message in my logs is:
Basic authentication failed for user. {"username":"test","exception":"[object] (Symfony\Component\Security\Core\Exception\BadCredentialsException(code: 0): Bad credentials. at my-project\vendor\symfony\security\Core\Authentication\Provider\UserAuthenticationProvider.php:84, Symfony\Component\Security\Core\Exception\BadCredentialsException(code: 0): The presented password cannot be empty. at my-project\vendor\symfony\security\Core\Authentication\Provider\DaoAuthenticationProvider.php:54)"} []
If you really don't want to have a proper authentication, and then authenticated user will do a call to a remote endpoint with the API key, and resolve the task in a more "dirty" way, then what you can do is:
create your own AuthenticationProvider, which will extend the original https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php
overwrite the checkAuthentication method where you will have same code as original, but without check on empty password (and perhaps everything else related in that else statement)
overwrite the service definition to point to your own created AuthenticationProvider
<service id="security.authentication.provider.dao" class="XXXX Your class here XXXX" abstract="true">
<argument /> <!-- User Provider -->
<argument /> <!-- User Checker -->
<argument /> <!-- Provider-shared Key -->
<argument type="service" id="security.encoder_factory" />
<argument>%security.authentication.hide_user_not_found%</argument>
</service>
clear the cache and try
Overwrite the service:
services:
...
...
security.authentication.provider.dao:
alias: MyProject\Service\Security\OverriddenDaoAuthenticationProvider
public: true
In your OverriddenDaoAuthenticationProvider class remember to call the original constructor to pass through the parameters:
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, string $providerKey, EncoderFactoryInterface $encoderFactory, bool $hideUserNotFoundExceptions = true)
{
parent::__construct($userProvider, $userChecker, $providerKey, $encoderFactory, $hideUserNotFoundExceptions);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With