Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. ]

like image 736
sunny kashyap Avatar asked Sep 12 '16 10:09

sunny kashyap


2 Answers

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

like image 121
sunny kashyap Avatar answered Sep 20 '22 12:09

sunny kashyap


According to API documentation https://laravel.com/api/5.2/Illuminate/Auth/Guard.html you should call user() method to get the currently authenticated user. So i would suggest that instead of Auth::guard() use Auth::user($user).

like image 45
Dean Gite Avatar answered Sep 19 '22 12:09

Dean Gite