sunny kashyap sunny kashyap - 2 months ago 4
PHP Question

Facebook login in laravel 5.2 can't hold the session after redirect

I am using Facebook PHP SDK to log my user.

I created a guard called login for this

Here is my config file of auth.php

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],

'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin'=>[
'driver'=>'session',
'provider'=>'adminusers',
],
'verify'=>[
'driver'=>'session',
'provider'=>'verify',
],
'login'=>[
'driver'=>'session',
'provider'=>'users'
]
],


to access Facebook api i created a class in App\services namespace called it Facebook

App\Services\Facbook.php

<?php
namespace App\Services;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config;

use App\Extensions\Facebook\FacebookLaravelPersistentDataHandler;
use Facebook\Facebook as FB;
use App;

class Facebook{

protected $fb;

protected $helper;

protected $permission;

protected $log;

protected $canvashelper;

protected $persistentDataHandler;

function __construct()
{
$this->fb = new FB([
'app_id'=>Config::get('facebook.app_id'),
'app_secret'=>Config::get('facebook.app_secret'),
'default_graph_version' => Config::get('facebook.default_graph_version'),
'persistent_data_handler' => new FacebookLaravelPersistentDataHandler(),
]);

$this->helper = $this->fb->getRedirectLoginHelper();

$this->permission = Config::get('facebook.permission');

$this->log = new Logging(Config::get('facebook.logfile'),'Facebook Log');

$this->canvashelper = $this->fb->getCanvasHelper();

$this->persistentDataHandler = new FacebookLaravelPersistentDataHandler();
}

public function FBAuthUrl()
{
if($this->isFBAuth())
{
return $this->helper->getLogoutUrl($this->persistentDataHandler->get('facebook_access_token'),route('facebook.logout'));
}
else
{
return $this->helper->getLoginUrl(route('facebook.callback'),$this->permission);
}
}

public function LoginCallback()
{
$accessToken = $this->helper->getAccessToken();
if(isset($accessToken))
{
$this->persistentDataHandler->set('facebook_access_token',(string) $accessToken);
}

}

public function isFBAuth()
{
return $this->persistentDataHandler->has('facebook_access_token');
}

public function getFBUser()
{
if($this->isFBAuth())
{
$this->fb->setDefaultAccessToken($this->persistentDataHandler->get('facebook_access_token'));
/*,user_birthday,user_tagged_places*/
$response = $this->fb->get("/me?fields=id,name,first_name,last_name,age_range,link,gender,locale,picture,timezone,updated_time,verified,email");
return $response->getGraphUser();
}
else
{
return false;
}
}

public function logout()
{
$this->persistentDataHandler->delete('facebook_access_token');
$this->persistentDataHandler->delete('state');
}

}


And Here is my UserController Where i write my login logic

class UserController extends Controller
{
.....
/*
* Facebook login callback function
* @param Object App\services\Facebook
* return redirect
*/

public function fbLogin(Facebook $facebook)
{
$facebook->LoginCallback();

/*
* get the usergraphnode from facebook
*/
$fbUser = $facebook->getFBUser();

/*
* Convert UserGraphNode User To Eloquent User
*/
$user = $this->getFBLoggedUser($fbUser);

/*
* Here Log the user in laravel System
*/
Auth::guard('login')->login($user);
//dump(Auth::guard($this->guard)->user());
dump(session()->all());
return reidrect('/');
}


public function getFBLoggedUser($fbUser)
{
if(User::where('email','=',$fbUser->getField('email'))->count())
{
$user = User::where('email','=',$fbUser->getField('email'))->first();
if($user->fb_app_id){
$user->fb_app_id = $fbUser->getField('id');
$user->save();
}
}
else
{
$user = $this->FBregister($fbUser);
}
return $user;
}


/**
* Register The user logged in from Facebook
*
* @param \Facebook\GraphNodes\GraphUser;
*
* return \App\Models\User
*/
public function FBregister($fbUser)
{
$user = new User();
$user->fname = $fbUser->getField('first_name');
$user->lname = $fbUser->getField('last_name');
$user->gender = $fbUser->getField('gender');
$user->email = $fbUser->getField('email');
$user->fb_app_id = $fbUser->getField('id');

$picture = $fbUser->getField('picture');
if($picture->isSilhouette()){
$user->profile_image = $picture->getUrl();
}

$user->save();

return $user;
}

.........
}


On Successful Facebook login redirect i am calling UserController@fbLogin
after calling
Auth::guard()->login()
i dump session it successfully show a
login_login_randomstring=>UserId
i session . but When i redirect it all session data lost.

But the weird thing is that it only happen when it calling through facebook redirect. If i use this function like normal login routes it works perfactaly like this

in route.php

Route::get('/login','UserController@login');


and in UserController

function login(){
$user = User::find(12);
Auth::guard('login')->login($user);
return redirect('/');
}


Using this method i can easily access Session data after redirecting from here but in facebook case it doesn't happening.

I stuck here for two days please anyone can help me

[Note: Please don't mention in your answer that i should grouped my routes in web middleware. ]

Answer

After digging very deep in laravel i finally found what i was doing wrong. And i am posting may be it help some in future.

Important thing :- Laravel save session very last in its request life-cycle. It saves session it sends header response. So if we echo something in controller class then it will send header response without doing saving session and our session will not save. In my case i use dump function in my controller which terminate the laravel default life-cycle and forcefully send header response to browser. that's why all of session data is lost. i remove dump() form my code and everything start working correctly