Weave Code
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

Security Core Laravel Package

symfony/security-core

Symfony Security Core provides the foundation for authentication tokens, roles, voters, role hierarchies, and access decision management. Use it to build flexible authorization logic decoupled from user providers and integrate fine-grained access checks into apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

To integrate symfony/security-core into a Laravel project, start by installing the package:

composer require symfony/security-core

First Use Case: Basic Authentication Check

Leverage the AccessDecisionManager to check user permissions in controllers or services:

use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Role\RoleHierarchy;

// Initialize components
$roleHierarchy = new RoleHierarchy(['ROLE_ADMIN' => ['ROLE_USER']]);
$accessDecisionManager = new AccessDecisionManager([
    new RoleVoter($roleHierarchy),
]);

// Simulate a logged-in user
$user = new \App\Models\User(['roles' => ['ROLE_ADMIN']]);
$token = new UsernamePasswordToken($user, 'main', $user->getRoles());

// Check if user has access
if (!$accessDecisionManager->decide($token, ['ROLE_ADMIN'])) {
    abort(403, 'Unauthorized');
}

Key Entry Points

  1. Authentication: Use AuthenticationTrustResolver, TokenStorage, and UserChecker for user validation.
  2. Authorization: Implement AccessDecisionManager with Voter classes (e.g., RoleVoter, AuthenticatedVoter).
  3. User Providers: Extend UserProviderInterface for custom user loading logic.

Implementation Patterns

Workflow: Role-Based Access Control (RBAC)

  1. Define Roles: Use RoleHierarchy to establish role inheritance (e.g., ROLE_ADMIN inherits ROLE_USER).
  2. Create Voters: Extend Voter for custom authorization logic:
    use Symfony\Component\Security\Core\Authorization\Voter\Voter;
    
    class CustomVoter extends Voter {
        protected function supports(string $attribute, mixed $subject): bool {
            return $attribute === 'EDIT_POST';
        }
    
        protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool {
            return $token->getUser()->canEditPost($subject);
        }
    }
    
  3. Integrate with AccessDecisionManager:
    $accessDecisionManager = new AccessDecisionManager([
        new RoleVoter($roleHierarchy),
        new CustomVoter(),
    ]);
    

Workflow: Token-Based Authentication

  1. Generate Tokens: Use UsernamePasswordToken or AnonymousToken for authentication:
    $token = new UsernamePasswordToken($user, 'main', $user->getRoles(), [
        'firewall' => 'admin',
    ]);
    
  2. Store Tokens: Use Laravel’s session or a custom TokenStorage implementation:
    $tokenStorage = new SessionTokenStorage(new NativeSession());
    $tokenStorage->setToken($token);
    
  3. Check Authentication: Retrieve the token in middleware or services:
    $token = $tokenStorage->getToken();
    if (!$token || !$token->isAuthenticated()) {
        abort(401);
    }
    

Integration with Laravel Middleware

Create a middleware to wrap Symfony’s security logic:

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class AuthenticateMiddleware {
    public function __construct(private TokenStorageInterface $tokenStorage) {}

    public function handle($request, Closure $next) {
        $token = $this->tokenStorage->getToken();
        if (!$token || !$token->isAuthenticated()) {
            return redirect()->route('login');
        }
        return $next($request);
    }
}

Extending User Providers

Implement UserProviderInterface for custom user loading (e.g., from a database):

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class EloquentUserProvider implements UserProviderInterface {
    public function loadUserByIdentifier(string $identifier): UserInterface {
        return User::where('email', $identifier)->firstOrFail();
    }

    public function refreshUser(UserInterface $user): UserInterface {
        return $this->loadUserByIdentifier($user->getUserIdentifier());
    }

    public function supportsClass(string $class): bool {
        return User::class === $class;
    }
}

Gotchas and Tips

