Why am I losing my session on page changes? - php

So I'm trying to integrate the PHP facebook SDK/API with codeigniter, because I love codeigniter, but for some reason I keep losing my facebook session as soon as I change pages from my base URL, I have printed the $_session and all i get is Array ( [fb_339393762762289_state] => cb8c201ed66ebcaa60407114aa92f001 ) any ideas why this is happening?
Here is what my controller looks like:
class Main extends CI_Controller {
var $user;
var $log_in_url;
var $log_out_url;
function __construct() {
parent::__construct();
$this->load->library('facebook');
$perams = array(
'scope' => 'user_about_me, read_friendlists',
'redirect_uri' => 'http://www.example.com/'
);
$this->user = $this->facebook->getUser();
$this->log_out_url = $this->facebook->getLogoutUrl();
$this->log_in_url = $this->facebook->getLoginUrl($perams);
print_r($this->user);
print_r($this->log_out_url);
print_r($this->log_in_url);
}
public function index() {
if ($this->user) {
try {
$data['user_profile'] = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$this->user = null;
}
}
if ($this->user) {
$data['logout_url'] = $this->log_out_url;
} else {
$data['login_url'] = $this->log_in_url;
}
$data['user'] = $this->user;
$this->load->view('templet/header', $data);
$this->load->view('main view');
$this->load->view('templet/footer');
}
public function account() {
if ($this->user) {
try {
$data['user_profile'] = $this->facebook->api('/me');
} catch (FacebookApiException $e) {
error_log($e);
$this->user = null;
}
}
if ($this->user) {
$data['logout_url'] = $this->log_out_url;
} else {
$data['login_url'] = $this->log_in_url;
}
$data['user'] = $this->user;
$this->load->view('templet/header', $data);
$this->load->view('account');
$this->load->view('templet/footer');
}
from what I can understand from the source code of the api is that it is in charge of handling sessions, so I don't understand why it keeps losing it.
I was thinking it could maybe have something to do with my Htaccess set up.. Ie. my url when i change pages looks like this www.example.com/index.php/controller_name/method_name/
also do i need to do anything with the $_GET vars? because that is one thing i noticed.. there seem to be some things passed in the URL, but they don't continue on to other pages.
any help on this would be greatly appreciated. I am really at a loss.

If you use CodeIgniter Session Library you must know that "The Session class does not utilize native PHP sessions. It generates its own session data"
CodeIgniter Session Class

my problem was somewhat simple, I kept loosing my session data any time I changed pages, and it tuns out the solution was quite simple. in the config file of CI you have to put you websites base URL, and I put and the session was being created for http://www.mysite.com/ so the php sdk/api created one session for the first url and another for the second.. thus i lost all of the data as soon as i changed pages. so it's a simple problem, but took a lot of trouble shooting.

Related

Getting Facebook session on Wordpress

BACKGROUND
We have a Wordpress site that requires a special kind of Facebook authentication. The WP site needs to authenticate a user with a different app, and then log the user into the app. The web app is built by us, and it has an API that the WP site uses to interact with it. Before we all get rowdy, this whole authentication process works using a normal login form. Using the API, we can easily see that the user is or is not logged into the app, and display that on the WP site.
PROBLEM
As stated, we need Facebook authentication. I am using Facebooks PHP SDK v4 and have it built into a custom plugin so as to keep the code seperate from the theme. When a user clicks on the FB icon, it shows the popup with the correct redirect URL. After a while, this popup closes, but there is nothing in the result. A few well placed var_dumps reveal that I'm not getting anything back from FacebookRedirectLoginHelper. This means I can't get the session which in turns means no user info.
CODE
As stated, I've created a plugin (ns-social.php) which handles everything. Here is that file:
/**
* Plugin Name: NS Social Plugin
*/
require_once 'ns-social-init.php';
require_once 'ns-callback-functions.php';
require_once 'ns-facebook.php' ;
$fb = null;
add_action('plugins_loaded','load_fb');
function load_fb() {
global $fb;
$fb = new WP_Facebook();
}
/**
* SOCIAL LOGIN CHECK
*/
function get_fb_url()
{
global $fb;
return $fb->login_url();
}
ns-social-init.php starts a session that FB can use:
/**
* Any functions that are required during initialisation of Wordpress or this plugin
*/
add_action('plugins_loaded', 'start_session');
function start_session()
{
if (!session_id()) {
session_start();
}
}
ns-callback-functions.php contains all the callback functions for the redirects. These are all shortcodes that are placed in pages, so the url will be www.site.com/facebook-callback and that page will only have [facebook-callback] in it which will handle the request.
add_shortcode('facebook_callback', 'facebook_callback');
function facebook_callback()
{
global $fb;
if (isset($_GET['error'])) {
if ($_GET['error'] == 'access_denied') {
echo "<script>
if(window.opener != null) {
window.close();
}
</script>";
exit;
}
}
$session = $fb->get_session();
$userArr = $fb->get_user();
$user['name'] = $userArr['first_name'];
$user['surname'] = $userArr['last_name'];
$user['email'] = $userArr['email'];
$user['verified'] = $userArr['verified'];
$_SESSION['registeruser'] = $user;
$_SESSION['registertype'] = 'Facebook';
$action = "";
die(var_dump($_SESSION,true));
if (user_exists($user['email'])) {
$action = '?login';
}
wp_redirect(home_url('social-register/' . $action));
}
And last but not least, my ns-facebook.php file:
use Facebook\FacebookRedirectLoginHelper;
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
class WP_Facebook
{
var $helper;
var $session;
var $permissions;
var $loginurl;
public function __construct()
{
// Initialize the SDK
FacebookSession::setDefaultApplication('0appId145', '00hahaitsmysecret23523');
$this->permissions = ['public_profile', 'email'];
$this->helper = new FacebookRedirectLoginHelper(home_url('facebook-callback'));
$this->loginurl = $this->helper->getLoginUrl($this->permissions);
}
/**
* Returns the login URL.
*
* #return string
*/
public function login_url()
{
return $this->loginurl;
}
/**
* Returns the current user's info as an array.
*/
public function get_user($session = null)
{
if(empty($session)) $session = $this->session;
if($session) {
/**
* Retrieve User's Profile Information
*/
// Graph API to request user data
$request = new FacebookRequest($session, 'GET', '/me');
$response = $request->execute();
// Get response as an array
$user = $response->getGraphObject()->asArray();
return $user;
}
return false;
}
public function get_session() {
try {
$this->session = $this->helper->getSessionFromRedirect();
} catch(FacebookRequestException $ex) {
// When Facebook returns an error
} catch(\Exception $ex) {
// When validation fails or other local issues
}
if ($this->session) {
return $this->session;
}
}
}
WHAT HAVE I TRIED
I've gone through quite a few questions on SO. What I have noticed is, when I first run the page, my FBRLH_state in my session is, abcdef for example. But when I get a response after clicking the login button, my FBRLH_state is xyz. I don't know if this has an effect on the outcome. If it could, how would I use this state? I don't set it, I'm assuming that the FB SDK does.
TL;DR
FB PHP SDK v4 is not sending back anything when I use FacebookRedirectLoginHelper. Why would it do this, and how do I fix it?
did you make a test with just the offical FacebookRedirectLoginHelper from official GitHub?
I have used the Facebook SDK a couple of times and never had a problem with missing returns.
So I fixed my issue with help from corvuszero's comment.
Here's the code in my ns-facebook.php file:
use Facebook\FacebookSession;
use Facebook\FacebookRequest;
use Facebook\FacebookRedirectLoginHelper;
class WP_Facebook
{
var $helper;
var $session;
var $permissions;
var $loginurl;
public function __construct()
{
// Initialize the SDK
FacebookSession::setDefaultApplication('303664476506500', '0197b7f08cc46f051ddb92dfba077484');
$this->permissions = ['public_profile', 'email'];
$this->helper = new FacebookRedirectLoginHelper( home_url('facebook-callback') );
try {
$this->session = $this->helper->getSessionFromRedirect();
} catch (FacebookRequestException $e) {
// handler
} catch (Exception $e) {
// handler
}
if(isset($_SESSION['fb_token'])) {
$this->session = new FacebookSession( $_SESSION['fb_token'] );
}
if($this->session) {
$_SESSION['fb_token'] = $this->session->getToken();
} else {
$this->loginurl = $this->helper->getLoginUrl($this->permissions);
}
}
/**
* Returns the login URL.
*
* #return string
*/
public function login_url()
{
return $this->loginurl;
}
/**
* Returns the current user's info as an array.
*/
public function get_user()
{
if($this->session) {
/**
* Retrieve User’s Profile Information
*/
// Graph API to request user data
$request = new FacebookRequest($this->session, 'GET', '/me');
$response = $request->execute();
// Get response as an array
$user = $response->getGraphObject()->asArray();
return $user;
}
return false;
}
public function get_session() {
return $this->session;
}
}

Laravel facebook-sdk bundle logout not working

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('/');
}));

