Closed TaromaruYuki closed 2 years ago
What problem are you facing with your Symfony authenticator? This bundle only integrates with the Form component, it adds a custom FieldType whose data is not mapped and with a default constraint that checks the captcha. It should be irrelevant in what context you use it, as long as you have a Form or a FormExtension in which you can add the field.
The verification is done by this class: https://github.com/Meteo-Concept/hcaptcha-bundle/blob/v3/Service/HCaptchaVerifier.php. You can import that class as a service and use the method verify to verify a captcha.
I reckon that the bundle could use more documentation, although the only intended usage is really what's shown in the readme.
When authenticating, the authenticator does not see it as a required param so it can be skipped. Which makes sense. So, I have to verify it myself.
I have attempted to make a verifier instance, but the client param is wrong. How would passing Symfony's HttpClient work then? The only example I can find is the VerifierTest but that uses HTTP mock.
You shouldn't need to instantiate it yourself and should use dependency injection instead, like any service.
Let's assume your class is called CustomAuthenticator, you can use :
<?php
use MeteoConcept\HCaptchaBundle\Form\HCaptchaResponse;
use MeteoConcept\HCaptchaBundle\Service\HCaptchaVerifier;
use Symfony\Component\HttpFoundation\RequestStack;
class CustomAuthenticator
{
private HCaptchaVerifier $verifier;
private RequestStack $requestStack;
private string $siteKey;
public function __construct(RequestStack $requestStack, HCaptchaVerifier $verifier, string $siteKey) {
$this->requestStack = $requestStack;
$this->verifier = $verifier;
$this->siteKey = $siteKey;
}
//...
public function verifyLogin() {
//..
$masterRequest = $this->requestStack->getMainRequest();
$response = $masterRequest->get("h-captcha-response");
$remoteIp = $masterRequest->getClientIp();
$captcha = new HCaptchaResponse($response, $remoteIp, $this->siteKey);
if ($this->verifier->verify($captcha)) {
// ...
}
}
}
You also need to pass the site key to your CustomAuthenticator class via a service definition. It's a bit cumbersome because normally the work of getting the captcha from the request is done by the Form DataTransformer. Alternatively you could define a service that extends the HCaptchaVerifier to do all the work.
If you have access to the form itself in the authenticator, it's easier because then, the captcha field value is already an instance of HCaptchaResponse so you can verify it directly.
Ah yeah, I've been doing vanilla PHP for a while. I'm just so used to making everything myself.
I did get it working, roughly used what was posted.
public function authenticate(Request $request): Passport
{
...
$h_res = $request->request->get('h-captcha-response');
$ip = $request->getClientIp();
$captcha = new HCaptchaResponse($h_res, $ip, $_ENV['HCAPTCHA_SITE_KEY']);
if ($h_res === "") {
throw new CustomUserMessageAuthenticationException(
"Capcha was not filled out. Please fill the capcha to login."
);
}
if($this->verifier->verify($captcha)) {
...
} else {
throw new CustomUserMessageAuthenticationException("Captcha could not verified. Please try again.");
}
}
Works perfectly, use it for my signup form. But I can't use it in my login form, as it uses a custom Symfony authenticator. There aren't any docs outside of the readme, which doesn't help.
If there isn't any support, is it possible to check and verify the captcha myself?
Thank you!