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

Bartender Laravel Package

directorytree/bartender

Opinionated Socialite authentication for Laravel. Ships ready-made routes (/auth/{driver}/redirect, /callback), a controller, migrations to store provider IDs and optional access/refresh tokens, and customizable hooks for features like soft deletes and email verification.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require directorytree/bartender
    php artisan vendor:publish --provider="DirectoryTree\Bartender\BartenderServiceProvider"
    php artisan migrate
    
    • Skip token columns migration if you don’t need provider tokens.
  2. Configure Routes:

    // routes/web.php
    use DirectoryTree\Bartender\Facades\Bartender;
    Bartender::routes(); // Adds `/auth/{driver}/redirect` and `/auth/{driver}/callback`
    
  3. Register Providers:

    // config/services.php
    'google' => [
        'redirect' => '/auth/google/callback',
        // ... other config
    ],
    
  4. Serve Providers:

    // app/Providers/AppServiceProvider.php
    Bartender::serve('google'); // Register with default handler
    
  5. First Use Case: Add login links in Blade:

    <a href="{{ route('auth.driver.redirect', 'google') }}">Login with Google</a>
    

Implementation Patterns

Core Workflow

  1. Redirect Flow:

    • User clicks /auth/{driver}/redirect → Socialite provider → /auth/{driver}/callback.
    • Bartender handles the callback, creates/updates the user, and redirects.
  2. Custom User Model:

    • If your User model isn’t in App\Models, set it in AuthServiceProvider:
      Bartender::setUserModel(\App\User::class);
      
  3. Token Storage (Optional):

    • Implement StoresProviderTokens in your User model and encrypt tokens:
      protected $hidden = ['provider_access_token', 'provider_refresh_token'];
      protected function casts(): array { return ['provider_access_token' => 'encrypted']; }
      

Common Patterns

  • Provider-Specific Scopes: Extend UserProviderHandler to modify scopes (e.g., Microsoft):

    class MicrosoftUserHandler extends UserProviderHandler {
        public function redirect(Provider $provider, string $driver): RedirectResponse {
            $provider->scopes(['Mail.ReadWrite']);
            return parent::redirect($provider, $driver);
        }
    }
    

    Register it:

    Bartender::serve('microsoft', MicrosoftUserHandler::class);
    
  • User Creation Logic: Bind a custom ProviderRepository to override exists() or updateOrCreate():

    $this->app->bind(ProviderRepository::class, CustomUserProviderRepository::class);
    
  • Post-Auth Redirects: Customize redirects in ProviderRedirector:

    public function userAuthenticated(Authenticatable $user, SocialiteUser $socialite, string $driver): RedirectResponse {
        Auth::login($user);
        Session::regenerate(); // Critical for security
        return redirect()->route('dashboard');
    }
    

Integration Tips

  • Laravel Socialite Providers: Ensure each provider (e.g., GitHub, Facebook) is properly installed before using Bartender::serve().

    • Debug Tip: Check for Driver [X] not supported errors if the provider isn’t registered.
  • Testing: Use Bartender::serve() with mock providers in tests:

    Bartender::serve('mock', MockProviderHandler::class);
    
  • Multi-Tenant Apps: Extend ProviderRepository to scope users by tenant:

    public function exists(string $driver, SocialiteUser $user): bool {
        return User::withTrashed()->where('email', $user->getEmail())
            ->where('tenant_id', request()->tenantId)->exists();
    }
    

Gotchas and Tips

Pitfalls

  1. Missing Bartender::serve():

    • Error: Routing requirement for "driver" cannot be empty.
    • Fix: Register all providers in AppServiceProvider::boot().
  2. Token Storage Mismatch:

    • If you skip the token migration but implement StoresProviderTokens, Bartender will throw an error.
    • Fix: Either:
      • Run the migration, or
      • Remove the interface and let Bartender skip token storage.
  3. Session Fixation:

    • Forgetting Session::regenerate() in ProviderRedirector leaves users vulnerable.
    • Fix: Always call it in userAuthenticated().
  4. Soft Deletes:

    • By default, soft-deleted users are restored on login. Override exists() in ProviderRepository to change this:
      public function exists(string $driver, SocialiteUser $user): bool {
          return User::where('email', $user->getEmail())->doesntExist(); // Never restore
      }
      
  5. Email Verification:

    • Default behavior auto-verifies emails. Disable by overriding updateOrCreate():
      $user->email_verified_at = null;
      

Debugging Tips

  • Provider Callback Failures:

    • Check storage/logs/laravel.log for Socialite errors (e.g., invalid credentials).
    • Verify services.php config matches the provider’s requirements.
  • Custom Handler Not Triggered:

    • Ensure the handler is bound after Socialite providers are registered (order matters in AppServiceProvider).
  • Token Encryption Issues:

    • If tokens aren’t encrypted, check:
      • The encrypted cast is applied to the model.
      • The provider_access_token column is of type text (not string).

Extension Points

  1. Dynamic Provider Registration: Register providers dynamically based on config:

    foreach (config('auth.providers') as $driver) {
        Bartender::serve($driver);
    }
    
  2. Provider-Specific Logic: Use dependency injection in custom handlers:

    public function __construct(
        protected Request $request,
        protected TenantService $tenantService
    ) {}
    
  3. Fallback to Email/Password: Extend ProviderRedirector to fall back if Socialite fails:

    public function unableToAuthenticateUser(Exception $e, string $driver): RedirectResponse {
        return redirect()->route('login.email');
    }
    
  4. Webhook Validation: For providers like GitHub, validate webhooks by extending ProviderHandler:

    public function callback(Provider $provider, string $driver): RedirectResponse {
        if (!$this->validateWebhook($provider->user())) {
            abort(403);
        }
        return parent::callback($provider, $driver);
    }
    

Configuration Quirks

  • Route Naming: Bartender uses auth.driver.redirect and auth.driver.callback. Override in routes/web.php:

    Bartender::routes(['prefix' => 'social']);
    
  • Provider Driver Names: Ensure services.php keys match the driver names used in Bartender::serve() (case-sensitive).

  • Password Hashing: Bartender uses Laravel’s Hash::make() by default. To customize:

    // In ProviderRepository
    public function updateOrCreate(string $driver, SocialiteUser $user): Authenticatable {
        $user->password = Hash::make('default_password');
        // ...
    }
    

```markdown
### Pro Tips
- **Leverage `SocialiteUser`**:
  Access raw provider data in `ProviderRepository`:
  ```php
  $user->name = $socialiteUser->getName();
  $user->avatar = $socialiteUser->getAvatar();
  • Rate Limiting: Protect /auth/{driver}/callback from brute force:

    Route::middleware(['throttle:10,1'])->group(function () {
        Bartender::routes();
    });
    
  • Testing Callbacks: Mock Socialite responses in tests:

    $this->mock(Socialite::class)->shouldReceive('driver')->andReturnSelf()
        ->shouldReceive('user')->andReturn($mockSocialiteUser);
    
  • Multi-Provider Logins: Track the last used provider in the User model:

    protected $casts = ['last_provider' => 'string'];
    // In ProviderRepository:
    $user->last_provider = $driver;
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4
php-http/client-implementation
phpcr/phpcr-implementation
cucumber/gherkin-monorepo
haydenpierce/class-finder
psr/simple-cache-implementation
uri-template/tests