Codeigniter lost session when cross controllers

I created a Facebook login on my site, then when I get data of a user logged, I created an array session to store the information of users in my controller.
I have problem with this session when I go to another page, my session gets lost, I don't know what happens with this?
I set the session like this: $this->session->set_userdata('fb_user_info', $user_info);
But, my own account login, I do the same way, it works on all pages.
My question is, Why does the session get lost?
Here is my code to set session when get user_info
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Account extends CI_Controller {
public function __construct()
{
parent::__construct();
//$this->authenticate();
// Facebook constructor code
$CI = & get_instance();
$CI->config->load("facebook",TRUE);
$config = $CI->config->item('facebook');
$this->load->library('facebook', $config);
public function index()
{
$user = $this->facebook->getUser();
if($user) {
try {
$user_info = $this->facebook->api('/me');
// Set session
$this->session->set_userdata('FB_SESSION_INFO', $user_info);
$args = $logout_url;
$data['getLogoutUrl'] = $this->facebook->getLogoutUrl($args);
} catch(FacebookApiException $e) {
echo '<pre>'.htmlspecialchars(print_r($e, true)).'</pre>';
$user = null;
}
} else {
$param = array('scope' => 'email','redirect_uri' => $mycurrent_url);
$data['getURLLogin'] = "Login with facebook";
}
}

How to store and change Zend_Auth session ID?

I've recently started using Zend Framework and I'm still pretty used to session_start, and assigning variables to certain session names (ie: $_SESSION['username'] == $username)
I'm trying to figure out how to do something similar to this in Zend. Right now, my auth script checks the credentials using LDAP against my AD server and, if successful, authenticates the user.
I want to create a script that will allow an admin user to easily "enter" someone else's session. Let's say admin1 had an active session and wanted to switch into user1's session. Normally I would just change the $_SESSION['username'] variable and effectively change the identity of the user logged in.
But with Zend, I'm not quite sure how to change the session info. For what it's worth, here's my authentication script:
class LoginController extends Zend_Controller_Action
{
public function getForm()
{
return new LoginForm(array(
'action' => '/login/process',
'method' => 'post',
));
}
public function getAuthAdapter(array $params)
{
$username = $params['username'];
$password = $params['password'];
$auth = Zend_Auth::getInstance();
require_once 'Zend/Config/Ini.php';
$config = new Zend_Config_Ini('../application/configs/application.ini', 'production');
$log_path = $config->ldap->log_path;
$options = $config->ldap->toArray();
unset($options['log_path']);
require_once 'Zend/Auth/Adapter/Ldap.php';
$adapter = new Zend_Auth_Adapter_Ldap($options, $username, $password);
$result = $auth->authenticate($adapter);
if ($log_path) {
$messages = $result->getMessages();
require_once 'Zend/Log.php';
require_once 'Zend/Log/Writer/Stream.php';
require_once 'Zend/Log/Filter/Priority.php';
$logger = new Zend_Log();
$logger->addWriter(new Zend_Log_Writer_Stream($log_path));
$filter = new Zend_Log_Filter_Priority(Zend_Log::DEBUG);
$logger->addFilter($filter);
foreach ($messages as $i => $message) {
if ($i-- > 1) { // $messages[2] and up are log messages
$message = str_replace("\n", "\n ", $message);
$logger->log("Ldap: $i: $message", Zend_Log::DEBUG);
}
}
}
return $adapter;
}
public function preDispatch()
{
if (Zend_Auth::getInstance()->hasIdentity()) {
// If the user is logged in, we don't want to show the login form;
// however, the logout action should still be available
if ('logout' != $this->getRequest()->getActionName()) {
$this->_helper->redirector('index', 'index');
}
} else {
// If they aren't, they can't logout, so that action should
// redirect to the login form
if ('logout' == $this->getRequest()->getActionName()) {
$this->_helper->redirector('index');
}
}
}
public function indexAction()
{
$this->view->form = $this->getForm();
}
public function processAction()
{
$request = $this->getRequest();
// Check if we have a POST request
if (!$request->isPost()) {
return $this->_helper->redirector('index');
}
// Get our form and validate it
$form = $this->getForm();
if (!$form->isValid($request->getPost())) {
// Invalid entries
$this->view->form = $form;
return $this->render('index'); // re-render the login form
}
// Get our authentication adapter and check credentials
$adapter = $this->getAuthAdapter($form->getValues());
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if (!$result->isValid()) {
// Invalid credentials
$form->setDescription('Invalid credentials provided');
$this->view->form = $form;
return $this->render('index'); // re-render the login form
}
// We're authenticated! Redirect to the home page
$this->_helper->redirector('index', 'index');
}
public function logoutAction()
{
Zend_Auth::getInstance()->clearIdentity();
$this->_helper->redirector('index'); // back to login page
}
}
Is there any way to do what I have described? Thanks for any suggestions.
Given your code, the result of authenticating is stored in the PHP session through a Zend_Auth_Storage_Session object.
Calling Zend_Auth::getIdentity() gets access to the storage and returns the result if it is not empty. Likewise, you can change the stored identity by getting access to the underlying storage and changing its value. The actual identity stored as a result of authenticating with Zend_Auth_Adapter_Ldap is just a string value representing the LDAP username.
To effectively change the logged in user, you can do:
Zend_Auth::getInstance()->getStorage()->write('newUserName');
This assumes the default behavior which should be in place given your code.
What I do in my applications after successful authentication is to create a new object of some User model, and write that to the Zend_Auth session so that I have more information about the user available in each session, so you should be aware that different things can be in the storage depending on the application.
This is what I do for example:
$auth = new Zend_Auth(...);
$authResult = $auth->authenticate();
if ($authResult->isValid() == true) {
$userobj = new Application_Model_UserSession();
// populate $userobj with much information about the user
$auth->getStorage()->write($userobj);
}
Now anywhere in my application I call Zend_Auth::getInstance()->getIdentity() I get back the Application_Model_UserSession object rather than a string; but I digress.
The information that should help you is:
$user = Zend_Auth::getInstance()->getIdentity(); // reads from auth->getStorage()
Zend_Auth::getInstance()->getStorage()->write($newUser);

CakePHP Ajax Login System

I am trying to create an ajax login script but have hit a wall. I hav built one before but now using the cakephp framwework.
I'm not really sure ho to go about this. At the moment I have a login function in the controller,
public function login()
{
if($this->request->is('post')) {
if($this->Auth->login()) {
$this->Session->setFlash('Login Passed');
} else {
$this->Session->setFlash('Login Failed');
}
}
}
Do i then use ajax to send values to this from the form? These lines are from my old (non-cakephp) system,
xmlhttp.open("POST","http://www.site.com/login/",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("AttemptLogin=true&AccountEmail="+ userMail +"&AccountPassword=" + userPass);
Should i modify them in any way? Also, how do i handle any validations and login attempts with errorsetc.
Sorry about the question being quite open ended and long but i don't know where to go,I have looked for tutorials but can't find any.
Many Thanks
Chris
You can use javascript helper from cake and have one template that converts
the response to the json format, in the controller just include the helper:
var $helpers = array('Javascript');
var $components = array('RequestHandler');
//the template ie "/views/templates/ajax.ctp"
echo $javascript->object(isset($response) ? $response : array());
So yo can set you function like:
public function login()
{
if($this->RequestHandler->isPost()) {
if($this->Auth->login()) {
$response('success'=>true);
} else {
$response('success'=>false);
}
$this->set('response', $response);
$this->render(null, 'ajax');
}
And the javascript i recommend jQuery
$.ajax({url:"/controller/login",type:"POST", data:$('#formLogin').serialize(), dataType:"json", success:responseLogin, context:this});
function responseLogin(response)
{
//here is the object returned by cakephp
if(!response.success)
//do something the user don't login
else
//do something the user pass the login
}

Categories