Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Login Captcha Laravel Package

lake/login-captcha

lake/login-captcha adds captcha protection to Laravel login forms with minimal setup. It integrates with the default authentication flow, helps block automated login attempts, and provides simple configuration for captcha rendering and validation. Ideal for quickly securing login pages.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Dcat-admin extension, so it slots into Dcat-admin's existing extension system rather than a plain Laravel package. The value proposition is narrow and clear: put a captcha on the /admin/auth/login screen to blunt scripted credential stuffing and password spraying against your admin panel.

Before you install, confirm your baseline:

  • Dcat-admin 2.x is installed and the admin panel boots (php artisan admin);
  • PHP has the gd extension enabled (php -m | grep gd) — image-based captchas fail hard without it;
  • Your session driver is shared if you run more than one app node (see Gotchas).

Install and register:

composer require lake/login-captcha
php artisan admin:import lake/login-captcha

admin:import is the Dcat-admin convention: it records the extension in config/admin.php under extensions and runs the package's install routine (publishing views/config/assets). If the import command complains about the name, use the service provider directly:

php artisan vendor:publish --provider="Lake\\LoginCaptcha\\LoginCaptchaServiceProvider"

Where to look first:

  1. vendor/lake/login-captcha/README.md and src/ — the service provider tells you exactly which routes, views, and config keys are registered. The package is small enough to read end-to-end in a few minutes.
  2. php artisan route:list | grep -i captcha after install to confirm the image endpoint exists.
  3. The published config file (typically config/login-captcha.php) for length, size, expiry, case sensitivity, and — as of 1.0.11 — the captcha position setting that controls where the captcha field is rendered on the login form.
  4. If you are upgrading rather than installing fresh, diff the package's config/ directory against your published copy — 1.0.11 adds a new key that your existing published config will not contain (see Gotchas).

First real use case: log out, hit /admin/auth/login, and verify the image renders in the position you configured, the refresh link works, and a wrong code is rejected server-side (not just client-side). That last check is the one most people skip — a captcha that only validates in JavaScript is decorative.

Implementation Patterns

1. Toggle-by-environment. Captcha on the login form makes automated testing and local development painful. Wire the package's enable flag (or a config override) to app()->environment() / config('app.env') so local and testing skip validation while production enforces it. Publish the config and commit it; do not rely on the package default.

2. Treat it as defense-in-depth, not the defense. Pair it with Dcat-admin's login throttling / a RateLimiter on the login route. The captcha stops naive bots; the rate limiter stops everything else. A captcha alone does not stop distributed attempts.

3. Reuse the validation rule in custom auth flows. If you have a second login surface (a separate guard, an SSO callback form, an API token endpoint with a human step), don't hand-roll validation — use the same rule/facade the package registers so the session-key format stays consistent:

$request->validate([
    'captcha' => ['required', 'captcha'], // confirm exact rule alias in the README
]);

If the package exposes a facade instead, call Captcha::check($request->input('captcha')) before authenticating. Either way, validate before hitting the credential check so failed captchas don't count against the user's password attempts.

4. Refresh affordance and field placement. The login blade should give users a click-to-refresh image and an accessible label. As of 1.0.11 the placement of the captcha field on the login form is configurable — use that setting rather than forking the login view just to move the input above or below the password field. If you use a custom Dcat-admin theme that overrides admin::pages.login, the position setting may not apply to your override; you must merge the captcha field into that override yourself or it will silently disappear after a theme update.

5. Customization via config, not edits. Length, image dimensions, character set, TTL, and now field position are almost always in the published config. Adjust there. Only override the view if you need branding (your logo inside the image, dark-mode colors, non-standard DOM placement); keep the override namespaced and documented so the next upgrade doesn't clobber it — and note in that doc that the position config no longer governs your rendering.

6. Session-key discipline. Captchas are stored in the session keyed to the login form. Whatever you do, keep the same session across form render → submit. If you introduce a subdomain split (e.g., assets on static.), set the session cookie domain to cover both, or the captcha will always fail for users.

7. Rollout pattern. Ship it behind a config flag defaulting to off, enable in staging, watch login failure rates and support tickets for 48 hours, then enable in production. Captcha friction is a common cause of "I can't log in" tickets, especially for non-technical admins. If you change the position setting post-launch, treat it as a UI change worth a quick note to admins — muscle memory matters on a login screen.

Gotchas and Tips

  • Published configs don't auto-merge. The position setting added in 1.0.11 is a new config key. If you installed an earlier version, your committed config/login-captcha.php will not have it, and the package will fall back to its default position — which may not be the one you want, and will differ from a fresh install. Republish (into a temp dir and diff, don't blow away your edits) or add the key manually, and do this deliberately on every upgrade of this package.
  • Verify the position option actually applies to your view. If you or your theme overrides the login blade, the new setting is likely inert. Check the rendered HTML after changing the value, not just the config file.
  • Shared sessions are non-negotiable. The captcha answer lives in the session. With a load balancer and local file sessions, a user's POST can land on a node that never issued the captcha. Use Redis or the database session driver across all nodes.
  • Missing GD = blank image or 500. This is the #1 install failure. Check php -m on every node and in the Docker image, not just locally.
  • CDN / page caching on the login route will break it. The login page must be uncacheable (Cache-Control: no-store) and the captcha image endpoint must be excluded from any edge cache. Otherwise every user sees the same stale image.
  • Regenerating invalidates the previous answer. Each request to the image endpoint rotates the session key. If your front-end preloads the image twice (a common <img src> plus a JS preload), users will submit an answer that no longer matches. Preload once.
  • Case sensitivity and character sets. Characters like 0/O, 1/l/I cause false rejections. Most captcha libraries let you exclude ambiguous characters; verify the config exposes that and turn it on. Confirm whether validation is case-insensitive by default — if not, decide deliberately.
  • Expiry. A short TTL is good security but bad UX for slow logins. 5 minutes is a reasonable default; don't drop below 2.
  • Debugging checklist: php artisan route:list (route registered?), browser Network tab (image returns 200 with image/png?), storage/logs/laravel.log (validation exception?), the rendered login HTML (is the field where you expect it?), and session()->getId() consistency between the GET and POST via a temporary log line.
  • Test bypass: in phpunit.xml set the env flag your config reads, or bind a fake captcha implementation in a test service provider. Do not disable captcha globally in phpunit.xml if you also run browser/E2E tests that should exercise the real login path — scope the bypass to unit test suites. A position-only release does not change validation behaviour, so existing bypasses keep working.
  • Compatibility risk is real. Releases are sporadic (this 1.0.11 follows a long gap since the March 2023 release), the package has ~32 stars and zero dependents, and 1.0.11 is a small UI-oriented patch that touches the login view — exactly the surface most likely to conflict with Dcat-admin theme overrides. Before adopting on a current stack, verify it boots against your Dcat-admin and Laravel versions, and check whether a minor Laravel upgrade (session/cookie internals) breaks it. If it does, the fallback is trivial: the package is a thin wrapper around a standard captcha library, and you can reproduce the same feature with mews/captcha (or gregwar/captcha) plus a small login-view override — likely in under an hour. Budget for that possibility.
  • Pin the version and record the decision. For a package this small and this sparsely maintained, treat it as vendored code: pin an exact version in composer.json (including 1.0.11's new position key in your runbook notes), and be ready to fork. Also confirm the Apache-2.0 license notice is retained if you do fork.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route