After a fresh Laravel installation run php artisan make:auth to generate the conventional form-based authentication scaffolding that will take care of your applications entire authentication system by setting up routes, views, and controllers for registration, authentication and password reset.

Now to setup Social authentication, we need to install laravel/socialite package by running composer require laravel/socialite. Laravel Socialite provides an eloquent way to authenticate with OAuth providers. It currently supports authentication with Facebook, Twitter, LinkedIn, Google, GitHub, and Bitbucket. But, there are adapters available for many other platforms developed by faustbrian. For this tutorial, I’m using Facebook OAuth for social authentication. We can start off by creating a new Facebook app by visiting developers.facebook.com. Name it whatever you want and enter your contact email address. Submit and fill in the captcha and your app will be created.

After creating your app, go to Settings > Basic. Click Show to reveal app secret.

Now we will use these OAuth credentials for Facebook in config/services.php

return [ [...] // other services 'facebook' => [ 'client_id' => env('FACEBOOK_CLIENT_ID'), // Your Facebook Client ID 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), // Your Facebook Client Secret 'redirect' => env('FACEBOOK_REDIRECT'), ], ] 1 2 3 4 5 6 7 8 9 return [ [ . . . ] // other services 'facebook' = > [ 'client_id' = > env ( 'FACEBOOK_CLIENT_ID' ) , // Your Facebook Client ID 'client_secret' = > env ( 'FACEBOOK_CLIENT_SECRET' ) , // Your Facebook Client Secret 'redirect' = > env ( 'FACEBOOK_REDIRECT' ) , ] , ]

Now edit your projects .env file and fill in your own app credentials at the end of the file.

[...] // other env variables FACEBOOK_CLIENT_ID=YOUR_APP_ID FACEBOOK_CLIENT_SECRET=YOUR_APP_SECRET FACEBOOK_REDIRECT=https://localhost:3000/login/facebook/callback 1 2 3 4 5 [ . . . ] // other env variables FACEBOOK_CLIENT_ID = YOUR_APP_ID FACEBOOK_CLIENT_SECRET = YOUR_APP_SECRET FACEBOOK_REDIRECT = https : //localhost:3000/login/facebook/callback

You also need to update your apps Valid OAuth Redirect URIs to allow incoming authentication requests for your app. Go to your app products and add Facebook login. Go to its settings and add your OAuth redirect URL.

All apps created after March 2018 requires HTTPS for OAuth Redirects. What this means is that you must have HTTPS enabled for your site in order to use Facebook OAuth services. Enforce HTTPS option can’t be turned off for apps created after March 2018, you need to use HTTPS even if you’re in a test environment and requesting from your localhost. If you self-host your app on digitalocean or any other VPS server and owns a domain, you can easily setup free LetsEncrypt SSL certificate. If you don’t have HTTPS and redirect to OAuth, you’ll be welcomed with this message stating that

Insecure Login Blocked: You can’t get an access token or log in to this app from an insecure page. Try re-loading the page as https://

If you’ve managed to bypass this setting for your local dev environment, please share it by posting a comment. Now we’ll be adding a link to our existing login form that will take the user to facebook authentication page. Edit your existing login view resources/views/auth/login.blade.php and add following HTML code.

@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <div class="panel panel-default"> <div class="panel-heading">Login</div> <div class="panel-body"...> <div class="panel-heading">Login with Facebook</div> <div class="panel-body"> <a class="btn btn-primary" href="/login/facebook"> Facebook Login </a> </div> </div> </div> </div> </div> @endsection 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @ extends ( 'layouts.app' ) @ section ( 'content' ) <div class = "container" > <div class = "row" > <div class = "col-md-8 col-md-offset-2" > <div class = "panel panel-default" > <div class = "panel-heading" > Login </div> <div class = "panel-body" . . . > <div class = "panel-heading" > Login with Facebook </div> <div class = "panel-body" > <a class = "btn btn-primary" href = "/login/facebook" > Facebook Login </a> </div> </div> </div> </div> </div> @ endsection

We need to define routes and methods for Facebook authentication. We can start off by defining routes in routes/web.php file.

Route::get('/login/facebook', 'Auth\LoginController@redirectToFacebookProvider'); Route::get('login/facebook/callback', 'Auth\LoginController@handleProviderFacebookCallback'); 1 2 3 Route:: get ( '/login/facebook' , 'Auth\LoginController@redirectToFacebookProvider' ) ; Route:: get ( 'login/facebook/callback' , 'Auth\LoginController@handleProviderFacebookCallback' ) ;

and adding methods to handle requests in app/Http/Controllers/Auth/LoginController.php

/** * Redirect the user to the Facebook authentication page. * * @return \Illuminate\Http\Response */ public function redirectToFacebookProvider() { return Socialite::driver('facebook')->redirect(); } /** * Obtain the user information from Facebook. * * @return void */ public function handleProviderFacebookCallback() { $user = Socialite::driver('facebook')->user(); // Fetch authenticated user dd($user); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /** * Redirect the user to the Facebook authentication page. * * @return \Illuminate\Http\Response */ public function redirectToFacebookProvider ( ) { return Socialite:: driver ( 'facebook' ) -> redirect ( ) ; } /** * Obtain the user information from Facebook. * * @return void */ public function handleProviderFacebookCallback ( ) { $user = Socialite:: driver ( 'facebook' ) -> user ( ) ; // Fetch authenticated user dd ( $user ) ; }

Now when users click on Facebook Login button, they will be redirected to the Facebook authentication page and after allowing the app to use your information, they will be redirected back to https://localhost:3000/login/facebook/callback URI which will call handleProviderFacebookCallback() method. We are fetching authenticated user by calling Socialite::driver('facebook')->user(); and dumping it.

To save the user, we need to setup database for our application. Add your database credentials in your project .env file.

DB_DATABASE=socialite DB_USERNAME=root DB_PASSWORD=secret 1 2 3 DB_DATABASE = socialite DB_USERNAME = root DB_PASSWORD = secret

We also need to run database migrations to create user table but before doing that we need to modify it to store OAuth user. Edit your CreateUsersTable Migrations which resides in database/migrations folder.

public function up() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->string('password')->nullable(); // Set to nullable $table->string('token'); // OAuth Token $table->rememberToken(); $table->timestamps(); }); } 1 2 3 4 5 6 7 8 9 10 11 12 public function up ( ) { Schema:: create ( 'users' , function ( Blueprint $table ) { $table -> increments ( 'id' ) ; $table -> string ( 'name' ) ; $table -> string ( 'email' ) -> unique ( ) ; $table -> string ( 'password' ) -> nullable ( ) ; // Set to nullable $table -> string ( 'token' ) ; // OAuth Token $table -> rememberToken ( ) ; $table -> timestamps ( ) ; } ) ; }

We made two changes to default migration. We are allowing nullable on password and adding a token column to user’s table to store OAuth token. Run php artisan migrate to migrate tables. Now we are modifying handleProviderFacebookCallback() method to create a new user when they redirect back after successful authentication from OAuth page.

public function handleProviderFacebookCallback() { $auth_user = Socialite::driver('facebook')->user(); $user = User::updateOrCreate( [ 'email' => $auth_user->email ], [ 'token' => $auth_user->token, 'name' => $auth_user->name ] ); Auth::login($user, true); return redirect()->to('/'); // Redirect to a secure page } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public function handleProviderFacebookCallback ( ) { $auth_user = Socialite:: driver ( 'facebook' ) -> user ( ) ; $user = User:: updateOrCreate ( [ 'email' = > $auth_user -> email ] , [ 'token' = > $auth_user -> token , 'name' = > $auth_user -> name ] ) ; Auth:: login ( $user , true ) ; return redirect ( ) -> to ( '/' ) ; // Redirect to a secure page }

We are using Eqlouent’s updateOrCreate() method to create a new user. The first argument passed to this method check whether a user with this emails exists or not if it exists we update token and name columns of the user table. If it doesn’t exist we create a new user with email, token and name. Make sure you add token attribute to $fillable array on your User model to avoid mass Eloquent assignment exception.

protected $fillable = [ 'name', 'email', 'password', 'token' ]; 1 2 3 protected $fillable = [ 'name' , 'email' , 'password' , 'token' ] ;

After creating or updating user, we are using login method on Auth facade to sign them into our application and redirecting them to a secure page. From a security point of view, it’s not recommended to store OAuth tokens in your database. If you’re using OAuth to just authenticate users for your application and not storing token to make calls to service on the behalf of the user, then it is recommended that you do not store it in your database. If you put them in sessions, it will still be saved on disk and can be abused in case your machine gets compromised. The recommended way is to always encrypt them before storing them in database or sessions. You can use Laravel Encrypter which provides AES-256 and AES-128 encryption. You can decrypt token at any time and make call to the service. If you’ve followed all the steps and still having trouble setting up OAuth authentication, comment and I’ll try to help you with your issue.