PSR proposal: CAPTCHA (CaptchaInterface and etc.)

87 views
Skip to first unread message

LeTraceurSnork

unread,
Jun 30, 2025, 11:42:13 AMJun 30
to PHP Framework Interoperability Group
Good day, everyone!
I would like to propose standardizing a new CaptchaInterface. It's main purpose, as I see it, is to unify all Captchas external providers into one simple interface that could be easily used when passed via DI. E.g.:
```php
class SomeFormHandler
{
    function __construct(CaptchaInterface $captcha)
    {
        $this->captcha = $captcha;
    }

    function formSubmit($some_request)
    {
        $captcha_token = $some_request->get('captcha_token');
        $verification = $this->captcha->verify($captcha_token);
        if ($verification->isSuccess()) {
            // captcha passed, do stuff
        } else {
            // captcha failed
        }
    }
}
```

The reason why I'm doing this, in a nutshell - to speed up potential switches from one vendor to another, avoiding potential vendor-lock and unifying SDK usage in a future
And while I'm saying "potential", please, don't think I'm paranoid :) We actually faced this problem recently and now had to switch captcha vendor from Google ReCaptcha to something else. And sadly enough, that something else doesn't have its own SDK, so, now unofficial will appear as mushrooms after a rain - and they better be unified with one another due to the reasons described above.

Well, more to that (and a lot of comments with interested in that developers) you can find in a PR: https://github.com/php-fig/fig-standards/pull/1330

--
Best regards,
Saligzhanov Ilya

Korvin Szanto

unread,
Jun 30, 2025, 2:24:17 PMJun 30
to PHP Framework Interoperability Group
Hi Ilya,
I'm glad to see your effort on this!

I'm not convinced that this deserves to be its own targeted thing rather than a more general request validator PSR. A more broad request validator PSR could handle more types of validators and validate the entirety of a request rather than just this one small aspect of request validation. For example, on a registration form submission I might want to validate the provided email, password, name, settings, etc. and I think by focusing on such a narrow swimlane for this might hinder future efforts to build the more broad PSR I'd prefer to see.

Can you speak to why this should be a standalone PSR and not a general request validator PSR?

Thanks,
Korvin

Andreas Heigl

unread,
Jun 30, 2025, 2:32:04 PMJun 30
to php...@googlegroups.com
Hey Ilya, hey List

Am 30.06.25 um 17:08 schrieb LeTraceurSnork:
> Good day, everyone!
> I would like to propose standardizing a new CaptchaInterface. It's main
> purpose, as I see it, is to unify all Captchas external providers into one
> simple interface that could be easily used when passed via DI. E.g.:
> ```php
> class SomeFormHandler
> {
> function __construct(CaptchaInterface $captcha)
> {
> $this->captcha = $captcha;
> }
>
> function formSubmit($some_request)
> {
> $captcha_token = $some_request->get('captcha_token');
> $verification = $this->captcha->verify($captcha_token);
> if ($verification->isSuccess()) {
> // captcha passed, do stuff
> } else {
> // captcha failed
> }
> }
> }
> ```
>
> The reason why I'm doing this, in a nutshell - to speed up potential
> switches from one vendor to another, avoiding potential vendor-lock and
> unifying SDK usage in a future
> And while I'm saying "potential", please, don't think I'm paranoid :) We
> actually faced this problem recently and now had to switch captcha vendor
> from Google ReCaptcha to something else. And sadly enough, that something
> else doesn't have its own SDK, so, now unofficial will appear as mushrooms
> after a rain - and they better be unified with one another due to the
> reasons described above.

Do we really want to encourage bad UX? Captchas are a way to distinguish
between human and machine. By now all captchas are more easily solved by
machines than by humans.

Using them is discouraged by several UX and Accessibility groups...

Just my 0.02€

Cheers

Andreas
--
,,,
(o o)
+---------------------------------------------------------ooO-(_)-Ooo-+
| Andreas Heigl |
| mailto:and...@heigl.org N 50°22'59.5" E 08°23'58" |
| https://andreas.heigl.org |
+---------------------------------------------------------------------+
| https://hei.gl/appointmentwithandreas |
+---------------------------------------------------------------------+
| GPG-Key: https://hei.gl/keyandreasheiglorg |
+---------------------------------------------------------------------+

OpenPGP_signature.asc

Jaap van Otterdijk

unread,
Jun 30, 2025, 2:42:00 PMJun 30
to PHP Framework Interoperability Group

Hi,

I have been following the captcha pr for a while. And I still have my doubts about the approach. If we look at the example code given here it could have been wrapped in a psr-15 middleware implementation. As you need the request, get some information out of it, and either fail or continue.

I do understand your point about not having a vendor lock in your code base. So from that point of view I get it. However I'm not sure we need a psr for this particular topic.

I think others also suggested to make this a broader psr that covers validation. Which would make sense if we could standardize the input and output and the way errors are reported. But as the whole validation chain has a lot of opinions, I think you would have a very hard time to standardize that. 

Neverless, I would like to praise you for all the work you did up til this far. I can see you are really willing and listening to others. I will keep following your progress. 


Op ma 30 jun 2025 17:42 schreef LeTraceurSnork <letrace...@gmail.com>:
--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/php-fig/4e708808-cfd6-428d-85c0-16e3cad763e8n%40googlegroups.com.

LeTraceurSnork

unread,
Jun 30, 2025, 3:54:57 PMJun 30
to PHP Framework Interoperability Group
Good night, gentlemen!
Well, allow me to defend my point then :-)
@KorvinSzanto actually, you have a very strong point now, I'm even starting to think that this PSR actually is unneeded, but! There is always a but - even tho it was also in my mind to propose Validators PSR (as I mentioned in Discord earlier), somehow I think that if Captcha gathered so many opinions, so many disagreements and strugglings, while there is only one, rougly speaking, global implementation (ReCapctchaV3) that almost everyone use and get used to its interface, I already see how many disagreements will be on Validator PSR and how long will it take to get him to Draft at least. While Captcha is already in business. And yes, now I actually see, that it fully covered by nonexistent (yet) ValidatorInterface with its only two semantical methods - say, `::simpleValidate($data): bool` and `::extendedValidate($data): ValidatorResponse`
And now to the point, where you and @JaapVanOtterdijk intersects: Yes, we can (probably) realise Captcha verifier via PSR-15 with PSR-7+PSR-18++++smth else, but (again) - as solId insists - we shall not. We shall not add Captcha verifier class methods it doesn't need - and I, as a user, and also as a developer of an internal-usage captcha SDK, definitely don't need `::getHeader()`, `::getHeaderLine()`, `::withBody()`, etc, etc. - from PSR-7 and I also find PSR-15 just too redundant for that matter.

All I want as a captcha user (developer-user) - is:
1. Grab my user's token
2. Pass it to something along with `secret_key`
3. That something must tell me `true`-`false` where `true` is "my user passed captcham he is not a bot"
That's all, I don't want to validate their values, generate requests on requests, responses on something, meeeh. Just take my string and say yes-or-no - simple interface as it is. And that simple interface is now absence.
So, the main question is - do we want that simple interface? I believe we do
And if you answer "yes, but we can present it in Validator PSR" - I agree with you. But until then we can present it via Captcha PSR and then, if needed, turn it into Deprecated/Abandoned

Summary: I believe that interfaces should be semantical. And nothing more semantical for captcha validation then specific Captcha validator interface

@AndreasHeigl well, we can't just ignore it - captcha is just the matter of fact for now. Good, bad, evil - it just is, it presents on the web, users pass it on daily basis, and developers are forced to verify it. And without proper interfaces it hurts :-(

понедельник, 30 июня 2025 г. в 23:42:00 UTC+5, Jaap van Otterdijk:

Jaap van Otterdijk

unread,
Jun 30, 2025, 5:31:35 PMJun 30
to PHP Framework Interoperability Group

Thanks again for taking the time to give us an answer. It just underlines my statement that your efforts to get this done are huge.

I was thinking again about your answer. And while reading I realized you have a point about the struggle we would have to  come with an interface for request validation. It's a hairy topic. Because everyone is doing this in their own way. But that's exactly the point of a standard. It's not just the matter of getting things done. It's about the value it provides. The interface for a captcha seems to me a very small work field. While you could argue that that's a good point. I think interfaces that have a bigger focus are better in place. Not that the interface itself should be large, but the way it can be used should be brought. At least in a standard lib.  Or it should focus on a very common problem. 

The psr standards all focus on very common patterns in a web application. Everyone needs logging, service containers can be found everywhere, and there is literally no php application out there that doesn't do request response. That's why those deserve a psr. That's also why I think validation would be a very good candidate. Because validation is everywhere. .

For captcha this is a different story. While there are many captcha providers, not all applications use captcha. It's not a common pattern. It's a solution for a specific problem. So the amount of applications actually using it will be very limited. If the would even exist in the future. I think more and more companies are actually looking for a better way to validate their users are human. 

I really tried to see the value. But I simply don't get it for this particular psr. 


Op ma 30 jun 2025 21:55 schreef LeTraceurSnork <letrace...@gmail.com>:

LeTraceurSnork

unread,
Jul 1, 2025, 1:19:16 AMJul 1
to PHP Framework Interoperability Group
Well, on the one hand, I agree with you, PSR should be something that is commonly used. On the other hand, numbers says (https://siteefy.com/how-many-websites-are-there/) that there is around 1.2 billions websites, 17% active (around 196 millions), and Aguko Captcha tracker (https://www.aguko.com/cat/captchas) says that almost 6.8 million websites actually using Captcha. If we take that PHP usage is about 74% (says w3techs https://w3techs.com/technologies/details/pl-php), the math is that about 4.6% of PHP websites using Captcha. I, ofc, understand, that in percentage that might be not a big number, but still - it appears to be that Captcha is actually widely popular (and intuitioon says the same) - it's not a rare specific problem, it's widely appearing problem that needs to be solved on daily basis for different developers - AND it already being solved in almost identical way (all Captchas have token, secret key most of them returns score/message, all of them can be presented as true/false validator), but strictly technical speaking, while those approaches unstandardized (uninterfaced) - they're different. Any library/SDK can release their major (or even minor) update and break this compatibility with others - because it doesn't know about the others. That's bad, that is leading the community to chaos and increases entropy

p.s. as I confessed to @samdark, I'm an inclusionist, as wikipedians would say, so I actually root for any interface if it solves semantical problem, no matter how small it may seem. My logic is simple - if anyone needs it - he will use it, if don't - well, don't use it xD Couldn't hurt from an existing interface if you don't know about one and don't implement it. Or as my ancestors say - "it doesn't ask for food and drink" :-)

