huluti / altcha-bundle
A simple package to help integrate Altcha on Symfony.
Package info
github.com/tito10047/altcha-bundle
Type:symfony-bundle
pkg:composer/huluti/altcha-bundle
Requires
- php: >=8.2
- altcha-org/altcha: ^v2.0
- symfony/console: ^6.4|^7.4|^8.0
- symfony/form: ^6.4|^7.4|^8.0
- symfony/http-client: ^6.4|^7.4|^8.0
- symfony/translation: ^6.4|^7.4|^8.0
- symfony/twig-bundle: ^6.4|^7.4|^8.0
- symfony/validator: ^6.4|^7.4|^8.0
- symfony/yaml: ^6.4|^7.4|^8.0
Requires (Dev)
- ext-ctype: *
- ext-iconv: *
- dbrekelmans/bdi: ^1.4
- phpstan/phpstan: ^1.8
- phpstan/phpstan-symfony: ^1.2
- phpunit/phpunit: ^10.5
- rector/rector: ^0.14.5
- symfony/asset-mapper: ^6.4|^7.4|^8.0
- symfony/debug-bundle: ^6.4|7.4.*|^8.0
- symfony/dotenv: ^6.4|7.4.*|^8.0
- symfony/framework-bundle: ^6.4|^7.4|^8.0
- symfony/panther: ^v2.4.0
- symfony/runtime: ^6.4|7.4.*|^8.0
- symfony/stimulus-bundle: ^2.30
- symfony/web-profiler-bundle: ^6.4|7.4.*|^8.0
- symfony/webpack-encore-bundle: ^2.3
- twig/twig: ^2.12|^3.21.1
This package is auto-updated.
Last update: 2026-08-29 09:20:40 UTC
README
This packages integrates ALTCHA, a privacy-friendly Captcha alternative, with Symfony forms.
Simply add an AltchaType field to your form and this package will automatically check the challenge issue.
ALTCHA uses a proof-of-work mechanism to protect your website, APIs, and online services from spam and unwanted content.
Unlike other solutions, ALTCHA is free, open-source and self-hosted, does not use cookies nor fingerprinting, does not track users, and is fully compliant with GDPR.
Say goodbye to tedious puzzle-solving and improve your website's UX by integrating a fully automated proof-of-work mechanism.
Support
- Symfony 6.4 | 7.4 | 8.0+
- PHP 8.2+
- Webpack | Asset Mapper | Twig
Installation
You can install the package via Composer:
composer require tito10047/altcha-bundle
Add bundle into config/bundles.php file:
Tito10047\AltchaBundle\AltchaBundle::class => ['all' => true]
Add a config file:
YML
config/packages/altcha.yaml
altcha: enable: true hmacSignature: '%env(APP_SECRET)%' # Replaces deprecated hmacKey hmacAlgorithm: 'SHA-256' hmacKeySignature: ~ # Optional signature key cost: 5000 counter_min: 5000 counter_max: 10000 timeout: 30.0 floating: true overlay: false use_stimulus: false include_script: true hide_logo: false hide_footer: false when@test: altcha: enable: false
Import bundle routes:
YML
altcha: resource: '@AltchaBundle/config/routes.yml' type: yaml
⚠️ Important – Security Configuration
If your application restricts access globally using a rule like:
access_control: - { path: ^/, roles: ROLE_USER }
Then the Altcha challenge endpoint (/altcha/challenge) will also be protected by default.
To allow it to be publicly accessible (as intended for the challenge mechanism to work), you must explicitly add the following rule before the global one:
access_control: - { path: ^/altcha/challenge, roles: PUBLIC_ACCESS } - { path: ^/, roles: ROLE_USER }
This ensures that the challenge endpoint is reachable by unauthenticated users, while keeping the rest of your app secure.
Use with your Symfony Form
Create a form type and insert an AltchaType to add the captcha:
<?php namespace App\Form; use App\Entity\Contact; use Tito10047\AltchaBundle\Type\AltchaType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; class ContactType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder ->add('name', TextType::class, ['label' => false, 'attr' => ['placeholder' => 'name']]) ->add('message', TextareaType::class, ['label' => false, 'attr' => ['placeholder' => 'message']]) ->add('security', AltchaType::class, [ 'label' => false, 'floating' => true, 'hide_logo' => false, 'hide_footer' => false, // Optional: override global config // 'cost' => 5000, // 'timeout' => 30.0, // 'counter_min' => 5000, // 'counter_max' => 10000, ]) ->add('submit', SubmitType::class) ; } public function configureOptions(OptionsResolver $resolver): void { $resolver->setDefaults([ 'data_class' => Contact::class, ]); } }
Use with Webpack Encore
//webpack.config.js module.exports = Encore.getWebpackConfig(); module.exports.resolve.alias["altcha/dist/i18n/all.js"]='altcha/i18n';
#config/packages/altcha.yaml altcha: use_stimulus: true include_script: false
Optional: usage with UX Live components
There is only one option need to be changed to work with or UX Live component.
altcha: use_stimulus: true floating: false include_script: false
Optional: usage with Sentinel
Configure the package by providing your sentinel instance endpoint and your API key:
altcha: sentinel: base_url: 'http://localhost:8080' api_key: 'key_xxxxxxxxxxxx'
Activating this configuration will have the effect to use the sentinel server to generate a new challenge and for it's verification. If the sentinel instance is not reachable by the client or by the server, we will fallback on our local configuration.
Need stronger protection?
ALTCHA is invisible to the user, but proof-of-work alone only makes submitting a form expensive — it cannot tell a patient bot from a human. If your forms are being hit by targeted spam that is willing to pay that cost, add a challenge the visitor has to solve.
For that case I recommend tito10047/iconcaptcha-bundle,
a Symfony integration of IconCaptcha:
the visitor picks the least-common icon out of five to eight. It is self-hosted as well —
no third-party service, no tracking, no API key — and it integrates exactly the same way
as this bundle: install it, import its route, and add a single field to your form type.
composer require tito10047/iconcaptcha-bundle
->add('security', \Tito10047\IconcaptchaBundle\Type\IconCaptchaType::class, [ 'label' => false, ])
Both bundles can live side by side — use ALTCHA where UX matters most and IconCaptcha on the few endpoints that need a real challenge.
License
The MIT License (MIT). Please see License File for more information.