Keycloak
Official CaptchaLa plugin for Keycloak. Adds a CAPTCHA challenge to Keycloak's built-in login, registration and reset-password screens, verified server-side, without writing any code. Ships as a single provider JAR you drop into Keycloak.
What it covers
Each flow below is wired in as a separate authentication step — you protect only the screens you want.
- Browser login (the username / password form)
- Self-registration
- Reset password (the "forgot password" screen)
The challenge renders as a floating widget by default (float), or as a click-to-open modal (popup).
Install
1. Get the JAR
The plugin is open source at github.com/Captcha-La/captchala-keycloak. Two options:
- Download the release (recommended) — grab
keycloak-captchala-<version>.jarfrom the repository's Releases page. - Build from source —
git clonethe repo and runmvn clean package; the JAR is produced undertarget/.
The plugin targets Keycloak ≥ 26 (Quarkus) and Java 17.
2. Deploy it
cp keycloak-captchala-1.0.0.jar /opt/keycloak/providers/
/opt/keycloak/bin/kc.sh build
# restart KeycloakThen set the login theme: Realm settings → Themes → Login theme → captchala.
3. Get your keys
Sign up at dash.captcha.la, create an application, then copy:
- App Key — public, embedded in the page
- App Secret — server-side only, used by Keycloak to mint a one-time token and call
/v1/validate
4. Wire the flows
In the admin console, add the matching execution to each flow you want protected, then click the gear icon to paste your App Key and App Secret:
- Browser login — duplicate the browser flow, replace Username Password Form with Captchala Username Password Form (REQUIRED), bind it as the realm browser flow.
- Registration — duplicate the registration flow, add Captchala Registration (REQUIRED) to the registration-form sub-flow, bind it as the realm registration flow.
- Reset password — duplicate the reset credentials flow, replace Choose User with Captchala Reset Credential (choose user) (REQUIRED), bind it as the realm reset-credentials flow.
Open one of the protected screens in a private window to confirm the challenge renders.
Configuration
Every execution is configured independently from its gear icon. The defaults work out of the box once the keys are set.
| Setting | Key | Default | Description |
|---|---|---|---|
| App Key | app.key | — | Public key from the CaptchaLa dashboard. Required. |
| App Secret | app.secret | — | Server secret. Required. Stored masked, never exposed to the browser. |
| API base URL | api.base | https://apiv1.captcha.la | CaptchaLa API base. |
| Widget script URL | script.url | https://api.captcha.la/sdk/jslib/captchala.js | Where the widget JS loads from. |
| Widget CSS URL | css.url | https://api.captcha.la/sdk/jslib/captchala.css | Where the widget CSS loads from. |
| Render mode | product | float | float (floating widget) or popup (modal). |
| Action label | action | per flow | The action sent on validation (login, register, reset). |
| Language | language | realm locale | Widget language; blank follows the Keycloak locale. |
| Fail closed | fail.closed | true | When the CaptchaLa API is unreachable, deny the submission. Turn off to fail open. |
| Use server token | use.server.token | true | Mint a one-time server token at render for stronger anti-replay. |
FAQ
Is the plugin free?
Yes. The Keycloak plugin is free and open source. The CaptchaLa free plan covers 10,000 verifications a month — paid plans only apply if you need more volume.
Which Keycloak versions are supported?
Keycloak 26+ on the Quarkus distribution, built against 26.5.6 with Java 17. Drop the JAR into providers/, run kc.sh build, and restart.
Which screens can it protect?
Browser login, self-registration, and reset password. Each is added to its flow independently, so you can protect one, two, or all three.
Is the App Secret ever exposed to the browser?
No. The secret is stored masked and is only ever sent in the X-App-Secret header from Keycloak to the CaptchaLa API. It never appears in any page, template, or log. Each challenge is verified with a single-use token, so a solved token can't be replayed.
What happens if the CaptchaLa API is unreachable?
By default the plugin fails closed (the submission is denied). Set fail.closed to off on any execution to fail open instead — useful for staged rollout, not recommended for production.
Source
- Plugin repository:
github.com/Captcha-La/captchala-keycloak - Releases (JAR):
github.com/Captcha-La/captchala-keycloak/releases - Issues / feature requests: filed against the repository above
- Related: Web SDK · API Reference