вторник, 1 июля 2025 г. в 02:31:35 UTC+5, Jaap van Otterdijk:

Andreas Heigl

unread,
Jul 1, 2025, 2:02:42 AMJul 1
to php...@googlegroups.com
Hey all.

Am 30.06.25 um 23:31 schrieb Jaap van Otterdijk:
I wholeheartedly agree with Japp here for several reasons:

Captchas are - despite their wide usage - an antipattern. The fact that
they are used on a lot of platforms does not mean that it is a good
idea. A lot of people are using timestamps or convert dates to UTC when
there are better options available. Just because people do it does not
mean it is the right thing to do.

Providing an interface from the FIG explicitly for Captcha-Usage will
make it look like the FIG supports this anti-pattern. I would rather not
see that.

On the other side though a Captcha is something that is included in a
form. It is one form field. If you don't use forms, you don't need
captchas.

And what indeed is missing - and I just stumbled upon this in another
project I am working on - is a set of interfaces that allow be to easily
build, display and validate a form. SOmething that allows me to add
form-fields from different sources to a form "object" and then easily
render that and in the next step validate it.

Something like $form->add(new TextField('name', 'value', 'default', ...))

And once there is such a "FormBuilder" interface set that allows adding
different fields from different sources (as they all share the same
interfaces) it should be no issue at all anymore to call then something
like $form->add(new Captcha('name', 'value', 'id-key', 'whatever else'));

Which then allows easily exchangeable Form fields. So then the only
thing missing is different implementations of the interface for
different Captchas. Switching them out should be a breeze

This way it is easy to use Captchas if you need to (You still should not
and you should make your managers understand why not!) but there is no
need for a specific captcha-related interface.

My 0.02
OpenPGP_signature.asc

LeTraceurSnork

unread,
Jul 2, 2025, 7:27:03 AMJul 2
to PHP Framework Interoperability Group
@AndreasHeigl, I agree that Captchas itself may be an antipattern (which is disputable, but anyway), but I guess thatyou mean Captchas in a narrow sense - those Google Captchas with disappearing traffic lights and stuff (or even older ones with curly texts) - yeah, they probably are. But in terms of this PSR, proposal, interface I implied Captcha in a broad sense - ANY kind of check that returns stringified $token that can be verified afterwards. It doesn't needs to be traffic lights, it doesn't needs to even be visible - there are bunch of invisible Captchas nowadays - ReCaptcha V3, for example. Another example - SmartCaptcha, it's even better, it's invisible at first, but if you have "bad score" - only then it appears and asks you for... curly texts, traffic lights, etc. xD
Proposed interface doesn't tell you where from to get that token - you may randomly generate it if you want, take it from another API, hire a bouncer that will tel "you pass, you don't" - the origins of the token is a blackbox, and the scenario begins only after token was already passed
I can easily see how invisible Captchas implements this interface (actually, one already do - you can see my example if you wish https://github.com/LeTraceurSnork/unofficial-captcha-sdk/pull/1 - still a PR, unfortunately, but soon-to-be-merged)
I can easily see how non-external Captchas pass this (those ones with 4-digits code in colors, or the ones with formulas like "calculate 25+12")
I can even see how no-captchas solutions may pass this (User-Agents, IPs, etc. - generates a token, stash it to session and verify it on backend)

So, while I partially may agree with your point, it has no direct connection to PSR, cause Captcha isn't always ... Captcha? xD Sometimes it's different kind of tests

вторник, 1 июля 2025 г. в 11:02:42 UTC+5, Andreas Heigl:

Alexander Makarov

unread,
Jul 11, 2025, 8:28:40 AMJul 11
to PHP Framework Interoperability Group
I support the effort and will join the WG. There are many CAPTHCAs in the wild. They're mostly evil, but we have to deal with these and having a common interface that works will make our lives easier.

LeTraceurSnork

unread,
Jul 14, 2025, 10:03:29 AMJul 14
to PHP Framework Interoperability Group
@samdark, thank you very much and welcome aboard! :-) Waiting for everyone else here!

Finally got my hands on this, so, here is my own implementation of proposed interface as I see it:
I believe, it will be easier to discuss something that is not abstract, but have at least some shape.
But it's not a final form carved in stone, of course, it's just v1, which may be reworked in the process of further discussion

--
Sincerely,
LeTraceurSnork
Reply all
Reply to author
Forward
0 new messages