ruwork/manual-auth-bundle
Symfony bundle for manually authenticating users through Symfony Security, simplifying programmatic login flows such as custom sign-in, impersonation, or session-based authentication without extra boilerplate.
config/ will auto-load it. If you drop it into a Laravel app the only thing you'll get is a Ruwork\ManualAuthBundle\... namespace that never boots because Symfony's Bundle base class isn't part of Laravel's container. Treat it as a reference implementation of the "log a user in programmatically" pattern rather than a dependency you install.ManualAuthenticator / Security\ManualAuth service first. The whole point of the package is a single service that takes a UserInterface (or a username) and installs a TokenInterface into security.token_storage plus the session. If you only read one file, read that one — it's the equivalent of Laravel's Auth::login($user, $remember).composer require ruwork/manual-auth-bundle in a Symfony 3.4/4.x app, then register Ruwork\ManualAuthBundle\ManualAuthBundle in AppKernel. It targets PHP 7.1-era Symfony Security. On a modern Symfony 6/7 app the peer constraints will fight you, and on Laravel it simply won't boot.User, then instead of the Symfony service call you write:Auth::login($user, remember: true);
request()->session()->regenerate();
That is the entire feature the bundle exists to wrap. If that's what you need in Laravel, you do not need this package.
TokenStorageInterface::setToken() call, session persistence (_security_<firewall> in Symfony vs. login_<guard>_<hash> in Laravel), and any AuthenticationEvents::AUTHENTICATION_SUCCESS dispatch. Those four concerns map to Auth::login, SessionGuard, Login event, and AuthenticationException handling in Laravel.public function loginAction(Request $request, ManualAuth $manualAuth, UserRepository $users)
{
$user = $users->findOneBy(['magicToken' => $request->query->get('token')]);
$manualAuth->authenticate($user); // sets token + session
return $this->redirectToRoute('dashboard');
}
In Laravel the same flow is Auth::login($user). Don't try to reproduce the service layer — use the guard.
Guard-scoped authentication. Symfony firewalls map loosely to Laravel guards. If you maintain multiple guards (web, admin, api), the Symfony bundle supports naming a firewall; in Laravel use Auth::guard('admin')->login($user) and be explicit about which session key you're populating, otherwise Auth::check() on the wrong guard returns false and you'll chase a phantom bug.
"Login as" impersonation. The classic reason to reach for manual auth. Symfony pattern: authenticate the target user, stash the original admin id in the session, add a "stop impersonating" route. Laravel translation:
// start impersonating
session(['impersonator_id' => Auth::id()]);
Auth::login($targetUser);
session()->regenerate();
// stop
Auth::loginUsingId(session('impersonator_id'));
session()->forget('impersonator_id');
session()->regenerate();
The bundle's contribution is just the authenticate() call; everything else (audit log, UI, restore) is yours.
Post-registration auto-login. After create() in a registration controller, call the manual-auth service so the user's first request is authenticated. In Laravel this is the standard Auth::login($user) before redirecting — the framework's built-in Registered event and email_verification middleware cover the rest.
API/token flows without passwords. The bundle lets you mint an authenticated session from a verified bearer token. In Laravel prefer stateless Sanctum::actingAs($user) or a custom guard implementing Illuminate\Contracts\Auth\Guard; the Symfony token-storage approach assumes sessions, which is wrong for a real API.
Event hooks. Symfony fires SecurityEvents::INTERACTIVE_LOGIN when a manual auth happens. In Laravel, listen for Illuminate\Auth\Events\Login (it fires for Auth::login too) to attach last-login timestamps, audit trails, or 2FA re-checks. This is the cleanest extension point — the bundle has nothing extra to offer here that Laravel's event system doesn't.
composer.json. Evaluate it as a 200-line reference, nothing more.composer.json will pin symfony/security-bundle to a 3.x/4.x range. Modern Composer will either refuse to install or you'll --ignore-platform-reqs your way into a broken autoloader. If you're exploring the code, git clone and read it; don't fight the resolver.session()->regenerate() yourself. Forgetting it turns every magic-link into a session-fixation vector, and Auth::login alone does not regenerate.Auth::login() vs. Auth::loginUsingId() mismatch. The former needs a hydrated User model; the latter hits the DB by primary key. If you're coming from the Symfony bundle's authenticate($userOrUsername), note it accepts both shapes — Laravel does not, and passing a string to Auth::login() throws TypeError. Pick the right method deliberately.Auth::login($user, true) does. If you're porting behavior tests from a Symfony app, the "stays logged in after session expiry" expectation will differ.Auth::check() false negatives. If your manual login used Auth::guard('admin') but a middleware later calls bare Auth::check() (defaulting to web), you'll be "logged in" and "logged out" simultaneously. Always match guard names across login, middleware, and logout.UserPasswordEncoder's needsRehash logic. Laravel's EloquentUserProvider::validateCredentials handles this; Auth::login() does not. If password hash upgrades matter, do them in your normal login only.Illuminate\Auth\Events\Login / Logout / Failed, Auth::extend() for custom guards, and Auth::viaRequest() for request-based (token/header) auth. These cover every use case this bundle advertises, with first-party maintenance.interface ManualLogin { public function login(User $u): void; } with a Symfony impl today and Auth::login impl tomorrow.Bottom line for a Laravel developer: the package is effectively a non-starter as a dependency. Its single idea — "authenticate a user you've already verified by some out-of-band means" — is exactly Auth::login(), already in the framework. Use this repo as documentation of the pattern (especially the session-regeneration and event-dispatch requirements) and skip the composer require.
How can I help you explore Laravel packages today?