3
3
</p >
4
4
5
5
<p align =" center " >
6
- An opinionated social authentication handler using Laravel Socialite.
6
+ An opinionated way to authenticate users using Laravel Socialite.
7
7
</p >
8
8
9
9
<p align =" center " >
@@ -13,8 +13,284 @@ An opinionated social authentication handler using Laravel Socialite.
13
13
<a href =" https://packagist.org/packages/directorytree/bartender " target =" _blank " ><img src =" https://img.shields.io/packagist/l/directorytree/bartender.svg?style=flat-square " /></a >
14
14
</p >
15
15
16
- ### Index
16
+ ---
17
+
18
+ ## Index
17
19
18
20
- [ Requirements] ( #requirements )
19
21
- [ Installation] ( #installation )
22
+ - [ Setup] ( #setup )
20
23
- [ Usage] ( #usage )
24
+
25
+ ## Requirements
26
+
27
+ - PHP >= 8.0
28
+ - Laravel >= 9.0
29
+ - Laravel Socialite >= 5.0
30
+
31
+ ## Installation
32
+
33
+ You can install the package via composer:
34
+
35
+ ``` bash
36
+ composer require directorytree/bartender
37
+ ```
38
+
39
+ Then, publish the migration:
40
+
41
+ > This will create a ` provider_id ` and ` provider_name ` column on the ` users ` table.
42
+
43
+ ``` bash
44
+ php artisan vendor:publish --provider=" DirectoryTree\Bartender\BartenderServiceProvider"
45
+ ```
46
+
47
+ Finally, run the migration:
48
+
49
+ ``` bash
50
+ php artisan migrate
51
+ ```
52
+
53
+ ## Setup
54
+
55
+ Register the authentication routes:
56
+
57
+ > This will register the ` /auth/{driver}/redirect ` and ` /auth/{driver}/callback ` routes.
58
+
59
+ ``` php
60
+ // routes/web.php
61
+
62
+ use DirectoryTree\Bartender\Facades\Bartender;
63
+
64
+ Bartender::routes();
65
+ ```
66
+
67
+ Set up your [ Socialite Providers] ( https://socialiteproviders.com/ ) in your ` services.php ` configuration file:
68
+
69
+ ``` php
70
+ // config/services.php
71
+
72
+ return [
73
+ // ...
74
+
75
+ 'google' => ['...'],
76
+
77
+ 'microsoft' => ['...'],
78
+ ];
79
+ ```
80
+
81
+ Register the Socialite Provider in your ` AuthServiceProvider ` :
82
+
83
+ ``` php
84
+ // app/Providers/AuthServiceProvider.php
85
+
86
+ use DirectoryTree\Bartender\Bartender;
87
+
88
+ class AuthServiceProvider extends ServiceProvider
89
+ {
90
+ // ...
91
+
92
+ public function boot()
93
+ {
94
+ Bartender::registerProvider('google');
95
+ Bartender::registerProvider('microsoft');
96
+ }
97
+ }
98
+ ```
99
+
100
+ If your application uses a ` User ` model outside the ` App\Models ` namespace, you can set it using the ` Bartender ` facade:
101
+
102
+ ``` php
103
+ // app/Providers/AuthServiceProvider.php
104
+
105
+ use App\User;
106
+ use DirectoryTree\Bartender\Facades\Bartender;
107
+
108
+ class AuthServiceProvider extends ServiceProvider
109
+ {
110
+ // ...
111
+
112
+ public function boot()
113
+ {
114
+ Bartender::useUserModel(User::class);
115
+ }
116
+ }
117
+ ```
118
+
119
+ ## Usage
120
+
121
+ Direct your user to the ` /auth/{driver}/redirect ` route to authenticate with the given driver:
122
+
123
+ ``` blade
124
+ <a href="{{ route('auth.driver.redirect', 'google') }}">
125
+ Login with Google
126
+ </a>
127
+
128
+ <a href="{{ route('auth.driver.redirect', 'microsoft') }}">
129
+ Login with Microsoft
130
+ </a>
131
+ ```
132
+
133
+ Once the user successfully authenticates, they will be redirected to the ` /auth/{driver}/callback `
134
+ route, and the users account will automatically be created or updated.
135
+
136
+ ## Extending & Customizing
137
+
138
+ Almost everything can be swapped out in Bartender.
139
+
140
+
141
+ If you would like to handle everything yourself for redirects and callbacks, you may create your own ` ProviderHandler ` :
142
+
143
+ ``` php
144
+ namespace App\Socialite;
145
+
146
+ use Illuminate\Http\Request;
147
+ use DirectoryTree\Bartender\ProviderHandler;
148
+
149
+ class UserProviderHandler implements ProviderHandler
150
+ {
151
+ /**
152
+ * Constructor.
153
+ */
154
+ public function __construct(
155
+ protected Request $request
156
+ ) {
157
+ }
158
+
159
+ /**
160
+ * Handle redirecting the user to the OAuth provider.
161
+ */
162
+ public function redirect(Provider $provider, string $driver): RedirectResponse
163
+ {
164
+ // Perform additional logic here...
165
+
166
+ return $provider->redirect();
167
+ }
168
+
169
+ /**
170
+ * Handle an OAuth response from the provider.
171
+ */
172
+ public function callback(Provider $provider, string $driver): RedirectResponse
173
+ {
174
+ // Authenticate the user your own way...
175
+
176
+ return redirect()->route('dashboard');
177
+ }
178
+ }
179
+
180
+ ```
181
+
182
+
183
+ ### User Creation & Updating
184
+
185
+ If you would like to customize the creation of the user provider, you can create your own
186
+ ` UserProvider ` implementation:
187
+
188
+ ``` php
189
+ namespace App\Socialite;
190
+
191
+ use Illuminate\Contracts\Auth\Authenticatable;
192
+ use DirectoryTree\Bartender\ProviderRepository;
193
+ use Laravel\Socialite\Two\User as SocialiteUser;
194
+
195
+ class UserProviderRepository implements ProviderRepository
196
+ {
197
+ /**
198
+ * Determine if the user already exists under a different provider.
199
+ */
200
+ public function exists(string $driver, SocialiteUser $user): bool
201
+ {
202
+ // ...
203
+ }
204
+
205
+ /**
206
+ * Update or create the socialite user.
207
+ */
208
+ public function updateOrCreate(string $driver, SocialiteUser $user): Authenticatable
209
+ {
210
+ // ...
211
+ }
212
+ }
213
+ ```
214
+
215
+ Then, bind your implementation in the service container in your ` AppServiceProvider ` :
216
+
217
+ ``` php
218
+ namespace App\Providers;
219
+
220
+ use App\Socialite\UserProviderRepository;
221
+ use DirectoryTree\Bartender\ProviderRepository;
222
+
223
+ class AppServiceProvider extends ServiceProvider
224
+ {
225
+ // ...
226
+
227
+ public function register()
228
+ {
229
+ $this->app->bind(ProviderRepository::class, UserProviderRepository::class);
230
+ }
231
+ }
232
+ ```
233
+
234
+ ### User Redirects & Flash Messaging
235
+
236
+ If you would like to customize the behavior of the redirects and flash messages depending
237
+ on the outcome of a OAuth callback, you can create your own ` ProviderRedirector ` implementation:
238
+
239
+ ``` php
240
+ namespace App\Socialite;
241
+
242
+ class UserProviderRedirector implements ProviderRedirector
243
+ {
244
+ /**
245
+ * Redirect when unable to authenticate the user.
246
+ */
247
+ public function unableToAuthenticateUser(Exception $e, string $driver): RedirectResponse
248
+ {
249
+ return redirect()->route('login')->with('error', 'Unable to authenticate user.');
250
+ }
251
+
252
+ /**
253
+ * Redirect when the user already exists.
254
+ */
255
+ public function userAlreadyExists(SocialiteUser $user, string $driver): RedirectResponse
256
+ {
257
+ return redirect()->route('login')->with('error', 'User already exists.');
258
+ }
259
+
260
+ /**
261
+ * Redirect when unable to create the user.
262
+ */
263
+ public function unableToCreateUser(Exception $e, SocialiteUser $user, string $driver): RedirectResponse
264
+ {
265
+ return redirect()->route('login')->with('error', 'Unable to create user.');
266
+ }
267
+
268
+ /**
269
+ * Handle when the user has been successfully authenticated.
270
+ */
271
+ public function userAuthenticated(Authenticatable $user, SocialiteUser $socialite, string $driver): RedirectResponse
272
+ {
273
+ Auth::login($user);
274
+
275
+ return redirect()->route('dashboard');
276
+ }
277
+ }
278
+ ```
279
+
280
+ Then, bind your implementation in the service container in your ` AppServiceProvider ` :
281
+
282
+ ``` php
283
+ namespace App\Providers;
284
+
285
+ use App\Socialite\UserProviderRedirector;
286
+
287
+ class AppServiceProvider extends ServiceProvider
288
+ {
289
+ // ...
290
+
291
+ public function register()
292
+ {
293
+ $this->app->bind(ProviderRedirector::class, UserProviderRedirector::class);
294
+ }
295
+ }
296
+ ```
0 commit comments