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

Persona Bundle Laravel Package

bitgrave/persona-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the bundle to composer.json:

    {
        "require": {
            "bitgrave/persona-bundle": "dev-master"
        }
    }
    

    Run composer update or composer install.

  2. Enable the Bundle Register BGPersonaBundle in app/AppKernel.php:

    new BGPersonaBundle(),
    
  3. Configure Security Update app/config/security.yml to include the Persona provider:

    providers:
        persona:
            id: bg_persona.security.persona_user_provider
    firewalls:
        main:
            pattern: ^/
            form_login:
                provider: persona
                login_path: /login
                check_path: /login_check
            logout: true
    
  4. Add Login Button Include the Twig helper in your login template (app/Resources/views/Security/login.html.twig):

    {{ persona_login_button() }}
    
  5. Test the Flow

    • Visit /login.
    • Click the Persona login button.
    • Authenticate via Mozilla Persona (e.g., using a test email like test@example.com).
    • Verify redirection to your app (e.g., /).

First Use Case: Basic Persona Login

  • Goal: Allow users to log in via Persona without database persistence.
  • Steps:
    1. Follow the minimal setup above.
    2. Ensure BGPersonaBundle is the only provider in security.yml.
    3. Test with a valid Persona email (e.g., test@example.com).
    4. Debug with var_dump($this->getUser()) in a controller to confirm authentication.

Implementation Patterns

Workflow: Integrating with FOSUserBundle

  1. Extend User Provider Override the default provider to sync Persona logins with FOSUserBundle:

    # app/config/security.yml
    providers:
        fos_userbundle:
            id: fos_user.user_provider.username_email
        persona:
            id: bg_persona.security.persona_user_provider
            # Custom provider class (see below)
    
  2. Custom User Provider Create a service to merge Persona and FOSUser data:

    // src/Acme/AppBundle/Service/PersonaFosUserProvider.php
    class PersonaFosUserProvider implements UserProviderInterface {
        private $personaProvider;
        private $fosProvider;
    
        public function __construct(PersonaUserProvider $personaProvider, UserProviderInterface $fosProvider) {
            $this->personaProvider = $personaProvider;
            $this->fosProvider = $fosProvider;
        }
    
        public function loadUserByUsername($username) {
            // Try FOSUser first, fall back to Persona
            try {
                return $this->fosProvider->loadUserByUsername($username);
            } catch (UsernameNotFoundException $e) {
                return $this->personaProvider->loadUserByUsername($username);
            }
        }
    }
    
  3. Configure the Service

    # app/config/services.yml
    services:
        acme.persona_fos_user_provider:
            class: Acme\AppBundle\Service\PersonaFosUserProvider
            arguments:
                - '@bg_persona.security.persona_user_provider'
                - '@fos_user.user_provider.username_email'
    
  4. Update Security

    # app/config/security.yml
    providers:
        merged:
            id: acme.persona_fos_user_provider
    

Workflow: Customizing the Login Button

  1. Override Twig Helper Extend the default button template:

    {# app/Resources/views/BGPersona/login_button.html.twig #}
    <a href="{{ path('bg_persona_login') }}" class="btn-persona">
        <img src="{{ asset('bundles/bgpersona/images/persona-logo.png') }}" alt="Login with Persona">
    </a>
    
  2. Update Routes Ensure bg_persona_login route is configured in routing.yml:

    bg_persona_login:
        path: /login/persona
        defaults: { _controller: BGPersonaBundle:Security:login }
    

Workflow: Handling Persona Verification Errors

  1. Custom Error Handling Override the PersonaAuthenticationListener to handle failures:

    // src/Acme/AppBundle/EventListener/PersonaAuthListener.php
    class PersonaAuthListener {
        public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
            if ($exception instanceof PersonaException) {
                // Log or redirect with custom message
                $request->getSession()->getFlashBag()->add('error', 'Persona login failed: ' . $exception->getMessage());
            }
        }
    }
    
  2. Register the Listener

    # app/config/services.yml
    services:
        acme.persona_auth_listener:
            class: Acme\AppBundle\EventListener\PersonaAuthListener
            tags:
                - { name: kernel.event_listener, event: security.authentication.failure, method: onAuthenticationFailure }
    

Gotchas and Tips

Pitfalls

  1. Deprecated API

    • Persona (now Mozilla Identity) deprecated its API in 2016. This bundle relies on a non-functional service.
    • Workaround: Use modern alternatives like Firefox Account or OAuth providers (e.g., Google, GitHub).
  2. Symfony 2.1 Dependency

    • The bundle only supports Symfony 2.1. Upgrading to newer Symfony versions will break compatibility.
    • Workaround: Fork the bundle and update dependencies manually (risky).
  3. No Persistent Sessions

    • Persona logins are stateless by design. Users must re-authenticate on every visit.
    • Workaround: Implement a "remember me" token via cookies (not recommended for security-sensitive apps).
  4. Email-Only Authentication

    • The bundle does not support email verification or password recovery via Persona.
    • Workaround: Combine with FOSUserBundle for hybrid auth.

Debugging Tips

  1. Enable Verbose Logging Add to app/config/config.yml:

    monolog:
        handlers:
            main:
                level: debug
                channels: ["!event"]
    
  2. Check Persona API Calls

    • Monitor HTTP requests to https://verifier.login.persona.org. Use browser dev tools or strace:
      strace -e trace=network -f php app/console
      
  3. Validate Email Format

    • Persona requires valid email addresses (e.g., test@example.com). Invalid emails (e.g., test) will fail silently.
    • Fix: Add client-side validation:
      // app/Resources/public/js/login.js
      if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
          alert('Please enter a valid email (e.g., test@example.com)');
      }
      

Extension Points

  1. Custom User Data Mapping

    • Extend PersonaUser to include additional fields (e.g., name, avatar):
      // src/Acme/AppBundle/Model/PersonaUser.php
      class PersonaUser extends User implements UserInterface {
          private $avatarUrl;
      
          public function setAvatarUrl($url) {
              $this->avatarUrl = $url;
          }
      }
      
  2. Post-Authentication Logic

    • Hook into security.interactive_login event:
      services:
          acme.persona_post_auth_handler:
              class: Acme\AppBundle\EventListener\PersonaPostAuthHandler
              tags:
                  - { name: kernel.event_listener, event: security.interactive_login, method: onPostAuth }
      
  3. Multi-Factor Authentication (MFA)

    • Combine Persona with 2FA (e.g., using friendsofsymfony/user-bundle):
      # app/config/security.yml
      firewalls:
          main:
              form_login:
                  provider: merged
              remember_me:
                  key: "persona_remember_me"
                  lifetime: 31536000 # 1 year
      

Configuration Quirks

  1. Domain Whitelisting

    • Persona requires your domain to be pre-registered in their system. Test with:
      curl -X POST https://verifier.login.persona.org/verify -d "assertion=test@example.com"
      
    • Fix: Register your domain at Persona’s test site (now defunct; use a mock server for testing).
  2. CSRF Protection

    • The bundle does not include CSRF tokens for Persona logins. Add manually:
      {{ form_start(form, { 'attr
      
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle