In addition to the Laravel Breeze starter kit, we will allow users to login and register via GitHub, Google, and Facebook. In this part we will implement this feature using official Laravel package Laravel socialite.
By the end of this lesson, we will have this view:
First, we need to install this package, and add fields to Users
table for each provider, where providers ID will be saved.
composer require laravel/socialitephp artisan make:migration "add socialite fields to users table"
database/migrations/xxxx_add_socialite_fields_to_users_table.php:
return new class extends Migration { public function up(): void { Schema::table('users', function (Blueprint $table) { $table->after('password', function (Blueprint $table) { $table->string('facebook_id')->nullable(); $table->string('google_id')->nullable(); $table->string('github_id')->nullable(); }); }); }};
Of course, don't forget to add filables to the User
Model.
app/Models/User.php:
class User extends Authenticatable{ // ... protected $fillable = [ 'name', 'email', 'password', 'facebook_id', 'google_id', 'github_id', ]; // ...}
And for users migrations, we need to set default for name
field, because users name will be updated after being created.
database/migrations/2014_10_12_000000_create_users_table.php:
return new class extends Migration{ public function up(): void { Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name')->default(''); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); }); }};
To be able to connect with the providers, we will need to set credentials for each provider. These values needs to set in your .env
file and then used in the config/services.php
.env:
GITHUB_CLIENT_ID=GITHUB_CLIENT_SECRET= FACEBOOK_CLIENT_ID=FACEBOOK_CLIENT_SECRET= GOOGLE_CLIENT_ID=GOOGLE_CLIENT_SECRET=
config/services.php:
return [ // ... 'github' => [ 'client_id' => env('GITHUB_CLIENT_ID'), 'client_secret' => env('GITHUB_CLIENT_SECRET'), 'redirect' => '/auth/github/callback', ], 'facebook' => [ 'client_id' => env('FACEBOOK_CLIENT_ID'), 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), 'redirect' => '/auth/facebook/callback', ], 'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => '/auth/google/callback', ], ];
TIP: Be a good developer and always provide env keys into
.env.example
.
Next, the controller:
php artisan make:controller Auth/SocialiteController
app/Http/Controllers/Auth/SocialiteController.php:
class SocialiteController extends Controller{ public function loginSocial(Request $request, string $provider): RedirectResponse { $this->validateProvider($request); return Socialite::driver($provider)->redirect(); } public function callbackSocial(Request $request, string $provider) { $this->validateProvider($request); $response = Socialite::driver($provider)->user(); $user = User::firstOrCreate( ['email' => $response->getEmail()], ['password' => Str::password()] ); $data = [$provider . '_id' => $response->getId()]; if ($user->wasRecentlyCreated) { $data['name'] = $response->getName() ?? $response->getNickname(); event(new Registered($user)); } $user->update($data); Auth::login($user, remember: true); return redirect()->intended(RouteServiceProvider::HOME); } protected function validateProvider(Request $request): array { return $this->getValidationFactory()->make( $request->route()->parameters(), ['provider' => 'in:facebook,google,github'] )->validate(); }}
Now we need to add routes.
routes/auth.php:
Route::middleware('guest')->group(function () { // ... Route::get('auth/{provider}/redirect', [SocialiteController::class, 'loginSocial']) ->name('socialite.auth'); Route::get('auth/{provider}/callback', [SocialiteController::class, 'callbackSocial']) ->name('socialite.callback');});// ...
And last thing, add links in the login and register pages. Because we will add them in two pages, we will create a Blade Component to reuse them, also if you will want to remove one of the providers, or add new one, you will need to edit only in one file.
php artisan make:component SocialLinks --view
resources/views/components/social-links.blade.php:
<div class="mt-4 space-y-2"> <a class="inline-flex w-full items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-xs font-semibold uppercase tracking-widest text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-25" href="{{ route('socialite.auth', 'github') }}"> GitHub </a> <a class="inline-flex w-full items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-xs font-semibold uppercase tracking-widest text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-25" href="{{ route('socialite.auth', 'google') }}"> Google </a> <a class="inline-flex w-full items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-xs font-semibold uppercase tracking-widest text-gray-700 shadow-sm transition duration-150 ease-in-out hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 disabled:opacity-25" href="{{ route('socialite.auth', 'facebook') }}"> Facebook </a></div>
In both resources/views/auth/login.blade.php
and resources/views/auth/register.blade.php
use this component just before layouts end.
// ... </form> <x-social-links /> </x-guest-layout>
Now your users will be able to login or register using GitHub, Google, or Facebook providers.
In the "app/Http/Controllers/Auth/SocialiteController.php" code you missing all the important imports...
look like imports are missing from more examples costing errors in VSCODE and make new users frustrated.
Also a typo at: recoures/views/components/social-links.blade.php: clearly need to be resources
Now your users will be able to login or register using GitHub, Google, or Facebook providers. NO they wouldn't you may want to include how to setup this GitHub, Google, or Facebook providers on those sites with the callback urls and so on...
Well, we often miss the "use" section because we think that it's understandable that you should include a new class on top. But ok, will be more careful next time and explain everything.
Also, we add a GitHub repository at the end, to double-check for everyone.
Thanks for proofreading, fixed the typo with "recoures"
Povilas im just curious is it okay to do the callbackSocial method like this? instead of using firstOrCreate i used updateOrCreate, while putting the name and provider id there altogether in one statement.
Haven't tried, but it looks good, should work!
Amazed by the directions. Excellent course!
Hello,
Is it possible to skip this section? I am building this into a local laravel project where I already am a admin user. Thanks for your reaction.
You can skip the parts that are not needed for you. This is integrating the social login, so if you don't want/need this, you can definitely skip