In my Laravel 5.4 project I was trying to store a state token in my controller method like this..
use Illuminate\Support\Facades\Session ;
...
public function authorize()
{
Session::set('state', $client->getState());
A lot of code here...
header('Location: ' . $authorizationUrl);
exit;
}
I also tried using the helper function
session('state', $client->getState());
But no matter what I've tried the session would not be created or persist.
So I switched to using the Symfony component directly..
use Symfony\Component\HttpFoundation\Session\Session;
...
public function authorise()
{
$session = new Session();
$session->set('state', $client->getState());
...
}
Doing it this way works perfectly. Any explanation why the facade is not working?
As a reference if anyone else has an issue like this, the issue was being caused by a redirect, to an oauth url, before the function finishes, or a view was loaded etc. (i.e. the session gets stored at the end of the Laravel application "lifecycle".) This issue can manifest itself in any number of situations other than just a redirect, including using dd() or die()etc.
e.g. If your method is basically like this Sessions works fine.
public function myAwesomeMethod($params)
{
Session::put('theKey','theValue');
return view('theView'); //Session gets stored at this point.
}
However if your method looks like something like this you will have an issue.
public function myCoolMethod($authUrl)
{
Session::put('theKey','theValue');
header('Location: ' . $authUrl); //Session seems to be lost here.
exit;
}
The solution was simple but I missed it because of my unfamiliarity with the Laravel sessions. In the last example simply add the save() method to the Sessions class (if using the Facade) like in the following.
public function myCoolMethod($authUrl)
{
Session::put('theKey','theValue');
Session::save();// Session gets stored immediately
header('Location: ' . $authUrl);
exit;
}
Related
I have a LoginController where I do my usual login operation with combination of an email address and a password associated with the account.
I have separated my Hybridauth related code into a separate controller named OauthController where I have all my Hybridauth magic and where my callback / endpoint resides.
In the OauthController I check if user's email from the specified provider is already registered, and in either case I try to login that user with $this->Auth->setUser(object).
Whenever, or whatever from the $this->Auth is called, I get a response stating:
Session was already started
I have browser through CakePHP 3 code and found the following statement in:
vendor/cakephp/cakephp/src/Network/Session.php (335)
public function start()
{
if ($this->_started) {
return true;
}
if ($this->_isCLI) {
$_SESSION = [];
$this->id('cli');
return $this->_started = true;
}
if (session_status() === \PHP_SESSION_ACTIVE) {
throw new RuntimeException('Session was already started');
}
...
And that's the point in code where that message is thrown at me.
Now, as I browsed through the Hybridauth code itself, I have found following in:
vendor/hybridauth/hybridauth/src/Storage/Session.php (46)
public function __construct()
{
if (session_id()) {
return;
}
if (headers_sent()) {
throw new RuntimeException('HTTP headers already sent to browser and Hybridauth won\'t be able to start/resume PHP session. To resolve this, session_start() must be called before outputing any data.');
}
if (! session_start()) {
throw new RuntimeException('PHP session failed to start.');
}
}
And both of them call session_start, one before the other, although CakePHP's part is blocking me.
I have tried removing !session_start() check from Hybridauth, but then Hybridauth doesn't know where to read out it's thingies it needs to read.
So, as a demonstrator, I am trying to achieve this in OauthController:
<?php
namespace App\Controller;
use Hybridauth\Hybridauth;
class OauthController extends AppController
{
public function callback($provider)
{
try {
$hybridauth = new Hybridauth($config);
// additional mystery code
$hybridauth->authenticate();
if($everything_okay) {
$this->Auth->setUser($userObject); // and this is the point of failure
return $this->redirect('/account'); // and this never happends... :(
}
}
}
}
Any help, ideas, insights on how to deal with this are all welcome!
Simply start the CakePHP session manually before using the Hybridauth library, so that it bails out at the session_id() check and picks up the existing session.
For example in your controller:
$this->getRequest()->getSession()->start();
// in CakePHP versions before 3.6/3.5
// $this->request->session()->start();
I'm using CakePHP 3.5 and two of the methods I want to use are deprecated and I can't find an alternative.
The methods are:
$this->response->send();
$this->response->stop();
I want to redirect to a different page and stop the execution of the current method. I've tried calling die() after my redirect and it doesn't work.
According to the migration guide the methods have been made obsolete.
Any thoughts?
Edit:
I'm trying to redirect users without access to certain pages. This is in the initialize() method in the controllers.
if ($allowedAccess) {
$this->Flash->error("Insufficient rights to access that location");
$this->redirect($this->referer());
// FIXME - find alternative to deprecated methods
return $this->response;
$this->response->send();
$this->response->stop();
}
Are you trying this in a controller? Simply return the response object from your controllers method:
public function index() {
// Some code
return $this->response;
}
send() was just a wrapper around phps exit(). Use exit() if you need to somewhere.
What happens when you return the response is that the ActionDispatcher processes the return value and if it's a Response object. See the __invoke() method.
The response will go through the middleware layer and will be finally send by the ResponseEmitter which is used by the Server. Check your webroot/index.php to see it:
// Bind your application to the server.
$server = new Server(new Application(dirname(__DIR__) . '/config'));
// Run the request/response through the application
// and emit the response.
$server->emit($server->run());
<?php
include(APPPATH.'/libraries/REST_Controller.php');
class Quiz extends REST_Controller{
function __construct()
{
// Call the Model constructor
parent::__construct();
}
public function user_get()
{
$this->load->model('Quizmodel');
$data = $this->Quizmodel->getAll();
$this->response($data, 200);
}
function restclient()
{
$this->load->library('rest', array(
'server' => 'http://localhost/CodeIg/index.php/quiz/'
));
$userr = $this->rest->get('user','','json');
echo $userr;
}
}
?>
I am able to get JSON output if I type http://localhost/CodeIg/index.php/quiz/user in my browser, however if I type http://localhost/CodeIg/index.php/quiz/restclient it gives this error: {"status":false,"error":"Unknown method"}
I tried changing get to post but still the same error.
I referred this page https://code.tutsplus.com/tutorials/working-with-restful-services-in-codeigniter--net-8814 to do it.
You pinged me on GitHub, even though I haven't used or even thought about this code in at least 4 years.
https://github.com/chriskacerguis/codeigniter-restserver/blob/d19dc77f03521c7a725a4555407e1e4e7a85f6e1/application/libraries/REST_Controller.php#L680
This is where that error is being triggered. Throw a few breakpoints in there or var_dump()'s until you see what is causing the trouble.
You probably want to get off CodeIgniter though, and use something more actively maintained like SlimPHP or Lumen.
firstly I want as you have loaded rest api and created your controller quiz as an api to call , where you can only create your functions like user_get or restclient_get and access them the same manner you are doing.Just change you function name restclient to restclient_get then it will call instead it is even not running at this moment.
I'm building my own MVC framework in order to learn the ropes properly.
Ive managed to get a login system working, but sessions dont seem to be persisting across page changes.
Ive done some reason reading around and am running session_start() in the controller as a few people seem to be directing.
On login, my processLogin method runs successfully and stores the session data as expected. I know this has happened because Im doing a var_dump on it in the main header file and its there when the login form loads (im not destroying it at any point).
The trouble I have is when it comes to do a location change after successful login, it runs the 'gallery' method, the session array is still there, but empty.
Its exasperating and Id really appreciate any help.
Heres my extended controller class for reference:
session_start();
class Home extends Controller {
public function index() {
require 'application/views/_templates/header.php';
require 'application/views/home/index.php';
require 'application/views/_templates/footer.php';
}
// login function (validation carried out client side)
public function processLogin() {
if (isset($_POST['loginUsername'])) {
$home_model = $this->loadModel("HomeModel");
$home_model->processLogin($_POST['loginUsername'], $_POST['loginPassword']);
}
}
public function gallery() {
require 'application/views/_templates/header.php';
require 'application/views/home/gallery.php';
require 'application/views/_templates/footer.php';
}
}
First thing you should use session_start() at the beginning of main file, usually index.php and not in Controller (because we don't know how your framework is build.
You should make sure that everywhere in your webpage you use the same domain - for example with www. or without www. Otherwise you should use session_set_cookie_params() to set it other way (for example for all subdomains)
I started to create a small application using codeigniter framework
and i have dowloaded Facebook connect from github after creating my application inside facebook, at this moment all work alright my only problem is getUser() always return 0
i have create a facebook.php inside application/config/
alse i have extracting facebook.php & base_facebook.php inside application/libraries/
this is my code
class Welcome extends CI_Controller {
private $data = array();
public function index() {
$this->data['loginUrl'] = $this->facebook->getLoginUrl();
$this->data['userId'] = $this->facebook->getUser();
$this->load->view('welcome_message', $this->data);
}
}
in autoload
i have :
$autoload['libraries'] = array('database','session','facebook');
so why getUser() return 0 and how can i fix this problem
thx
on base_facebook.php, find the makeRequest() method, and, inside the function, find this line:
$opts = self::$CURL_OPTS;
Immediately following it, add:
$opts[CURLOPT_SSL_VERIFYPEER] = false;
or read from here
It does this, sometimes. I've never worked out why, but there is a simple solution that I now always follow.
As opposed to asking for getUser, ask for api(/me) wrapped in a try catch block. If this fails, user is not logged in/token is invalid. If it works the user is logged in, and you get the user id from the resultant array.
You're probably saving a call, as you'll ask for /me anyway. Just remember the try catch for error trapping!