Pitfalls

  1. Token Serialization:

    • Avoid custom serialization logic for tokens. Use Symfony’s built-in __serialize()/__unserialize() methods.
    • Fix: Extend AbstractToken instead of implementing from scratch:
      class CustomToken extends AbstractToken { ... }
      
  2. Role Hierarchy Caching:

    • RoleHierarchy caches role mappings. Clear the cache if roles change dynamically:
      $roleHierarchy->clearCache();
      
  3. Impersonation Issues:

    • Impersonation tokens may break on subsequent requests if not handled properly.
    • Fix: Use ImpersonatingToken and ensure the original token is preserved:
      $impersonatingToken = new ImpersonatingToken($originalToken, $impersonatedUser);
      
  4. Voter Order Matters:

    • Voters are evaluated in order. Place stricter checks (e.g., AuthenticatedVoter) before broader ones (e.g., RoleVoter).
    • Tip: Use AccessDecisionManager::setDecisionStrategy() to customize the voting strategy (e.g., AffirmativeStrategy for majority approval).
  5. Deprecated Methods:

    • Avoid eraseCredentials() (deprecated in Symfony 7.3). Use UserInterface::getRoles() without sensitive data.
    • Fix: Store hashed credentials separately if needed.

Debugging Tips

  1. Enable Debugging:

    • Set SYMFONY_DEBUG=1 to log voter decisions and token states.
    • Example:
      $accessDecisionManager->setLogger(new \Monolog\Logger('security'));
      
  2. Inspect Tokens:

    • Dump token attributes for debugging:
      dd($token->getRoles(), $token->getAttributes());
      
  3. Role Hierarchy Visualization:

    • Use Symfony’s RoleHierarchy dumper to visualize role inheritance:
      $roleHierarchy->dump();
      

Extension Points

  1. Custom Voters:

    • Extend Voter for attribute-based authorization (e.g., IS_OWNER):
      class OwnerVoter extends Voter {
          protected function supports(string $attribute, mixed $subject): bool {
              return $attribute === 'IS_OWNER';
          }
      
          protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool {
              return $subject->getUserId() === $token->getUser()->id;
          }
      }
      
  2. Token Attributes:

    • Attach metadata to tokens for fine-grained access control:
      $token = new UsernamePasswordToken($user, 'main', $user->getRoles(), [
          'department' => 'engineering',
      ]);
      
    • Access attributes in voters:
      $department = $token->getAttribute('department');
      
  3. Event Listeners:

    • Listen to SecurityEvents (e.g., INTERACTIVE_LOGIN) for post-authentication logic:
      $dispatcher->addListener(SecurityEvents::INTERACTIVE_LOGIN, function (InteractiveLoginEvent $event) {
          // Log or notify on login
      });
      
  4. Remember-Me Cookies:

    • Customize RememberMeServices for persistent logins:
      $rememberMeServices = new RememberMeServices(
          $tokenStorage,
          new PersistentTokenBasedRememberMeServices(
              $cookieName,
              $tokenStorage,
              new PersistentTokenRepository(),
              new PersistentToken($user->getUserIdentifier(), $secret),
              new \DateTime('+30 days'),
              true // Always remember
          )
      );
      

Laravel-Specific Quirks

  1. Session Integration:

    • Symfony’s SessionTokenStorage works with Laravel’s session driver by default. Ensure session configuration matches:
      'session' => [
          'driver' => 'file', // or 'database', 'redis', etc.
      ],
      
  2. CSRF Protection:

    • Symfony’s CsrfTokenManager can conflict with Laravel’s built-in CSRF. Disable one or the other:
      // Disable Laravel's CSRF middleware if using Symfony's
      $middleware->remove(\App\Http\Middleware\VerifyCsrfToken::class);
      
  3. User Model Mapping:

    • Ensure your User model implements UserInterface and maps to Symfony’s expected methods:
      class User implements UserInterface {
          public function getRoles(): array { ... }
          public function getPassword(): string { ... }
          public function getUserIdentifier(): string { ... }
      }
      
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.
nasirkhan/laravel-sharekit
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony