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

Default Authenticator Extension Laravel Package

anomaly/default_authenticator-extension

Default authenticator extension for Anomaly that gives Laravel applications a ready-made authentication layer out of the box. Drop it in to handle standard credential checks and user sessions without custom wiring.

View on GitHub
Deep Wiki
Context7

Getting Started

What it actually is. anomaly/default_authenticator-extension is a Streams Platform extension addon for the anomaly/users-module. It contributes the "default" authenticator — the plain email/username + password check — into the Users module's authenticator extension group. It contains almost no business logic of its own; it is a thin, registered implementation of the Users module's authenticator contract. That framing matters for everything below: you almost never call this package directly, you call the Users module and this extension is what answers.

Minimal install.

composer require anomaly/default_authenticator-extension
php artisan addon:install anomaly/default_authenticator-extension
php artisan addon:publish anomaly/default_authenticator-extension   # only if it ships config/lang/migrations

Then confirm it registered:

php artisan addon:list | grep -i authenticator

Where to look first. In this order:

  1. src/ — usually one extension class (e.g. DefaultAuthenticatorExtension) plus one authenticator class implementing the Users module contract. Read these before anything else; it is a small package and the whole behaviour is there.
  2. resources/config/ and resources/lang/en/addon.php — the name/description and any credential-field config.
  3. The $provides property on the extension class — this string is the wiring key (e.g. anomaly.module.users::authenticator.default). Everything hinges on it matching what the Users module looks up.
  4. The Users module's own src/User/Authenticator/ directory in vendor/anomaly/users-module — that is the contract and the caller.

First use case. You do not write code for this. The first "use" is verifying that a standard login form posts email + password, the Users module resolves the default authenticator, and your seeded user authenticates:

// tinker or a throwaway route
$users = app(\Anomaly\UsersModule\User\Contract\UserRepositoryInterface::class);
$users->findByEmail('[email protected]');        // does the user exist?
Auth::attempt(['email' => '[email protected]', 'password' => 'secret']); // does it authenticate?

If Auth::attempt() returns false while the user exists and you know the password is correct, the problem is wiring or hashing, not this package's logic — jump to Gotchas.

Implementation Patterns

Consume the Users module, not the extension. The correct day-to-day pattern is to depend on the authenticator contract (or just Auth), never on Anomaly\DefaultAuthenticatorExtension\... classes. This keeps you swappable for SSO/LDAP later:

use Anomaly\UsersModule\User\Contract\AuthenticatorInterface;

public function login(AuthenticatorInterface $auth, Request $request)
{
    return $auth->authenticate($request->only('email', 'password'));
}

Bind against the interface in a service provider if you need to inject a specific implementation in tests.

Treat it as the fallback in a chain. The extension-group design exists so you can add authenticators (LDAP, OAuth, magic link) and keep the default as the last resort. Build your custom authenticator as its own extension addon implementing the same contract, register it in the same group, and let ordering decide precedence. Your custom one returns null/"not handled" for unknown users so the default still runs — do not return false for "not mine", or you break the chain.

Credential-field mapping. The default authenticator assumes the Users module's configured login field (email, typically, sometimes username). If your app authenticates by username, change it at the Users module config level rather than forking this package:

// config/anomaly/module/users.php (or the addon's published config)
'login' => 'username',

Then teach your login form and any Auth::attempt() calls to send that key. Mismatch here is the single most common cause of "the authenticator rejects valid users".

Reuse it for non-form logins. API login, post-registration auto-login, and admin impersonation should all route through the same contract so hashing, activation checks, and throttling stay in one place:

if (! app(AuthenticatorInterface::class)->authenticate($credentials)) {
    abort(401);
}

Password migration pattern. When importing users from a legacy system, hash into the users.password column using Laravel's hasher before the first login:

$user->password = Hash::make($plaintext);

If you cannot pre-hash, log the user in via a custom authenticator that verifies the legacy hash and then rehashes — and keep the default authenticator out of that path so you don't accidentally accept legacy formats forever.

Testing. In feature tests, don't hit the real authenticator; bind a fake implementation of AuthenticatorInterface in the container. Keep one integration test that exercises the real default authenticator against a seeded user, because the wiring (the $provides string) is exactly what unit tests miss.

Gotchas and Tips

Silent-failure wiring is the #1 pitfall. If the extension is installed but not enabled, or if its $provides key doesn't match what the Users module resolves, logins fail with a generic "credentials invalid" rather than a clear "no authenticator". Check php artisan addon:list, check the Users module's core.php/config extension list, and log the resolved authenticator class once during debugging.

Caches bite after every change. Extension registration is cached. After install, enable, or a composer update:

php artisan cache:clear
php artisan view:clear
php artisan addon:install anomaly/default_authenticator-extension
composer dump-autoload

In local dev, a bootstrap/cache stale addon manifest produces "class not found" for a class that plainly exists.

Hashing must match the users module. The default authenticator checks the stored hash; it does not read plaintext and it does not auto-rehash legacy formats. bcrypt vs argon2id mismatches (after a config/hashing.php change) will reject everyone. Verify with Hash::check() in tinker before blaming the package.

Never edit vendor/. The package is tiny and stable; if you need different behaviour, write your own extension addon that implements the contract, or subclass the shipped authenticator and re-register your subclass under the same $provides key. A subclass plus a one-line service-container rebind is much cheaper than a fork.

Debug the boundary, not the internals. Because the logic is trivial, failures are almost always at the edges: is the user active/confirmed? is the password column non-null? is there a global scope or repository override filtering users? Dump the user record before the auth call, and put a temporary Log::debug() around the contract call site in your own code — don't add debug statements inside a vendor file you'll forget to revert.

Version-pin and plan for abandonment. This is a zero-star, near-zero-dependent package whose entire surface is a contract implementation plus a $provides string. That is a feature: pin the exact version in composer.json, and if it ever goes unmaintained, replacing it is a ~40-line class you can own outright. Don't spread knowledge of it across your codebase — keep every reference behind AuthenticatorInterface so the swap is a container binding, not a refactor.

Check compatibility on upgrade, not on install. Because the package is a contract implementation, a major bump of anomaly/users-module can change the authenticator interface while this extension sits on an old tag. When you upgrade the Users module, re-run the login integration test — that is the only place the breakage surfaces.

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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator