I am using Facebook-sdk bundle for Laravel and everything works fine, except the logout link. When I click logout, I get redirected and all looks like it is working, but when it loads the page back, I'm still logged in?
Is this a Laravel problem maybe? Does it store sessions differently?
I've built this class, but as I said, I don't think this is a problem because all is working fine, except logout session is not getting cleared.
Code:
class Fb{
// -----------------------------------------------------------------------
// Variables
private $ioc; // IOC container
public $state; // If logged or not
public $data; // Data that came from request
public $settings = array("name,gender");
// -----------------------------------------------------------------------
// Logical functions
public function __construct(){
$this->ioc = IoC::resolve('facebook-sdk');
if ($this->getUser()) {
try {
$this->request();
$this->state = true;
} catch (FacebookApiException $e) {
error_log($e);
}
}else{
$this->state = false;
}
}
public function getUser(){
return $this->ioc->getUser();
}
public function request(){
$this->data = $this->ioc->api("/me?fields=".implode($this->settings));
}
public function debug(){
return dd($this->data);
}
// -----------------------------------------------------------------------
// Login & Logout links
public function login(){
return $this->ioc->getLoginUrl();
}
public function logout(){
return $this->ioc->getLogoutUrl();
}
// -----------------------------------------------------------------------
// Get data via SDK
// Name
public function name(){
return $this->data['name'];
}
// Picture
public function picture($w=50,$h=50){
return "https://graph.facebook.com/". $this->data['id'] ."/picture?width=$w&height=$h";
}
// Gender
public function gender(){
return $this->data['gender'];
}
}
Thanks for any help!
Cheers!
The underlying facebook php sdk uses the built in php sessions (by default) to store persistent information like the authenticated facebook user's id.
However the sdk won't destroy this information on its own since it's difficult to tell when that should happen automatically.
You can clear this persisted information with the destroySession method on the facebook sdk object. The best place to call this method is on the logout url's redirect back endpoint, since that is where the visitor gets directly after facebook done with it's own logout.
This would look like:
// method on Fb class
public function destroySession() {
// just forward the call down to the sdk object
$this->ioc->destroySession();
}
You probably want to set up a route where users will arrive after logout and pass it into getLogoutUrl() like this:
// method on Fb class
public function logout(){
// tell explicity where to send the user when facebook is done, otherwise the current url will be used
return $this->ioc->getLogoutUrl(array('next' => URL::to_route('after_logout')));
}
And have a route like this:
Route::get('after_logout', array('as' => 'after_logout', 'do' => function() {
$fb = new Fb();
// call the session clearing
$fb->destroySession();
// send the user to its merry way
return Redirect::to('/');
}));
Related
I've been using Laravel-5.8.35. I was invoking a GET request through a form. On my route, I redirected the form action to the same controller where the form was submitted but redirected through a different route, as,
$router->get('/merchant/sd-refund', 'Reports\ReportController#refundSecurityDeposit');
And, in my refundSecurityDeposit method, I called my SohojSdRefundService service,
public function refundSecurityDeposit(Request $request)
{
// $userId, $reason, $sdAmount was fetched from the $request instance
$this->execRefundRequest($userId, $reason, $sdAmount);
}
public function execRefundRequest($userId, $reason, $sdAmount)
{
// here the API service request data was handled,
// and stored in $data instance
return SohojSdRefundService::callSdRefundApi($data);
}
While my SohojSdRefundService service was done handling, I wanted to redirect the route to another route, as,
class SohojSdRefundService
{
public function __construct()
{
}
public static function callSdRefundApi($requestData)
{
// call to other methods inside the class to handle the API response,
// and then return to the same route which isn't working
return redirect('/admin/merchant/list');
}
}
Respectively, instead of redirecting to that route, the page happens to be still on the /merchant/sd-refund?... where the form was submitted initially. I redirected another service like this, which is working fine though. Could anyone suggest what I could be implementing wrong here? TIA.
You need to return a result in refundSecurityDeposit fucntion
public function refundSecurityDeposit(Request $request)
{
return $this->execRefundRequest($userId, $reason, $sdAmount);
}
I am using Laravel framework. There is a function in controller that creates session with name store_id
StoreController.php
function initiate($id)
{
//Some queries
session['store_id' => 'some value'];
}
Now if I run this function on one tab then session::get('store_id') is going on. But if I open another tab in the same browser then again run the function that means session('store_id') will be again set. How do I handle this situation that if there is already a session then it should redirect to it's perspective url.
Okay first of all, Bruuuhhhh been there and done that
Alright, lets begin. you want that if there is already a session with store_id going on then you want user to redirect or send back.
In your controller add this
public function initiate()
{
if(session()->has('store_id'))
{
//What ever your logic
}
else
{
redirect()->to('/store')->withErrors(['check' => "You have session activated for here!."]);
}
}
Most probably you would be wondering that user can just go to other url after /store/other-urls Yess he can.
To avoid this. Add a custom middleware
php artisan make:middleware SessionOfStore //You can name it anything.
In that middleware
public function handle($request, Closure $next)
{
if($request->session()->has('store_id'))
{
return $next($request);
}
else
{
return redirect()->back()->withErrors(['privilege_check' => "You are not privileged to go there!."]);
}
return '/home';
}
in your main store page. Add an anchor tag Stop Service
Now in your web.php
Route::group(['middleware' => 'SessionOfStore'], function()
{
//Add your routes here.
Route::get('/stop', 'StoreController#flushSession');
});
Now you have restrict access to urls and has checked the sessions.
Now in
public function flushSession()
{
//empty out the session and
return redirect()->to('/home');
}
The Laravel session helper has the function has to check this.
if (session()->has('store_id'))
{
// Redirect to the store
}
else
{
// Set the store id
}
The documentation contains all of the possible functions that can be used with the session helper.
I want to redirect from a controller and pass data;
public function fortest(Request $request)
{
$user = DB::table('user2s')->where('name', $request->name)->first();
if (isset($user))
{
return redirect('/fortest2', ['user'=>$user]);//compact('user'));
//return $this->fortest2($request);
}
}
public function fortest2(Request $request)
{
return $request->name;
}
Route::get('/fortest', 'UserController#fortest');
Route::get('/fortest2/', 'UserController#fortest2');
The code works when calling the controller directly from within the controller. The data type has a model. How can I accomplish this?
If you want to pass data in a redirect, you can use the with() method.
You have to append it to the redirect like so:
redirect('/fortest2')->with('data', 'value');
It will be saved in your current session, so it will be only persistent until you refresh the page again. If you want to store it for longer you have to go with a database/textfile etc. You can then check for it using
if (session()->has('data')) { // check if it exists
$value = session('data'); // to retrieve value
}
You can also send errors with the redirect (from validation i.e.) using withErrors(), sending the current input with it using withInput()
For what you want to achieve, try using this in your controller. This will just send the users name with the redirect:
$user = DB::table('user2s')->where('name', $request->name)->first();
redirect('/fortest2')->with('username', $user->name);
You can then access is via session('username')
You need to use sessions to pass data when using redirect:
return redirect('/fortest2')->with('data', 'some data');
Then get data from session:
$data = session('data');
Or you can persist data in DB and then get it from there.
Try to do like this
public function fortest(Request $request)
{
$user = DB::table('user2s')->where('name', $request->name)->first();
if(isset($user))
{
return redirect('/fortest2/$user->name');
}
}
public function fortest2($name)
{
return $name;
}
Your route
Route::get('/fortest', 'UserController#fortest');
Route::get('/fortest2/{$name}', 'UserController#fortest2');
i use email verification for my registration.
after register i login user and keep it's id in session (i have a session class for storing user login info) and then send a link to his mail and after all i redirect user to another page and tell him please check ur mail and click....
this is link that i send to user mail(for now i just send to my mail by default)
$body.="<h4><a href='http://www.habibabdollahi.com/fani/home/activate.php?user=".$user->id.
"&code=".$user->mail_verify_code."'>فعال سازی</a></h4>";
in activate.php i verify user with his id and his code but it seem i dont access the session after click link in the mail.
but if if redirect user after register to the activate.php like the last link there is no problem and i have session in this situation.
redirect_to("home/activate.php"."?user=$user->id&code=$user->mail_verify_code");
whats the problem friends, i'm going to be mad!
just focus on session, i just want know why my session lost after redirect via mail
and this my session class
class Session{
public $user_id;
private $loged_in=false;
private $verified_mail=false;
private $verified_mobile=false;
private $user_type;
function __construct(){
session_start();
$this->check_login();
$this->check_verification();// ham mobile va ham mail ra check mikonad
$this->check_user_type();
}
/* It'es get method, that get the loged status */
public function is_logged_in(){
return $this->loged_in;
}
public function login($user){
//database should find user based on username and password
if($user){
$this->user_id=$_SESSION['user_id']=$user->id;
$this->loged_in=true;
}
}
public function verify_mobile($is_verified){
if($is_verified){
$this->verified=$_SESSION['verified_mobile']=$is_verified;
}else{
return false;
}
}
public function verify_mail($is_verified){
if($is_verified){
$this->verified=$_SESSION['verified_mail']=$is_verified;
}else{
return false;
}
}
/****** user type ra be khater miseparad *********************/
public function remember_user_type($user){
if($user){
$this->user_type=$_SESSION['user_type']=$user->user_type_id;
}
}
public function get_user_type(){
return $this->user_type;
}
private function check_user_type(){
if(isset($_SESSION['user_type'])){
$this->user_type=$_SESSION['user_type'];
}
}
// che mobile va ya che mail verify shode bashad okeye
public function get_is_verified(){
return ($this->verified_mobile || $this->verified_mail);
}
public function get_is_verified_mobile(){
return $this->verified_mobile;
}
public function get_is_verified_mail(){
return $this->verified_mail;
}
public function logout(){
unset($_SESSION['user_id']);
unset($this->user_id);
$this->loged_in=false;
}
public function get_user_id(){
return $this->user_id;
}
private function check_login(){
if(isset($_SESSION['user_id'])){
$this->user_id=$_SESSION['user_id'];
$this->loged_in=true;
}else{
unset($this->user_id);
$this->loged_in=false;
}
}//check_login
private function check_verification(){
if(isset($_SESSION['verified_mail'])){
$this->verified_mail=$_SESSION['verified_mail'];
//$this->verified=true;
}
if(isset($_SESSION['verified_mobile'])){
$this->verified_mobile=$_SESSION['verified_mobile'];
//$this->verified=true;
}
}
}//class end
$session=new Session();
//var_dump($session);
You may try this
if(isset($_SESSION['user_id'])){
$this->user_id=$_SESSION['user_id'];
$this->loged_in=true;
}
instead of
if(isset($_REQUEST['user'])){
$this->user_id=$_REQUEST['user'];
$this->loged_in=true;
}
because of use pass user parameter on url
$body.="<h4><a href='http://www.habibabdollahi.com/fani/home/activate.php?user=".$user->id.
"&code=".$user->mail_verify_code."'>فعال سازی</a></h4>";
After the verification code refresh the session and redirect the user
to login page When user coming for login then check if user is Active
then all user data is send to session Array
I am not Expert but give a advice
first take take user identity ID which you select for login
then send those ID to login function and then give him session
Just try that
private function check_login($userID){
Used Fetch Query there for login authentication and then give him to session ...
your session code is here......................... and redirect or return true
}
I am attempting to use the Facebook PHP SDK in conjunction with CodeIgniter to allow users to login to my site using Facebook Connect. No matter what I try, getUser() always returns 0, even after (apparently) successful authentication via Facebook.
CodeIgniter version: 2.1.3
Facebook PHP SDK version: 3.2.2
I have created a config file, facebook.php, in the application/config folder and I am loading the Facebook PHP SDK via CodeIgniter's $this->load->library(...) method. The library is indeed getting loaded and I can successfully call many of the get...() methods including getAccessToken(), getAppId() and getAppSecret(), all of which return their expected values.
Here is a stripped down version of my login controller: (note that I also provide an alternate method of logging in via email, hence the CodeIgniter session code sprinkled throughout)
class Login extends CI_Controller {
public function __construct()
{
//Call parent constructor
parent::__construct();
//Magic sauce - not sure if this is required but a lot of other people
//are recommending it to be included (happy to remove it if necessary)
parse_str($_SERVER['QUERY_STRING'], $_REQUEST);
//Load facebook library
$facebook_config = $this->load->config('facebook');
$this->load->library('facebook', $facebook_config);
}
public function index()
{
//Check if user is logged in
$user_id = $this->session->userdata('user_id');
$is_logged_in = $this->session->userdata('is_logged_in');
if(($is_logged_in) && ($user_id != 0)) {
//Logged in - redirect to game
redirect('game');
} else {
//Not logged in
//Get facebook login url
$facebook_data = array(
'redirect_uri' => 'hxxp://xxxxxxxx.com/facebook_login/',
'scope' => 'email'
);
$data['facebook_login_url'] = $this->facebook->getLoginUrl($facebook_data);
//Redirect to login form
$this->load->view('login/login_form', $data);
}
}
public function facebook_login()
{
//Always returns 0!! Even after authenticating via facebook!
$facebook_user_id = $this->facebook->getUser();
if ($facebook_user_id) {
try {
$user_profile = $this->facebook->api('/me');
print_r($user_profile);
} catch (FacebookApiException $e) {
echo $e->getMessage();
}
} else {
echo "Could not log in with Facebook";
}
}
}
The stripped down view (login_form.php) is as follows:
<html>
<head>
<title>Facebook Connect Test</title>
</head>
<body>
<a href='<? echo $facebook_login_url; ?>'>Login with Facebook</a>
</body>
</html>
I have a route that redirects hxxp://xxxxxxxx.com/facebook_login to the login/facebook_login method, which is working.
I am running this code on a live development server.
My current flow is as follows:
Load hxxp://xxxxxxxx.com/ (Routes to login controller, which loads login_form view)
Click "Login with Facebook" link
Facebook asks me to login (which I do)
Facebook asks me to give permission to my app (which I do)
Facebook redirects me to the url specified in the redirect_uri parameter, which is identical to the one on the app settings page
And here's where it all goes wrong. The $this->facebook->getUser() method ALWAYS returns 0, even after authentication.
I have been scouring the Facebook developer documentation and everywhere else on the internet I can think of trying to find an answer to this. I have come across many posts similar to this and have tried to apply the solutions suggested, but to no avail.
What am I doing wrong?
The getCode() method in base_facebook.php uses the $_REQUEST global to store data. PHP 5.3.0 and greater uses the "request_order" param in php.ini, and by default $_REQUEST does not contain Cookie variables.
Per php.net (http://php.net/manual/en/ini.core.php#ini.request-order):
"This directive describes the order in which PHP registers GET, POST and Cookie variables into the _REQUEST array. Registration is done from left to right, newer values override older values.
If this directive is not set, variables_order is used for $_REQUEST contents.
Note that the default distribution php.ini files does not contain the 'C' for cookies, due to security concerns."
So it looks like your options are to modify the getCode() method like Max Power did above, or update your php.ini and add the "C" value to the request_order setting.
I managed to solve my problem. The questions linked to by Qweick and Stéphane Bruckert had the solution. The problem lies in the getCode() function of the base_facebook.php file.
The getCode() function needs to be modified. The modifications I used are listed below.
Existing non-working code:
protected function getCode() {
if (isset($_REQUEST['code'])) {
if ($this->state !== null &&
isset($_REQUEST['state']) &&
$this->state === $_REQUEST['state']) {
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
return $_REQUEST['code'];
} else {
self::errorLog('CSRF state token does not match one provided.');
return false;
}
}
return false;
}
Modified working code:
protected function getCode() {
$server_info = array_merge($_GET, $_POST, $_COOKIE);
if (isset($server_info['code'])) {
if ($this->state !== null &&
isset($server_info['state']) &&
$this->state === $server_info['state']) {
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
return $server_info['code'];
} else {
self::errorLog('CSRF state token does not match one provided.');
return false;
}
}
return false;
}
The getUser() call now returns a valid user Id and the Facebook API calls now return valid data.
Thanks to everyone that helped point me in the right direction!