Let’s get started by creating a new Laravel project by running
composer create project laravel/laravel acme
Add laravel/socialite and facebook/graph-sdk to composer.json file
1 2 3 4 5 |
"require": { [...] // other dependencies "facebook/graph-sdk": "^5.6", "laravel/socialite": "^3.0", }, |
and run composer install to install them. We are using socialite package to authenticate users with Facebook OAuth service. After authentication, we’ll be storing user access token in the database and use it to make calls to OAuth service on the user’s behalf. I wrote a very detailed tutorial on social authentication with socialite. Follow the steps below to integrate Facebook SDK in your laravel application and using it to post to profile and pages.
Step 1: Create a Facebook App.
Visit facebook developers console and create a new app. Fill in details and create App ID. We’ll be using this app to authenticate users and post on their behalf. Go to Settings > Basic and copy app id and secret. Add a new product and choose Facebook login.
Step 2: Populate Facebook Credentials
Edit config/service.php file. Add following lines at the end of the services array.
1 2 3 4 5 6 |
'facebook' => [ 'client_id' => env('FACEBOOK_CLIENT_ID'), // Your Facebook App Client ID 'client_secret' => env('FACEBOOK_CLIENT_SECRET'), // Your Facebook App Client Secret 'redirect' => env('FACEBOOK_REDIRECT'), // Your application route used to redirect users back to your app after authentication 'default_graph_version' => 'v2.12', ], |
Edit your project’s .env file.
1 2 3 |
FACEBOOK_CLIENT_ID=APP_CLIENT_ID FACEBOOK_CLIENT_SECRET=APP_SECRET FACEBOOK_REDIRECT=https://localhost:3000/login/facebook/callback |
Step 3: Add Redirect URL to App Valid OAuth Redirect URIs
Go to your App > Products > Facebook Login > Settings and update Valid OAuth Redirect URIs. For apps created after March 2018, it’s compulsory to use HTTPS to use OAuth service. Even if you’re requesting from your local dev environment, you must have https enabled to make use of their service. You can’t disable Enforce HTTPS options in your app settings. If you’re on Windows platform, you can easily configure XAMPP to use HTTPS. If you’re running Linux, you can use a self-signed certificate with nginix or apache. After settings up your self-signed certs, you can enable allow-insecure-localhost flag in chrome://flags settings to allow requests to localhost over HTTPS even when an invalid certificate is presented.
Step4: Integrating Facebook
We are using Laravel service providers to bootstrap Facebook to avoid unnecessary instantiation of Facebook object every time we’ll be making calls to Facebook OAuth service. Create a new FacebookServiceProvider.
php artisan make:provider FacebookServiceProvider
Now edit app/Providers/FacebookServiceProviders.php and add following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php namespace App\Providers; use Facebook\Facebook; use Illuminate\Support\ServiceProvider; class FacebookServiceProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { $this->app->singleton(Facebook::class, function ($app) { $config = config('services.facebook'); return new Facebook([ 'app_id' => $config['client_id'], 'app_secret' => $config['client_secret'], 'default_graph_version' => 'v2.6', ]); }); } } |
In register() method of our service provider, we are defining an implementation of Facebook\Facebook in the service container. We are using Laravel’s built-in config() method to retrieve Facebook OAuth credentials from config/services.php file and using it to construct Facebook class object which we will be using throughout our application to make calls to Facebook API.
Step 4: Database Migrations
After populating database credentials in your project’s .env file. Modify and run migrations to create database tables nessary to store our OAuth user. This is what our User migration looks like.
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(); }); } |
Step 5: Setting up authentication routes and controllers
Run php artisan make:auth to generate Laravel’s default authentication scaffolding. Edit routes/web.php file to add social authentication routes.
1 2 3 |
Route::get('/login/facebook', 'Auth\LoginController@redirectToFacebookProvider'); Route::get('login/facebook/callback', 'Auth\LoginController@handleProviderFacebookCallback'); |
Edit app/Http/Controllers/Auth/LoginController.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use App\User; use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Support\Facades\Auth; use Laravel\Socialite\Facades\Socialite; class LoginController extends Controller { use AuthenticatesUsers; /** * Where to redirect users after login. * * @var string */ protected $redirectTo = '/home'; /** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('guest')->except('logout'); } /** * Redirect the user to the Facebook authentication page. * * @return \Illuminate\Http\Response */ public function redirectToFacebookProvider() { return Socialite::driver('facebook')->scopes([ "publish_actions, manage_pages", "publish_pages"])->redirect(); } /** * Obtain the user information from Facebook. * * @return void */ 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 } } |
In redirectToFacebookProvider() method, we are requesting publish and manage permissions for profile and pages by using Socialite scopes method. App user will be redirected to Facebook OAuth page after visiting /login/facebook route. Upon accepting they will be redirected back to login/facebook/callback route and we will retrieve their access token and profile details to create a new user or update existing one with a fresh token. Now we’ll be using this token to make calls to Graph API on the behalkf of user.
Retrieving User Profile via the Graph API
Let’s create a new controller to handle requests for using Graph API.
php artisan make:controller GraphController
Add an authenticated route to routes/web.php
1 2 3 4 5 |
Route::group(['middleware' => [ 'auth' ]], function(){ Route::get('/user', 'GraphController@retrieveUserProfile'); }); |
Now define retrieveUserProfile method in GraphController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?php namespace App\Http\Controllers; use Facebook\Exceptions\FacebookSDKException; use Facebook\Facebook; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class GraphController extends Controller { private $api; public function __construct(Facebook $fb) { $this->middleware(function ($request, $next) use ($fb) { $fb->setDefaultAccessToken(Auth::user()->token); $this->api = $fb; return $next($request); }); } public function retrieveUserProfile(){ try { $params = "first_name,last_name,age_range,gender"; $user = $this->api->get('/me?fields='.$params)->getGraphUser(); dd($user); } catch (FacebookSDKException $e) { } } } |
Posting to Profiles
Add a new method publishToProfile to GraphController for handling requests to create profile posts.
1 2 3 4 5 6 7 8 9 10 11 12 |
public function publishToProfile(Request $request){ try { $response = $this->api->post('/me/feed', [ 'message' => $request->message ])->getGraphNode()->asArray(); if($response['id']){ // post created } } catch (FacebookSDKException $e) { dd($e); // handle exception } } |
Add a corresponding route to routes/web.php call it.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?php [...] Route::group(['middleware' => [ 'auth' ]], function(){ Route::get('/user', 'GraphController@retrieveUserProfile'); Route::post('/user', 'GraphController@publishToProfile'); }); |
To confirm if your post was created, you can check id on the response object. If the request was successful it will be populated with the id of the newly created node. In case of an unsuccessful request, it will be null.
Posting to Pages
Method of posting to pages is different from profiles. When you’re posting to your profile, you’re using your own access token to make the request. Every page your manage has its own access token and you have to retrieve it before making any requests. Add a new method getPageAccessToken to GraphController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public function getPageAccessToken($page_id){ try { // Get the \Facebook\GraphNodes\GraphUser object for the current user. // If you provided a 'default_access_token', the '{access-token}' is optional. $response = $this->api->get('/me/accounts', Auth::user()->token); } catch(FacebookResponseException $e) { // When Graph returns an error echo 'Graph returned an error: ' . $e->getMessage(); exit; } catch(FacebookSDKException $e) { // When validation fails or other local issues echo 'Facebook SDK returned an error: ' . $e->getMessage(); exit; } try { $pages = $response->getGraphEdge()->asArray(); foreach ($pages as $key) { if ($key['id'] == $page_id) { return $key['access_token']; } } } catch (FacebookSDKException $e) { dd($e); // handle exception } } |
We’re passing $page_id to getPageAccessToken to retrieve access token. You can get your page id from about section of your facebook page. After retrieving all pages, we are returning access token. Now we’ll use this token to post to a page. Add publishToPage method to GraphController and route to call it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public function publishToPage(Request $request){ $page_id = 'YOUR_PAGE_ID'; try { $post = $this->api->post('/' . $page_id . '/feed', array('message' => request->message), $this->getPageAccessToken($page_id)); $post = $post->getGraphNode()->asArray(); dd($post); } catch (FacebookSDKException $e) { dd($e); // handle exception } } |
1 2 3 4 5 6 7 8 9 |
Route::group(['middleware' => [ 'auth' ]], function(){ Route::get('/user', 'GraphController@retrieveUserProfile'); Route::post('/user', 'GraphController@publishToProfile'); Route::post('/page', 'GraphController@publishToPage'); }); |
Creating Photo Posts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public function publishToProfile(Request $request){ $absolute_image_path = '/var/www/larave/storage/app/images/lorde.png'; try { $response = $this->api->post('/me/feed', [ 'message' => $request->message, 'source' => $this->api->fileToUpload('/path/to/file.jpg') ])->getGraphNode()->asArray(); if($response['id']){ // post created } } catch (FacebookSDKException $e) { dd($e); // handle exception } } |
To create a media post, all you have to do is to pass source along with text message. It should be an instance of FacebookFile entity. Calling fileToUpload('/path/to/file.jpg') with absolute image path also return an instance of FacebookFile.
I hope after following above steps, you’ll be able to easily integrate Facebook SDK into your Laravel app. I’ve also created an example project repository on github. However, If you’re still facing any issue, please comment and I’ll try to help you solve your problem.
Hi, great tutorial. I am just beginner in Laravel. I have implemented Facebook login feature in core PHP. Will try to use this feature in Laravel 5. Thanks for sharing it.
Nice tutorial got me up and running in no time. however please fix the “;” at Creating Photo Posts section
‘source’ => $this->api->fileToUpload(‘/path/to/file.jpg’);
should be
‘source’ => $this->api->fileToUpload(‘/path/to/file.jpg’)
Fixed!
Hi there, great article/tutorial btw. Have one question regarding video publishing, is that even possible while facebook remove ‘publish_actions’ permission?
Thanks
No, you can not since it’s deprecated. You can use ‘publish_pages’ to publish text, photo, and videos to your page. For profiles, it’s not possible anymore.
Hi, thank you for the great tutorial.
as Daniel said, facebook will be removing the
publish_actions
permission on August 1,so is there any way we can post directly to user profiles using the
access_token
?the Sharing product isn’t my option because it will break my purpose of “Sharing a content using my app in the background”.
Please reply, thank you
Hi, I am creating a app where in i am sharing the content of my page i.e, the photos and description to facebook but, the facebook is not taking the content of my page. Can u please help me out.
Are you publishing to profiles or pages? Facebook no longer lets you publish to user profiles feed. They revoked publish_actions permission for apps created after 24 April 2018. Use Facebook’s Share Dialog instead. If you’re unable to publish to pages, please be more specific about your issue.
Hi, I want the user to share the post on my company’s Facebook account without logging into the account. For Example: A user uploads the product for marketing then the post has to be shared to our company’s Facebook account without logging in, and not to his personal account. So can is it possible to do..?
You cannot post to user profiles with Facebook API anymore.
Thanks thank you so much for your reply and can u please elaborate why we cannot post as such.?
Invalid Scopes: publish_actions, manage_pages, publish_pages. This message is only shown to developers. Users of your app will ignore these permissions if present. Please read the documentation for valid permissions at: https://developers.facebook.com/docs/facebook-login/permissions
API has drastically changed since article was published.
Hi,
how can you run your project on https://localhost:8000 ? It works fine in http but not in https.
I have already enable on chrome://flags.
Do you have any ideas ?
Thanks for the tutorial !
Which OS and web server are you running?
Thank you, but how can i post picture with message on pages ? when i try with this endpoint : $response = $this->api->post(‘/photos’, [
‘message’ => $request->message,
‘source’ => $this->api->fileToUpload(‘/path/to/file.jpg’)],$token);
The picture is posted but never the message. Or when i try this
$this->api->post(‘/feed’, [
‘message’ => $request->message,
‘source’ => $this->api->fileToUpload(‘/path/to/file.jpg’)],$token);
The message is posted but never the picture.
I am also facing same problem
Can you tell how your problem solved
Hello
Great tutoriel. I have just one huge problem
I don’t know how to run the app on https://localhost:3000
I tried php artisan serve :3000 but, of course this will run on http
I read some where that laravel uses php’s inbuild server which is the native HTTP and does not support HTTPS. Thus, artisan serve command SSL is not possible 🙂
But since no one is referring to that here, there must be a solution … or maybe I am missing something…
I’am on ubuntu 18.04 and runing laravel on apache2 and php7.2
and I have set the ssl on local following the link you provided.
Can you help on this please?
You can use self-signed certificates with apache on ubuntu and configure your https virtual host in
/etc/apache2/sites-available/default-ssl.conf
file.After generating your self-signed certificates, edit your
default-ssl.conf
file and change path of these two directives and point them to your certificate and key.SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key
Also change your
DocumentRoot
and point it to your web app directory.Hi, can you hel me.. I’m geting:
Call to a member function post() on null
in GraphController.php (line 54)
I am getting this error “The default access token must be of type “string” or Facebook\AccessToken”
Be precise
How can I display all the user’s posts? I can only get a max of 275 posts.
I am getting this error while trying to upload image.
fopen(https://44xxx7f.ngrok.io/storage/postFiles/Screen Shot 2019-03-24 at 12.44.04 PM_1554708559.png): failed to open stream: HTTP request failed! HTTP/1.0 400 Bad request
Make sure your storage directory has read and write permissions. Assuming that you’re running apache to server your web app, do this.
sudo chown -R www-data:your_user storage && sudo chmod -R 775 storage
to change storage directory group and user.Hi, I am setup this project for post on facebook page but there are error class facebook not found.
please tell me about how this resolve.
Thanks for your tutorial. My Question is how can I create social share buttons as this page have i.e. share this post on fb twitter bla bla bla bla. show that i opens a popup for related social media as your page dose. Thanks
hi i already make my laravel project login with facebook with different method ,
and now i just want posting in facebook page with laravel please you can make short tutorial you explain within it ,
just how posting in facebook page with laravel 5.8
Hi dear ! how i can see all my facebook friend request and accept bulk requests it’s possible ???
thanks,nice one,its really usefull ,
thank you brother, do this work for laravel 6?
How can I now call post to page mehotd inside my Conroller? Can you give me example?
Hello, I would like to ask for example how I can use this inside another Controller. I have PostController with method store() for storing new posts to database. I would like to call publishToPage() from here.
public function handleProviderFacebookCallback()
{
$auth_user = Socialite::driver(‘facebook’)->user();
//dd($auth_user->token);
$user = User::updateOrCreate(
[
‘name’ => $auth_user->name,
‘token’ => $auth_user->token,
’email’ => $auth_user->email
]
);
Auth::login($user, true);
return redirect()->to(‘/’); // Redirect to a secure page
}
in this function ‘$auth_user->token’ get the token but did not saved in my database
(#100) source should represent a valid URL => I am having this error message from Facbook Api when adding stream option. fileToUpload() is working fine.
Hi, thanks for the tutorial.
I follow your instructions and I get this error when I try with the endpoint /user:
Required “app_id” key not supplied in config and could not find fallback environment variable “FACEBOOK_APP_ID”
Any suggestions?
Thanks!
Hi
I can’t post in my profile with publishToProfile()
Excetion
“Facebook\Exceptions\FacebookAuthorizationException: (#200) If posting to a group, requires app being installed in the group, and \
either publish_to_groups permission with user token, or both pages_read_engagement \
and pages_manage_posts permission with page token; If posting to a page, \
requires both pages_read_engagement and pages_manage_posts as an admin with \
sufficient administrative permission”
But I’m using “publishToProfile”
Hi,
Is your solution is valid in December 2021? FACEBOOK APIS ARE CHANGES. I WANT TO POST TO MY PAGE
No!