PHPackages                             directorytree/bartender - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. directorytree/bartender

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

directorytree/bartender
=======================

An opinionated way to authenticate users using Laravel Socialite.

v1.5.0(2mo ago)28516.6k↓40.4%13MITPHPPHP &gt;=8.0CI passing

Since Apr 3Pushed 1w ago2 watchersCompare

[ Source](https://github.com/DirectoryTree/Bartender)[ Packagist](https://packagist.org/packages/directorytree/bartender)[ RSS](/packages/directorytree-bartender/feed)WikiDiscussions master Synced 1w ago

READMEChangelog (10)Dependencies (10)Versions (19)Used By (0)

[![](https://github.com/DirectoryTree/Bartender/raw/master/art/logo.svg)](https://github.com/DirectoryTree/Bartender/blob/master/art/logo.svg)

An opinionated way to authenticate users using Laravel Socialite.

[![](https://camo.githubusercontent.com/ea3cd954f2e4db7ad50e275d229e0e37adf2c8bf1409f1167fd6f7c3b10e812b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6469726563746f7279747265652f62617274656e6465722f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572267374796c653d666c61742d737175617265)](https://github.com/directorytree/bartender/actions)[![](https://camo.githubusercontent.com/b782b52e14729524923334361f436c6ba9e4685c337e697bb92a6149014f6287/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6469726563746f7279747265652f62617274656e6465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/directorytree/bartender)[![](https://camo.githubusercontent.com/f3c51aa9a8084bf6afa5b5cae34f36d214d0d070a5c5c4f6e99c9c79b80330df/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6469726563746f7279747265652f62617274656e6465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/directorytree/bartender)[![](https://camo.githubusercontent.com/f4942fe4816793a470f36ea1fecda090861a1c3426034b6d2c455e65429823a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6469726563746f7279747265652f62617274656e6465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/directorytree/bartender)

---

Bartender serves you a controller, routes, and a default implementation for easily handling authentication with Laravel Socialite providers. Almost everything in Bartender can be customized.

Index
-----

[](#index)

- [Requirements](#requirements)
- [Installation](#installation)
- [Setup](#setup)
- [Usage](#usage)
    - [Soft Deletes](#soft-deletes)
    - [Email Verification](#email-verification)
    - [Access/Refresh Tokens](#accessrefresh-tokens)
- [Extending &amp; Customizing](#extending--customizing)

Requirements
------------

[](#requirements)

- PHP &gt;= 8.0
- Laravel &gt;= 9.0
- Laravel Socialite &gt;= 5.0

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require directorytree/bartender
```

Then, publish the migrations. They will create the required columns on the `users` table:

- `provider_id`
- `provider_name`
- `provider_access_token`
- `provider_refresh_token`

> If your application does not need to store/access provider tokens, you may delete the `2024_10_27_131354_add_provider_token_columns_to_users_table.php` migration.

```
php artisan vendor:publish --provider="DirectoryTree\Bartender\BartenderServiceProvider"
```

Finally, run the migrations:

```
php artisan migrate
```

Setup
-----

[](#setup)

Register the authentication routes using `Bartender::routes()`.

This will register the `/auth/{driver}/redirect` and `/auth/{driver}/callback` routes.

```
// routes/web.php

use DirectoryTree\Bartender\Facades\Bartender;

Bartender::routes();
```

Set up any [Socialite Providers](https://socialiteproviders.com) you need, and update your `services.php` configuration file with the `redirect` URL for each provider:

Important

Remember to fully complete the installation steps for each Socialite Provider you wish to use.

If you receive a `Driver [X] not supported` exception, you have not completed the installation steps for the provider.

```
// config/services.php

return [
    // ...

    'google' => [
        // ...
        'redirect' => '/auth/google/callback',
    ],

    'microsoft' => [
        // ...
        'redirect' => '/auth/microsoft/callback',
    ],
];
```

Finally, register the Socialite Provider in your `AppServiceProvider` using `Bartender::serve()`:

```
// app/Providers/AppServiceProvider.php

use DirectoryTree\Bartender\Facades\Bartender;

class AppServiceProvider extends ServiceProvider
{
    // ...

    public function boot(): void
    {
        Bartender::serve('google');
        Bartender::serve('microsoft');
    }
}
```

If your application uses a `User` model outside the default `App\Models` namespace, you can set it using the `Bartender` facade.

> If your application uses the default Laravel `User` model in the `App\Models` namespace, skip this step.

```
// app/Providers/AuthServiceProvider.php

use App\User;
use DirectoryTree\Bartender\Facades\Bartender;

class AuthServiceProvider extends ServiceProvider
{
    // ...

    public function boot(): void
    {
        Bartender::setUserModel(User::class);
    }
}
```

Usage
-----

[](#usage)

Direct your user to the `/auth/{driver}/redirect` route to authenticate with the given driver:

```

    Login with Google

    Login with Microsoft

```

Once the user successfully authenticates, they will be redirected to the `/auth/{driver}/callback`route, which will automatically create or update their application user account.

Important

If you receive a `Routing requirement for "driver" cannot be empty` exception upon clicking one of the login links, you have forgotten to register your the Socialite provider with Bartender using `Bartender::serve()` in your `AppServiceProvider`.

### Soft Deletes

[](#soft-deletes)

With the default `UserProviderRepository`, soft-deleted users will be restored if they log in with their provider.

To change this behaviour, [swap out the repository](#user-creation--updating).

### Email Verification

[](#email-verification)

With the default `UserProviderRepository`, users with emails will be automatically verified (by setting the `email_verified_at` timestamp column) if it is not already set.

To change this behaviour, [swap out the repository](#user-creation--updating).

### Access/Refresh Tokens

[](#accessrefresh-tokens)

To enable storing the authentication provider access and refresh tokens on your user so that you can access them later, you may apply the `StoresProviderTokens` interface on your model:

```
// app/Models/User.php

namespace App\Models;

use DirectoryTree\Bartender\StoresProviderTokens;

class User extends Authenticatable implements StoresProviderTokens
{
    // ...
}
```

You may also want to add these columns to your model's `$hidden` attributes, along with `encrypted` casts for additional security:

```
// app/Models/User.php

class User extends Authenticatable implements StoresProviderTokens
{
    /**
     * The attributes that should be hidden for serialization.
     */
    protected $hidden = [
        'provider_access_token',
        'provider_refresh_token'
    ];

    /**
     * Get the attributes that should be cast.
     */
    protected function casts(): array
    {
        return [
            'provider_access_token' => 'encrypted',
            'provider_refresh_token' => 'encrypted',
        ];
    }
}
```

Otherwise, if you do not need to store these tokens, you are free to delete the published `2024_10_27_131354_add_provider_token_columns_to_users_table.php`migration file and omit applying the `StoresProviderTokens` interface. Bartender will skip storing these tokens as it does not require them to successfully authenticate users.

Extending &amp; Customizing
---------------------------

[](#extending--customizing)

Almost everything can be swapped out in Bartender.

If you would like to handle everything yourself for OAuth redirects and callbacks, you may create your own `ProviderHandler`:

```
// app/Socialite/UserProviderHandler.php

namespace App\Socialite;

use Illuminate\Http\Request;
use Laravel\Socialite\Contracts\Provider;
use DirectoryTree\Bartender\ProviderHandler;

class UserProviderHandler implements ProviderHandler
{
    /**
     * Constructor.
     */
    public function __construct(
        protected Request $request
    ) {
    }

    /**
     * Handle redirecting the user to the OAuth provider.
     */
    public function redirect(Provider $provider, string $driver): RedirectResponse
    {
        // Perform additional logic here...

        return $provider->redirect();
    }

    /**
     * Handle an OAuth response from the provider.
     */
    public function callback(Provider $provider, string $driver): RedirectResponse
    {
        // Authenticate the user your own way...

        return redirect()->route('dashboard');
    }
}
```

Then, provide it into the second argument in the `Bartender::serve` method:

```
// app/Providers/AuthServiceProvider.php

namespace App\Providers;

use App\Socialite\UserProviderHandler;
use DirectoryTree\Bartender\Facades\Bartender;

class AuthServiceProvider extends ServiceProvider
{
    // ...

    public function boot(): void
    {
        Bartender::serve('google', UserProviderHandler::class);
        Bartender::serve('microsoft', UserProviderHandler::class);
    }
}
```

You may also extend the built-in `UserProviderHandler` implementation if you prefer.

For example, if you need to adjust the scopes for a single provider:

```
// app/Socialite/MicrosoftUserHandler.php

namespace App\Socialite;

use Illuminate\Http\RedirectResponse;
use Laravel\Socialite\Contracts\Provider;
use DirectoryTree\Bartender\UserProviderHandler;

class MicrosoftUserHandler extends UserProviderHandler
{
    /**
     * Handle redirecting the user to Microsoft.
     */
    public function redirect(Provider $provider, string $driver): RedirectResponse
    {
        $provider->scopes([
            'Mail.ReadWrite',
            // ...
        ]);

        return parent::redirect($provider, $driver);
    }
}
```

Then register it as the handler:

```
Bartender::serve('microsoft', MicrosoftUserHandler::class);
```

### User Creation &amp; Updating

[](#user-creation--updating)

If you would like to customize the creation of the user in the default handler, you may create your own `ProviderRepository` implementation:

```
// app/Socialite/UserProviderRepository.php

namespace App\Socialite;

use App\Models\User;
use Illuminate\Contracts\Auth\Authenticatable;
use DirectoryTree\Bartender\ProviderRepository;
use Laravel\Socialite\Contracts\User as SocialiteUser;

class UserProviderRepository implements ProviderRepository
{
    /**
     * Determine if the user already exists under a different provider.
     */
    public function exists(string $driver, SocialiteUser $user): bool
    {
        return User::withTrashed()->where('...')->exists();
    }

    /**
     * Update or create the socialite user.
     */
    public function updateOrCreate(string $driver, SocialiteUser $user): Authenticatable
    {
        $user = User::withTrashed()->firstOrNew([
            // ...
        ]);

        return $user;
    }
}
```

Then, bind your implementation in the service container in your `AppServiceProvider`:

```
// app/Providers/AppServiceProvider.php

namespace App\Providers;

use App\Socialite\UserProviderRepository;
use DirectoryTree\Bartender\ProviderRepository;

class AppServiceProvider extends ServiceProvider
{
    // ...

    public function register(): void
    {
        $this->app->bind(ProviderRepository::class, UserProviderRepository::class);
    }
}
```

### User Redirects &amp; Flash Messaging

[](#user-redirects--flash-messaging)

If you would like to customize the behavior of the redirects of the default redirector and flash messages depending on the outcome of a OAuth callback, you can create your own `ProviderRedirector` implementation:

> It's recommended to regenerate the session after authentication to prevent users from exploiting a [session fixation attack](https://laravel.com/docs/11.x/session#regenerating-the-session-id).

```
// app/Socialite/UserProviderRedirector.php

namespace App\Socialite;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;

class UserProviderRedirector implements ProviderRedirector
{
    /**
     * Redirect when unable to authenticate the user.
     */
    public function unableToAuthenticateUser(Exception $e, string $driver): RedirectResponse
    {
        report($e);

        return redirect()->route('login')->with('error', 'Unable to authenticate user.');
    }

    /**
     * Redirect when the user already exists.
     */
    public function userAlreadyExists(SocialiteUser $user, string $driver): RedirectResponse
    {
        return redirect()->route('login')->with('error', 'User already exists.');
    }

    /**
     * Redirect when unable to create the user.
     */
    public function unableToCreateUser(Exception $e, SocialiteUser $user, string $driver): RedirectResponse
    {
        report($e);

        return redirect()->route('login')->with('error', 'Unable to create user.');
    }

    /**
     * Handle when the user has been successfully authenticated.
     */
    public function userAuthenticated(Authenticatable $user, SocialiteUser $socialite, string $driver): RedirectResponse
    {
        Auth::login($user);

        Session::regenerate();

        return redirect()->route('dashboard');
    }
}
```

Then, bind your implementation in the service container in your `AppServiceProvider`:

```
// app/Providers/AppServiceProvider.php

namespace App\Providers;

use App\Socialite\UserProviderRedirector;

class AppServiceProvider extends ServiceProvider
{
    // ...

    public function register(): void
    {
        $this->app->bind(ProviderRedirector::class, UserProviderRedirector::class);
    }
}
```

###  Health Score

56

—

FairBetter than 97% of packages

Maintenance93

Actively maintained with recent releases

Popularity46

Moderate usage in the ecosystem

Community17

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 93.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~60 days

Recently: every ~131 days

Total

13

Last Release

72d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c6dd082636ff8a08df8dfdcd622ea242374d1d76dd33bceec5a6cd3ae26dc24f?d=identicon)[stevebauman](/maintainers/stevebauman)

---

Top Contributors

[![stevebauman](https://avatars.githubusercontent.com/u/6421846?v=4)](https://github.com/stevebauman "stevebauman (96 commits)")[![Copilot](https://avatars.githubusercontent.com/in/1143301?v=4)](https://github.com/Copilot "Copilot (3 commits)")[![happytodev](https://avatars.githubusercontent.com/u/425998?v=4)](https://github.com/happytodev "happytodev (2 commits)")[![Lakshan-Madushanka](https://avatars.githubusercontent.com/u/47297673?v=4)](https://github.com/Lakshan-Madushanka "Lakshan-Madushanka (1 commits)")[![nick-potts](https://avatars.githubusercontent.com/u/1109914?v=4)](https://github.com/nick-potts "nick-potts (1 commits)")

---

Tags

laraveloauth2socialiteoauth

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/directorytree-bartender/health.svg)

```
[![Health](https://phpackages.com/badges/directorytree-bartender/health.svg)](https://phpackages.com/packages/directorytree-bartender)
```

###  Alternatives

[socialiteproviders/manager

Easily add new or override built-in providers in Laravel Socialite.

42645.6M574](/packages/socialiteproviders-manager)[auth0/login

Auth0 Laravel SDK. Straight-forward and tested methods for implementing authentication, and accessing Auth0's Management API endpoints.

2795.2M3](/packages/auth0-login)[kovah/laravel-socialite-oidc

OpenID Connect OAuth2 Provider for Laravel Socialite

24110.5k](/packages/kovah-laravel-socialite-oidc)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
