symfony/security-http
Symfony Security HTTP integrates the Security Core with HTTP: firewalls, request handling, and authenticators to secure parts of your app and authenticate users. Install via composer require symfony/security-http.
To integrate symfony/security-http into a Laravel project, start by installing the package and its dependencies:
composer require symfony/security-core symfony/security-http symfony/security-bundle
Leverage Laravel’s service container to configure a firewall in config/security.php (or a custom config file):
// config/security.php
'firewalls' => [
'main' => [
'pattern' => '^/', // Applies to all routes
'stateless' => false,
'providers' => [
'users' => [
'entity' => [
'class' => App\Models\User::class,
'property' => 'email',
],
],
],
'entry_point' => 'authentication', // Uses Symfony's AuthenticatorInterface
'authenticators' => [
'form_login' => [
'class' => Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator::class,
'form_page' => '/login',
'check_path' => '/login_check',
'login_path' => '/login',
'username_parameter' => 'email',
'password_parameter' => 'password',
'csrf_parameter' => '_csrf_token',
'csrf_token_id' => 'authenticate',
'csrf_token_manager' => 'security.csrf_token_manager',
],
],
'logout' => [
'path' => '/logout',
'target' => '/',
],
],
],
In config/app.php, add the Symfony Security Bundle to the providers array:
'providers' => [
// ...
Symfony\Bundle\SecurityBundle\SecurityBundle::class,
],
Create a custom authenticator (e.g., app/Http/Authenticators/CustomAuthenticator.php):
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class CustomAuthenticator extends AbstractAuthenticator
{
public function supports(Request $request): ?bool
{
return $request->isMethod('POST') && $request->getPathInfo() === '/login';
}
public function authenticate(Request $request): TokenInterface
{
$email = $request->request->get('email');
$password = $request->request->get('password');
if (!$email || !$password) {
throw new AuthenticationException('Credentials required.');
}
// Fetch user from your Laravel model (e.g., User::where('email', $email)->first())
$user = User::where('email', $email)->first();
if (!$user || !Hash::check($password, $user->password)) {
throw new AuthenticationException('Invalid credentials.');
}
return new UserToken($user, $this->passwordEncoder->encodePassword($user, $password));
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewall): ?Response
{
return new RedirectResponse('/dashboard');
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
return new RedirectResponse('/login?error=1');
}
}
In your AppServiceProvider's boot() method:
public function boot()
{
$this->app->make(Symfony\Component\Security\Http\SecurityEvents::AUTHENTICATION_SUCCESS)
->listen(function ($event) {
// Custom logic on successful auth
});
$this->app->bind(
Symfony\Component\Security\Http\Authenticator\AuthenticatorManagerInterface::class,
function ($app) {
return new Symfony\Component\Security\Http\Authenticator\AuthenticatorManager(
$app->make(Symfony\Component\Security\Core\User\UserProviderInterface::class),
$app->make(Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface::class),
$app->make(Symfony\Component\Security\Http\Logout\LogoutHandlerInterface::class),
$app->tagged('security.authenticator')
);
}
);
}
Use middleware to apply firewalls to routes in app/Http/Kernel.php:
protected $routeMiddleware = [
'auth' => [
\Symfony\Component\Security\Http\Middleware\FirewallMiddleware::class,
'firewall' => 'main',
],
];
Apply it to routes:
Route::middleware(['auth'])->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
});
FirewallMiddleware intercepts requests and delegates to the AuthenticatorManager.FormLoginAuthenticator).TokenInterface.UserToken is stored in the session (or statelessly via JWT).#[IsGranted] attribute or AccessControl to enforce permissions.Leverage Symfony’s middleware within Laravel’s pipeline:
// app/Http/Middleware/Authenticate.php
use Symfony\Component\Security\Http\Middleware\FirewallMiddleware;
public function handle($request, Closure $next)
{
$firewall = $this->app->make(Symfony\Component\Security\Http\Firewall::class);
$firewall->addMiddleware(new FirewallMiddleware($firewall, $this->app->make('security.http_utils')));
return $firewall->handle($request, $next);
}
Extend AbstractAuthenticator for reusable logic:
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;
class ApiTokenAuthenticator extends AbstractAuthenticator
{
public function supports(Request $request): ?bool
{
return $request->headers->has('X-API-TOKEN');
}
public function authenticate(Request $request): Passport
{
$token = $request->headers->get('X-API-TOKEN');
$user = User::where('api_token', $token)->first();
return new SelfValidatingPassport(
new UserBadge($user->email)
);
}
}
Use Symfony’s #[IsGranted] attribute in controllers:
use Symfony\Component\Security\Http\Attribute\IsGranted;
class AdminController extends Controller
{
#[IsGranted('ROLE_ADMIN')]
public function index()
{
return view('admin.dashboard');
}
}
Enable CSRF protection in your firewall config:
'firewalls' => [
'main' => [
// ...
'csrf_protection' => true,
],
],
For API-based auth, use StatelessTokenStorage:
use Symfony\Component\Security\Http\Authenticator\Token\StatelessToken;
class JwtAuthenticator extends AbstractAuthenticator
{
public function authenticate(Request $request): ?TokenInterface
{
$token = $request->headers->get('Authorization');
if (!$token) {
return null;
}
$decoded = JWT::decode($token, $this->secret, ['HS256']);
$user = User::where('email', $decoded->user_email)->first();
return new StatelessToken($user, $this, ['ROLE_USER']);
}
}
Use Symfony’s ImpersonatorInterface for admin impersonation:
use Symfony\Component\Security\Http\Impersonator\ImpersonatorInterface;
class ImpersonateController extends Controller
{
public function __invoke(ImpersonatorInterface $impersonator, User $user)
{
$impersonator->impersonate($user);
return redirect()->to('/dashboard');
}
}
Firewall Order Matters:
main firewall should come after an api firewall if both match the same route.Token Persistence:
stateless: true in the firewall.'firewalls' => [
'api' => [
'pattern' => '^\/api',
'stateless' => true,
// ...
],
],
CSRF Token Mismatches:
csrf_token_id and csrf_parameter match the frontend’s tokenHow can I help you explore Laravel packages today?