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

Symfony Security Bridge Laravel Package

bengor-user/symfony-security-bridge

Adapter bridge to integrate BenGorUser’s User model with the Symfony Security component. Install via Composer, fully tested with PHPSpec, and documented in the main BenGorUser/User library docs. PHP 5.5+.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require bengor-user/symfony-security-bridge
    

    Ensure your Laravel project uses PHP ≥5.5 (compatible with Symfony Security).

  2. Bridge Your User Model Extend your Laravel User model with SymfonyUserInterface and implement required methods:

    use BenGorUser\SymfonySecurityBridge\User\SymfonyUserInterface;
    
    class User extends Authenticatable implements SymfonyUserInterface
    {
        public function getRoles()
        {
            return ['ROLE_USER']; // Return array of roles
        }
    
        public function getPassword()
        {
            return $this->password; // Return hashed password
        }
    
        public function getSalt()
        {
            return null; // Symfony 3+ ignores this; return null for Laravel Hash::check()
        }
    
        public function eraseCredentials()
        {
            // Clear sensitive data after login
            $this->password = null;
        }
    }
    
  3. Configure Symfony Security In config/auth.php, set the provider to use the bridged user:

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
    ],
    
  4. First Use Case: Authentication Use Symfony’s UserChecker or AuthenticationUtils in a Laravel controller:

    use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
    use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
    
    public function login(Request $request, TokenStorage $tokenStorage)
    {
        $user = User::where('email', $request->email)->first();
        $token = new UsernamePasswordToken($user, $this->generatePassword(), 'main', $user->getRoles());
        $tokenStorage->setToken($token);
    }
    

Implementation Patterns

Workflow: Role-Based Access Control (RBAC)

  1. Define Roles in User Model

    public function getRoles()
    {
        return $this->roles->pluck('name')->toArray(); // Assume `roles` is a relationship
    }
    
  2. Use Symfony’s Voter System Create a custom voter:

    use Symfony\Component\Security\Core\Authorization\Voter\Voter;
    
    class AdminVoter extends Voter
    {
        protected function supports($attribute, $subject)
        {
            return $attribute === 'IS_ADMIN';
        }
    
        protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
        {
            return in_array('ROLE_ADMIN', $token->getUser()->getRoles());
        }
    }
    
  3. Integrate with Laravel Middleware

    use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
    
    class AdminMiddleware
    {
        public function __construct(AuthorizationCheckerInterface $authChecker)
        {
            $this->authChecker = $authChecker;
        }
    
        public function handle($request, Closure $next)
        {
            if (!$this->authChecker->isGranted('IS_ADMIN')) {
                abort(403);
            }
            return $next($request);
        }
    }
    

Workflow: Password Hashing

  • Leverage Laravel’s Hashing The bridge expects getPassword() to return the hashed password (use Laravel’s Hash::make()). Symfony’s UserPasswordHasher will work seamlessly with Laravel’s Hash facade.

Workflow: Session Management

  • Extend Symfony’s SessionAuthenticationStrategy
    use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
    
    class LaravelSuccessHandler implements AuthenticationSuccessHandlerInterface
    {
        public function onAuthenticationSuccess(Request $request, TokenInterface $token)
        {
            // Redirect or set flash messages using Laravel's session
            session()->flash('status', 'Logged in!');
            return redirect('/dashboard');
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Role Format Mismatch

    • Symfony expects roles as strings prefixed with ROLE_ (e.g., ['ROLE_ADMIN']).
    • Laravel’s can() method uses plain strings (e.g., ['admin']).
    • Fix: Normalize roles in getRoles():
      public function getRoles()
      {
          return array_map(fn($role) => "ROLE_{$role}", $this->roles);
      }
      
  2. Password Hashing Conflicts

    • If using Symfony’s UserPasswordHasher, ensure your Laravel User model’s password field is not auto-hashed twice.
    • Fix: Disable Laravel’s shouldHash in Authenticatable or manually hash passwords before saving.
  3. TokenStorage in Laravel

    • Symfony’s TokenStorage is not natively available in Laravel.
    • Workaround: Bind it manually in AppServiceProvider:
      $this->app->bind(TokenStorage::class, function () {
          return new TokenStorage(new AnonymousToken('main', null, []));
      });
      
  4. Deprecated Methods

    • The package assumes Symfony ≤3.x (e.g., getSalt() is ignored in Symfony 4+).
    • Tip: Override getSalt() to return null for compatibility.

Debugging Tips

  1. Check User Roles Dump the user’s roles during authentication:

    dd($token->getUser()->getRoles());
    
  2. Verify Token Creation Ensure tokens are created correctly:

    $token = new UsernamePasswordToken(
        $user,
        $this->generatePassword(), // Use a dummy password; Symfony validates against getPassword()
        'main',
        $user->getRoles()
    );
    
  3. Symfony Event Listeners Use Symfony’s events (e.g., security.interactive_login) via Laravel’s event system:

    Event::listen('security.interactive_login', function ($event) {
        // Custom logic after login
    });
    

Extension Points

  1. Custom User Providers Extend SymfonyUserProvider to fetch users from non-standard sources:

    use BenGorUser\SymfonySecurityBridge\User\SymfonyUserProvider;
    
    class CustomUserProvider extends SymfonyUserProvider
    {
        public function loadUserByUsername($username)
        {
            return User::where('email', $username)->firstOrFail();
        }
    }
    
  2. Laravel-Powered Firewalls Combine with spatie/laravel-permission for granular RBAC:

    public function getRoles()
    {
        return $this->getAllPermissions()->pluck('name')->map(fn($p) => "ROLE_{$p}");
    }
    
  3. Testing Mock Symfony’s TokenStorage in PHPUnit:

    $token = $this->createMock(TokenInterface::class);
    $token->method('getUser')->willReturn($user);
    $storage = $this->createMock(TokenStorage::class);
    $storage->method('getToken')->willReturn($token);
    $this->app->instance(TokenStorage::class, $storage);
    
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.
craftcms/url-validator
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