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

Authenticator Laravel Package

wolfcode/authenticator

A Laravel authentication package for wolfcode/authenticator, offering a simple way to add login, registration, and access control to your PHP applications. Lightweight and easy to integrate.

View on GitHub
Deep Wiki
Context7

Getting Started

wolfcode/authenticator is a small, unopinionated PHP library for the "authenticator app" half of two-factor authentication — the TOTP/HOTP style codes you'd scan into Google Authenticator, Authy, 1Password, etc. It is not a Laravel package with guards, middleware, migrations, or a service provider you can lean on; treat it as a primitive you wrap in your own application code.

Minimal path in a Laravel app:

  1. composer require wolfcode/authenticator and confirm the autoloader picks it up (composer dump-autoload).
  2. Open vendor/wolfcode/authenticator/src/ first. There is no meaningful documentation surface at 0 stars — the source is the spec. Identify the entry class and note: does it return an otpauth:// provisioning URI, a raw Base32 secret, or both? Does it generate QR images or only URIs? Does it accept a window/drift parameter on verification?
  3. Check composer.json for extra.laravel and any illuminate/* requirements. If there is no service provider, there's nothing to publish — you'll instantiate the class yourself and bind it in a TwoFactorService of your own.
  4. First use case: enrollment. Generate a secret on demand, persist it against the user (not yet "enabled"), render the provisioning URI as a QR code with bacon/bacon-qr-code or endroid/qr-code, and require one successful code entry before flipping the user to two_factor_enabled = true.

The fastest sanity check before writing any app code is a throwaway route that generates a secret, prints the otpauth:// URI, adds it to your phone, and verifies a code. If that round-trip works, the library does what you need and everything after is your own plumbing.

Implementation Patterns

Wrap it, don't sprinkle it. Define an interface in your domain (TwoFactorProvider with generateSecret(), provisioningUri(), verify()) and implement it against this package. Given the maturity signals here, you want a one-file swap to pragmarx/google2fa if you ever need to move. Bind it in a service provider and inject it.

Enrollment flow (the one you'll actually write):

  • Generate the secret server-side; never let the client choose it.
  • Store it in a dedicated column, cast as encrypted (Laravel's encrypted cast uses APP_KEY). A TOTP secret is a long-lived shared credential — treating it as plaintext is the most common mistake in this space.
  • Keep enrollment and activation separate: two_factor_secret set but two_factor_confirmed_at null until the first valid code. Otherwise users lock themselves out with a mistyped scan.
  • Generate 8–10 single-use recovery codes at confirmation time, hash them (Hash::make), and show them once.

Login flow:

  • After password validation succeeds, if the user has 2FA enabled, put them in a short-lived "pending 2FA" state (session flag or a signed temporary token) rather than fully authenticating them. Don't call Auth::login() until the code checks out.
  • Verify inside a FormRequest or a dedicated action, not in the controller body.
  • On success, record two_factor_last_used_at (or the TOTP time-step) and clear the pending state.

Replay protection. A TOTP code is valid for its whole 30-second window (plus any drift window the library allows). Persist the last accepted time-step and reject anything <= it. Otherwise a code captured from a shoulder-surf or a logged request is reusable for up to a minute and a half.

Rate limiting. Codes are 6 digits. Without throttling, an attacker with a valid password brute-forces the second factor in a few thousand requests. Use Laravel's RateLimiter keyed on user ID + IP (5 attempts / 5 minutes is a reasonable start), and lock the challenge after N failures requiring a fresh password login.

Recovery codes belong in their own table or JSON column, each marked consumed on use, with the same rate limiting and an audit log entry.

Testing. Freeze time so tests are deterministic — Carbon::setTestNow() combined with the library's verification call. Cover: valid current code, code from one step ago (should pass only if your window allows), code from ten steps ago (must fail), a code already consumed (must fail), and a malformed/whitespace-padded input. If the library exposes a step-based API, test against the RFC 6238 test vectors rather than trusting generated values.

Blade/UI integration. Show the QR plus the manual Base32 secret as a copyable string — a meaningful share of users are on desktop and want to type it into a phone app. Also surface the otpauth:// URI as a fallback link for mobile.

Gotchas and Tips

Server clock drift is the #1 support ticket. TOTP is entirely time-based. If your app server's clock is off by 40 seconds, every code fails and you'll blame the library. Ensure NTP (chrony/systemd-timesyncd) is running on every app node, and set a drift window of ±1 step in the verifier. Don't widen it beyond ±1 — each extra step roughly doubles the brute-force surface.

APP_KEY rotation invalidates every enrolled secret. If you use the encrypted cast, rotating the key without re-encrypting (or keeping the old key in APP_PREVIOUS_KEYS) silently locks out every 2FA user. Plan for it or store the secret with a dedicated key managed separately.

Base32 input hygiene. Users paste secrets with spaces, lowercase letters, and padding = characters. Normalize before verifying: uppercase, strip whitespace and =. Most libraries are strict, and a mismatch looks like "the code is wrong" rather than "the secret is malformed."

Zero stars and no dependents means zero independent scrutiny. This is a security-sensitive primitive handling a shared secret. Before shipping: read every line of src/ (it's small — that's the upside), confirm it uses random_bytes/random_int for secret generation and hash_equals for comparison, and check that the release tag matches what you reviewed. Pin an exact version ("wolfcode/authenticator": "1.0.0") rather than a caret range, and add it to whatever dependency-review process you have.

Check the Base32 alphabet and secret length. TOTP secrets should be ≥160 bits (32 Base32 chars) per RFC 4226. If the generator defaults to something shorter, generate your own and feed it in.

QR codes are probably not included. Most lean packages in this space emit the otpauth:// URI only. Budget for bacon/bacon-qr-code (pure PHP, no Imagick requirement) or endroid/qr-code. Build the URI yourself if needed: otpauth://totp/{issuer}:{account}?secret={base32}&issuer={issuer}&algorithm=SHA1&digits=6&period=30 — URL-encode the label, because email addresses contain @ and issuers contain spaces.

No service provider means no config file. Don't hunt for config/authenticator.php. Put your settings (window, issuer, digits) in your own config/auth.php or a dedicated config/two_factor.php that you author and that your wrapper reads.

Don't gate the whole app behind 2FA on day one. Ship it as opt-in, then enforce per-role once you've watched failure rates and support volume for a couple of weeks. An aggressive rollout with a clock-drift bug produces a login outage that looks like a breach.

Have an admin reset path. Support staff need a way to clear a user's two_factor_secret and confirmed_at after identity verification. Build it before launch, log it loudly, and rate-limit it — it's the softest target in any 2FA implementation.

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