directorytree/bartender
Opinionated Laravel Socialite auth starter. Ships ready-made routes (/auth/{driver}/redirect, /callback), controller, and user columns for provider ID/name plus optional access/refresh tokens. Highly customizable; supports soft deletes and email verification.
Installation:
composer require directorytree/bartender
php artisan vendor:publish --provider="DirectoryTree\Bartender\BartenderServiceProvider"
php artisan migrate
Register Routes:
// routes/web.php
use DirectoryTree\Bartender\Facades\Bartender;
Bartender::routes();
Configure Providers:
Update config/services.php with provider-specific redirect URLs (e.g., 'redirect' => '/auth/google/callback').
Enable Providers:
// app/Providers/AppServiceProvider.php
Bartender::serve('google'); // Add other providers (e.g., 'microsoft')
First Use Case: Add login links in a Blade template:
<a href="{{ route('auth.driver.redirect', 'google') }}">Login with Google</a>
Redirect Flow:
/auth/google/redirect).redirect() for the provider./auth/google/callback.Callback Handling:
callback().ProviderRepository).StoresProviderTokens is implemented).ProviderRedirector).User Management:
ProviderRepository).email_verified_at is missing.provider_access_token/provider_refresh_token if StoresProviderTokens is implemented.Custom Providers:
Extend UserProviderHandler to modify scopes or logic per provider (e.g., Microsoft’s Mail.ReadWrite scope).
Bartender::serve('microsoft', MicrosoftUserHandler::class);
User Resolution:
Override ProviderRepository to customize user lookup/creation logic (e.g., multi-provider merging).
$this->app->bind(ProviderRepository::class, CustomUserProviderRepository::class);
Post-Auth Actions:
Use ProviderRedirector to handle redirects/flash messages (e.g., session regeneration for security).
public function userAuthenticated($user, $socialite, $driver) {
Auth::login($user);
Session::regenerate();
return redirect()->route('dashboard');
}
Token Management:
For APIs, store tokens in a separate table (e.g., oauth_tokens) and link via provider_id.
Missing Provider Setup:
Driver [X] not supported.Socialite::driver('google')) and Bartender::serve('google') is called.Route Requirements:
Routing requirement for "driver" cannot be empty.Bartender::routes() is called in web.php and providers are served in AppServiceProvider.Token Storage:
StoresProviderTokens.$hidden/$casts in User model are configured:
protected $hidden = ['provider_access_token', 'provider_refresh_token'];
protected function casts(): array { return ['provider_access_token' => 'encrypted']; }
Soft Deletes:
exists()/updateOrCreate() in ProviderRepository to change logic.Email Verification:
email_verified_at is null.updateOrCreate() if not needed.Log Provider Data:
Dump Socialite user data in ProviderRepository to debug mismatches:
dd($user->getEmail(), $user->getId());
Test Redirects:
Use php artisan route:list to verify /auth/{driver}/redirect and /auth/{driver}/callback routes exist.
Token Issues:
Check provider_access_token/provider_refresh_token in the DB or use Tinker:
php artisan tinker
>>> $user = App\Models\User::find(1);
>>> dd($user->provider_access_token);
Custom Handlers:
UserProviderHandler for provider-specific logic (e.g., custom scopes).scopes() before redirect() in redirect() method.Repository Swaps:
ProviderRepository to:
provider_avatar_url).Redirect Logic:
ProviderRedirector for:
/admin).with('locale', $user->locale)).Token Management:
TokenManager to refresh tokens silently:
public function refreshToken(User $user, string $driver) {
$provider = Socialite::driver($driver)->user();
$user->forceFill(['provider_refresh_token' => $provider->token])->save();
}
Migration Skipping:
Delete 2024_10_27_131354_add_provider_token_columns_to_users_table.php if tokens aren’t needed (but ensure StoresProviderTokens isn’t implemented).
User Model Namespace:
Set custom User model in AuthServiceProvider if not in App\Models:
Bartender::setUserModel(\App\User::class);
Hashing:
Bartender uses Laravel’s Hash::make() (not bcrypt). Override in ProviderRepository if needed:
$user->password = Hash::make('default_password');
How can I help you explore Laravel packages today?