symfony/security-bundle
Symfony SecurityBundle integrates the Security component into the Symfony full-stack framework, providing authentication, authorization, firewalls, user providers, and access control configuration for applications built with Symfony.
Installation:
composer require symfony/security-bundle
Add to config/bundles.php:
return [
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
];
Basic Configuration (config/packages/security.yaml):
security:
enable_authenticator_manager: true
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
firewalls:
main:
lazy: true
provider: app_user_provider
form_login: ~
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
First Use Case:
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[IsGranted('ROLE_USER')]
public function secureAction(): Response
{
return new Response('Secure content');
}
php bin/console debug:security to inspect roles, users, and voters.Form Login:
firewalls:
main:
form_login:
login_path: app_login
check_path: app_login_check
#[IsGranted('IS_AUTHENTICATED_FULLY')] to restrict routes.OAuth/OIDC:
firewalls:
main:
oauth:
resource_owners:
github: { client_id: ..., client_secret: ..., provider: oauth_github }
security:oidc-token:generate CLI command for testing.Role-Based Access Control (RBAC):
security:
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
#[IsGranted('ROLE_ADMIN')] in controllers or access_decision() in Twig.Voters: Custom voter for complex logic:
use Symfony\Component\Security\Core\Authentication\Voter\Voter;
class PostVoter extends Voter {
protected function supports(string $attribute, mixed $subject): bool {
return $attribute === 'EDIT_POST' && $subject instanceof Post;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool {
return $token->getUser() === $subject->getAuthor();
}
}
Register in security.yaml:
security:
voters:
- App\Security\PostVoter
Lazy Firewalls:
firewalls:
api:
lazy: true
provider: app_user_provider
stateless: true
json_login:
check_path: /api/login_check
Custom Entry Points:
firewalls:
main:
custom_authenticators:
- App\Security\CustomAuthenticator
firewalls:
main:
remember_me:
secret: '%kernel.secret%'
lifetime: 86400
path: /
security:
rate_limiter:
login:
storage: memory
policy: 10 per minute
Configure storage (e.g., Redis) in config/packages/security.yaml.
Symfony UX & Live Components:
Use #[IsGranted] with Live Components to dynamically show/hide UI elements:
#[IsGranted('ROLE_USER')]
public function userPanel(LiveComponentInterface $component): Response
{
return $this->renderComponent($component, ['user' => $this->getUser()]);
}
Messenger Integration:
Dispatch security events (e.g., AuthenticationSuccessEvent) via Messenger for async processing:
use Symfony\Component\Security\Http\Event\AuthenticationSuccessEvent;
public function onAuthenticationSuccess(AuthenticationSuccessEvent $event): void
{
$this->messageBus->dispatch(new UserLoggedIn($event->getUser()));
}
API Platform: Combine with API Platform’s security extensions for JWT/OAuth2:
security:
firewalls:
api:
pattern: ^/api
stateless: true
jwt: ~
Testing:
Use LoginLink for testing authenticated routes:
use Symfony\Component\Security\Http\Authenticator\Passport\LoginLink;
public function testSecureRoute(): void
{
$link = new LoginLink('https://example.com/login');
$client->followRedirects(true);
$client->request('GET', '/secure-route', [], [], ['HTTP_REFERER' => 'https://example.com']);
}
Deprecations:
eraseCredentials() in UserInterface (deprecated in Symfony 7.3+).Role Hierarchy:
ROLE_ADMIN → ROLE_USER → ROLE_ADMIN) cause infinite loops. Use security:role-hierarchy:dump to visualize:
php bin/console security:role-hierarchy:dump --format=mermaid
Lazy Firewalls:
stateless: true to avoid session issues.OIDC/OAuth2:
security:
oauth:
providers:
oidc:
jwks_uri: https://example.com/.well-known/jwks.json
cache: true
security:oidc-token:generate to debug token generation locally.Remember-Me:
secret is unique and stored securely (e.g., %kernel.secret%).COOKIE_USE_ONLY_HTTP_PATH=false in PHP to avoid local development issues.CSRF Protection:
POST):
security:
csrf_token_generator:
enabled: true
firewalls:
main:
csrf_protection: ~
stateless: true and handle CSRF manually (e.g., with custom tokens).Profiler:
_profiler/security)._profiler/security/access_decision)._profiler/security/voters).Logging:
monolog:
handlers:
security:
type: stream
path: "%kernel.logs_dir%/security.log"
level: debug
channels: ["security"]
CLI Commands:
php bin/console security:role-hierarchy:dump
php bin/console debug:security:users
php bin/console debug:security:voter
Common Errors:
firewalls reference a valid provider in security.yaml.UserProvider implementation and property in entity provider.csrf_token is included in forms and csrf_protection is enabled.AbstractAuthenticator for custom logic (e.g., API keys, JWT):
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
class ApiKeyAuthenticator extends AbstractAuthenticator {
public function supports(Request $request): ?bool {
return $request->headers->has('X-API-KEY');
}
public function authenticate(Request $request): Passport {
$apiKey = $request->headers->get('X-API-KEY');
return new ApiKeyPassport($apiKey);
}
}
Register in security.yaml:
security:
firewalls:
api:
custom_authenticators:
- App\Security
How can I help you explore Laravel packages today?