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

Voucher Authentication Bundle Laravel Package

elao/voucher-authentication-bundle

Symfony bundle enabling voucher (email link) authentication. Register the bundle, import routes, and enable the “voucher” firewall. Generate and persist disposable voucher tokens in your app or via CLI, then send users a login/activation link with an optional TTL.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require elao/voucher-authentication-bundle
    

    Add to config/bundles.php (Symfony) or config/app.php (Laravel via bridge):

    Elao\VoucherAuthenticationBundle\ElaoVoucherAuthenticationBundle::class => ['all' => true],
    
  2. Configuration Publish the default config:

    php artisan vendor:publish --provider="Elao\VoucherAuthenticationBundle\ElaoVoucherAuthenticationBundle" --tag="config"
    

    Key settings to review:

    • voucher_expiration (default: 3600 seconds)
    • voucher_length (default: 16 chars)
    • email_template (path to Twig template for voucher emails)
  3. First Use Case: Email Link Authentication

    • Generate a voucher for a user:
      use Elao\VoucherAuthenticationBundle\Generator\VoucherGeneratorInterface;
      
      $generator = $this->container->get(VoucherGeneratorInterface::class);
      $voucher = $generator->generate($user);
      
    • Send the voucher via email (manually or via event listener).
    • Redirect users to a login page with the voucher in the URL:
      /login?voucher=ABCD1234EFGH5678
      

Implementation Patterns

Workflow: Voucher-Based Login

  1. User Registration/Request Flow

    • Trigger voucher generation on registration or password reset.
    • Example event listener:
      use Elao\VoucherAuthenticationBundle\Event\VoucherGeneratedEvent;
      
      public function onVoucherGenerated(VoucherGeneratedEvent $event)
      {
          $voucher = $event->getVoucher();
          $user = $event->getUser();
          Mail::to($user->email)->send(new VoucherEmail($voucher));
      }
      
  2. Login Handling

    • Create a custom guard or extend the default voucher guard:
      // config/auth.php
      'guards' => [
          'voucher' => [
              'driver' => 'session',
              'provider' => 'users',
          ],
      ],
      
    • Override VoucherAuthenticator to handle voucher validation:
      public function authenticate(Request $request)
      {
          $voucher = $request->query->get('voucher');
          $user = $this->voucherManager->findUserByVoucher($voucher);
      
          if ($user && !$this->voucherManager->isVoucherExpired($voucher)) {
              $this->voucherManager->consumeVoucher($voucher);
              return $this->auth->login($user);
          }
          return null;
      }
      
  3. Integration with Forms

    • Use a simple form to capture the voucher:
      <form method="POST" action="/login">
          @csrf
          <input type="hidden" name="voucher" value="{{ request('voucher') }}">
          <button type="submit">Login with Voucher</button>
      </form>
      

Advanced Patterns

  • Rate Limiting: Extend VoucherManager to track failed attempts per voucher/IP.
  • Multi-Use Vouchers: Override consumeVoucher() to allow reuse (e.g., for shared accounts).
  • Voucher Metadata: Store additional data (e.g., expires_at, used_at) in the database.

Gotchas and Tips

Pitfalls

  1. Voucher Expiration

    • Default expiration is 1 hour. Adjust voucher_expiration in config if needed.
    • Expired vouchers silently fail; add logging or user feedback:
      if ($this->voucherManager->isVoucherExpired($voucher)) {
          throw new VoucherExpiredException('Voucher has expired.');
      }
      
  2. Database Schema

    • The bundle expects a vouchers table with columns:
      • id, user_id, voucher, expires_at, used_at.
    • Run migrations manually if not auto-generated:
      php artisan vendor:publish --provider="Elao\VoucherAuthenticationBundle\ElaoVoucherAuthenticationBundle" --tag="migrations"
      
  3. Security Risks

    • Voucher Leakage: Ensure vouchers are not logged or exposed in errors.
      • Use try-catch for voucher validation:
        try {
            $user = $this->voucherManager->findUserByVoucher($voucher);
        } catch (VoucherNotFoundException $e) {
            // Log generically: "Invalid voucher provided."
        }
        
    • Replay Attacks: Consume vouchers immediately after validation (default behavior).
  4. Testing

    • Mock VoucherGeneratorInterface to avoid real voucher creation in tests:
      $generator = $this->createMock(VoucherGeneratorInterface::class);
      $generator->method('generate')->willReturn('TEST1234TEST1234');
      

Tips

  1. Custom Voucher Generation

    • Extend VoucherGenerator to enforce stricter rules (e.g., alphanumeric-only):
      class CustomVoucherGenerator extends VoucherGenerator
      {
          protected function generateRandomString()
          {
              return substr(strtoupper(bin2hex(random_bytes(8))), 0, 16);
          }
      }
      
    • Register as a service:
      # config/services.yaml
      Elao\VoucherAuthenticationBundle\Generator\VoucherGeneratorInterface: '@custom_voucher_generator'
      
  2. Email Templates

    • Customize the voucher email template (resources/views/elao_voucher_authentication/email.txt.twig):
      Hello {{ user.email }},
      
      Your voucher is: {{ voucher.voucher }}
      It expires at: {{ voucher.expiresAt|date('Y-m-d H:i') }}
      
    • Override the template path in config:
      email_template: 'path/to/custom_template'
      
  3. Debugging

    • Enable SQL logging to verify voucher queries:
      DB::enableQueryLog();
      $user = $this->voucherManager->findUserByVoucher($voucher);
      dd(DB::getQueryLog());
      
    • Check for expired vouchers in the database:
      SELECT * FROM vouchers WHERE expires_at < NOW();
      
  4. Performance

    • Add an index to vouchers(voucher) and vouchers(user_id) for large-scale use:
      CREATE INDEX voucher_index ON vouchers(voucher);
      CREATE INDEX user_voucher_index ON vouchers(user_id);
      
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.
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
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope