How to pickup old session handling from Drupal after using SimpleSAMLphp? - php

Code example:
<?php
require_once(DRUPAL_ROOT . '/simplesaml/lib/_autoload.php');
session_write_close();
session_set_save_handler(new SessionHandler(), true);
$as = new \SimpleSAML\Auth\Simple('default-sp');
$as->requireAuth();
$attributes = $as->getAttributes();
$samlSession = \SimpleSAML\Session::getSessionFromRequest();
$samlSession->cleanup();
$_SESSION['saml'] = $attributes; // <-- this does not work, since altering $_SESSION at this point is useless. reading out $_SESSION on a another page does not have anything saved after calling the SimpleSAMLphp functions
We are using SimpleSAMLphp on our website as SP to use with a Shibboleth IDP. The server cant run the apache modules or memcache so we need to use PHP sessions. On the simplesamlphp documentation it says:
If we are using PHP sessions in SimpleSAMLphp and in the application
we are protecting, SimpleSAMLphp will close any existing session when
invoked for the first time, and its own session will prevail
afterwards. If you want to restore your own session after calling
SimpleSAMLphp, you can do so by cleaning up the session like this:
$session = \SimpleSAML\Session::getSessionFromRequest();
$session->cleanup();
If you don't cleanup SimpleSAMLphp's session and try to use $_SESSION
afterwards, you won't be using your own session and all your data is
likely to get lost or inaccessible.
The problem is, that is exactly the issue we are facing. Whatever I write into $_SESSION after loading the SSP files is lost at the new page request.
Now, we are using Drupal 7. I dont know how to implement the documentation code in a Drupal environment:
// use custom save handler
session_set_save_handler($handler); // what is this? what is $handler?
session_start();
// close session and restore default handler
session_write_close();
session_set_save_handler(new SessionHandler(), true);
// use SimpleSAML\Session
$session = \SimpleSAML\Session::getSessionFromRequest();
$session->cleanup();
session_write_close();
// back to custom save handler
session_set_save_handler($handler); // how do i get the Drupal handler?
session_start();
So how do I implement the session swapping in a Drupal 7 environment? Or generally, how do I get a session handler/ reference?
Drupal itself does this at some point in session.inc:
session_set_save_handler('_drupal_session_open', '_drupal_session_close', '_drupal_session_read', '_drupal_session_write', '_drupal_session_destroy', '_drupal_session_garbage_collection');
But calling any Drupal session function didnt work, $_SESSION was always unwritable (or rather didnt actually save) after using SimpleSAMLphp.

Edited:
If you are not using SimpleSAMLphp's stand-alone web UI, this might work:
require_once(DRUPAL_ROOT . '/simplesaml/lib/_autoload.php');
$as = new \SimpleSAML\Auth\Simple('default-sp');
$as->requireAuth();
$attributes = $as->getAttributes();
$samlSession = \SimpleSAML\Session::getSessionFromRequest();
$samlSession->cleanup();
$_SESSION['saml'] = $attributes;
It should keep your original session handler (which would also be used by SSP), then reload the old session ID by restoring previous session id and name.
Original answer:
Looking at the SimpleSAMLphp session handler's code it should already recover the previous session - If there are any active in the moment of invoking SimpleSAMLphp.
I would say that what happens here is that you manually closed the session by using session_write_close(); before SimpleSAMLPhp started theirs, so when you closed SimpleSAMLphp's session, the previous one could not be restored.
I would try to do as follows (I assumed it is the code you are using):
// If I recall well, Drupal already starts session for you,
// but if it's not the case in your configuration, go ahead and uncomment following lines
// session_set_save_handler($handler);
// session_start();
// use SimpleSAML\Session
$session = \SimpleSAML\Session::getSessionFromRequest();
$session->cleanup();
// Just resume your $_SESSION use
$_SESSION['myAttribute'] = 'myValue';

Related

when i disconnect the azure user he remains in the saml2 session

I have an app integrated with saml2 on azure, on my system I always check to see if the user is logged in using:
$as = new \SimpleSAML\Auth\Simple('default-sp');
$as->requireAuth();
however when I log out the user from azure the requireAuth returns that the user is still logged in, only when I close the browser and enter it again it sends the user to log in again.
Using PHP sessions in SimpleSAMLphp will close any existing session when invoked for the first time, and its own session will prevail afterwards.
If you want to restore your own session after calling SimpleSAMLphp, you can cleaning up the session by using following steps:
$session = \SimpleSAML\Session::getSessionFromRequest();
$session->cleanup();
If you don't want to cleanup SimpleSAMLphp's session and try to use $_SESSION afterwards, you won't be using your own session and all your data is likely to get lost or inaccessible.
Note that if your application uses a custom session handler. You can lead to problems because SimpleSAMLphp's stand-alone web UI uses the default PHP session handlers. So, you need to unset the custom handler before making any calls to SimpleSAMLphp:
// use custom save handler
session_set_save_handler($handler);
session_start();
// close session and restore default handler
session_write_close();
session_set_save_handler(new SessionHandler(), true);
// use SimpleSAML\Session
$session = \SimpleSAML\Session::getSessionFromRequest();
$session->cleanup();
session_write_close();
// back to custom save handler
session_set_save_handler($handler);
session_start();
Refer Doc & SO thread for usage of session

Managing multiple PHP sessions causes script to hang under specific circumstance

Running PHP 7.2.12 on a local Apache server (XAMPP on Windows).
I'm playing around with multiple sessions in PHP to see if I can stash away an open session, play around with a new one, and retrieve the previous session. I'm about to give up and just chalk it up to some kind of file locking thing.
The code that hangs ("connection reset" in Firefox):
//first session
session_start();
$old_id = session_id();
$old_session = $_SESSION;
$id = session_create_id();
session_commit(); //same as session_write_close()
//new session
session_id($id);
session_name('new_name');
session_start();
I don't particularly need any of the code to be this way, but I'm totally lost as to why this hangs due to this:
Comment out any one of the following lines:
$old_id = session_id();
$old_session = $_SESSION;
session_name('new_name');
And it doesn't hang. You can also replace session_create_id() with an alphanumeric string literal and it won't hang. It only seems to hang when all 3 of these optional lines are present, and when using session_create_id() to create a new collision free id. Is there a way to guarantee that it won't hang?
And for anyone who has time, I have another question: What would be the proper way to stash an open session, open/manipulate/save my own session, and then restore the original session?
This works:
//previous session
session_start();
$_SESSION['var'] = 'value';
//try to stash open session
$old_id = session_id();
session_commit();
//open new session
session_id('mySession');
session_start();
//modify and save my session
$_SESSION['var'] = 'mine';
session_commit();
//restore previous session
session_id($old_id);
session_start();
echo $_SESSION['var']; //output 'value'
But I'm afraid that once I start messing with new session names in combo with session_create_id() that I'll run into the hanging problem. Maybe I should check for session id collision without the use of session_create_id()? Or should I just try to piggy-back onto the already open session?
Edit: Maybe the core of what I'm asking is that if I make a PHP class that wants to pass anonymous data to/from the client, and somebody using my class opened a PHP session prior to using my class, what's the accepted way of handling that without stepping on the previous session? Ideally I want to name my session with something unique to the class, ie. not the default 'PHPSESSID'.
You ahe handling Session wrong in first example (you call session_create_id uselessly), it probably cause to hanging. Check logs if something info was here.
Maybe problem can be exhalted when you copy $_SESSION variable to another variable and then close session. As PHP internally works it can cause to unpredictable behavion, because $_SESSION is special type of array.

SESSION variables not working after require SIMPLESAMLPHP

I'm having a problem with my session variables.
I can't set any variable after my require once.
But I need to store my data after the login.
Here is the code :
<?php include "include/header.php";
require_once('simplesamlphp/lib/_autoload.php');
$as = new \SimpleSAML\Auth\Simple('default-sp');
$as->requireAuth();
$attributes = $as->getAttributes();
$_SESSION["nivauth"] = "test";
?>
EDIT :
session_start() is in the header.php
i try to get the session var on another page with echo $_SESSION["nivauth"];
I have this error on the other page :
Notice: Undefined index: nivauth in /var/www/html/cableEdit.php on line 10
And my session var nivauth is available only on my first page.
My session_start() is working, and all my others sessions variables are created on others pages can be viewed.
If I place $_SESSION["nivauth"] = "test"; just under the include everything works, but I can't get nivauth from the authentification.
The var is created but can't be accessed on other page...
Refer to this part of the documentation
If we are using PHP sessions in SimpleSAMLphp and in the application we are protecting, SimpleSAMLphp will close any existing session when invoked for the first time, and its own session will prevail afterwards. If you want to restore your own session after calling SimpleSAMLphp, you can do so by cleaning up the session like this:
$session = SimpleSAML_Session::getSessionFromRequest();
$session->cleanup();
If you don't cleanup SimpleSAMLphp's session and try to use $_SESSION afterwards, you won't be using your own session and all your data is likely to get lost or inaccessible.
I was stuck on a similar issue with SimpleSamlPHP. After tried with various solutions, finally below workaround solved my issue.
In your header.php(or other pages), instead of session_start(); initiate SimpleSamlPHP class by adding below two lines you can restore your custom session variable along with simplesamlphp session.
require_once('simplesamlphp/lib/_autoload.php');
$as = new \SimpleSAML\Auth\Simple('default-sp');
Here is the snippet.
<?php
//header.php
//session_start();
require_once('simplesamlphp/lib/_autoload.php');
$as = new \SimpleSAML\Auth\Simple('default-sp');
echo $_SESSION["nivauth"];
cleanup() simply was not working So i did two changes in addition to $session->cleanup() to make it work
1- empty session.phpsession.cookiename in config/config.php
'session.phpsession.cookiename' => ''
2- Added session_start(); after cleanup()
$session = SimpleSAML_Session::getSessionFromRequest();
$session->cleanup();
//session_write_close();
session_start();

Access all server session variables

I thought about some helper to manage session variables on my development localhost.
I would like to read,change and delete session variables from ALL vhosts on my machine.
As far i know, from PHP i can access only current host session variables, which will be populated to $_SESSION variable, after call to session_start. That's not enough for my needs.
After some research (ex. Access active sessions in PHP) i found solution :
Load all files from php session directory
Use session_decode to load data to $_SESSION variable
Read/change/delete some variables
Use session_encode to encode my session back to file
There is any better method to do that?
Maybe there is already dedicated tool for that task?
EDIT:
Another solution which i now currenty use is just enable debugger in IDE for desired project, and use watches/stack window to edit session.
EDIT2:
I dont want any project-specific solution like storing session data in database. This should work "out-of-the-box", for any project.
For better understanding, use example:
In magento admin panel grid filters are stored in session variables.
When you enable broken filter there is an error page, and you can't easily disable this filter without removing session cookie, or setting debugger for it.
I spend some time once with a script that programatically "expires" server sessions to obtain info about user inactivity. On that occasion, I had a database with session_ids to transverse, but it can be done with directory listing (note that are php's compilation specific advices on code)
//Preserve runtime variable
$pre_config = ini_get('session.use_cookies');
//Check previous session_start();
if($previous_sid = session_id()){
//close and save current session
session_write_close();
}
//To determine where php session files are stored, see http://stackoverflow.com/questions/4927850/location-for-session-files-in-apache-php
if(($save_path = session_save_path()) === ''){
// PHP compilation specific
// There are diferences between CLI (saves in sys_get_temp_dir()) and mod_php (where session_save_path() works) on Fedora 12
$save_path = '/var/lib/php/session/';
session_save_path('/var/lib/php/session/');
}
//Avoid new cookies from other session_start()
ini_set('session.use_cookies', false);
//Do the magic
if ($handle = opendir($save_path)) {
while (false !== ($entry = readdir($handle))) {
if (strpos($entry, 'sess_') === 0) {
$session_id = str_replace('sess_' , '', $entry);
session_id($session_id);
session_start();
//Do whatever you want with this session, using $_SESSION
session_write_close();
}
}
closedir($handle);
}
//Restore previous configuration
ini_set('session.use_cookies', $pre_config);
//Restore previous session
if($previous_sid) {
session_id($previous_sid);
session_start();
}
I do not recommend running this code on client request. Remember that session_start block script execution while "session id" is in use on another request. And I think that is not recommended to run it by a CLI script, because PHP embedded on WebServers and PHP CLI uses different environment and configurations (besides the fact that the running user of a PHP CLI must be the same user that runs the WebServer to prevent permission deny).
I think that the ideal solution is to trigger requests to this script with a HTTP GET periodically (by linux crontab or similar), of course this solution depends on final use been planned. If HTTP request trigger can be done, the part of the code that saves previous settings and session can be eliminated.

What if PHP sessions are already started?

I'm making somewhat of a "module" that gets included into another unrelated PHP application. In my "module" I need to use sessions. However, I get the 'session has already been started...' exception. The application that my "module" is included into is starting the session. If I cannot disable sessions in this application, what are my options? I'd like to use Zend_Session, but it seems upon first glance that it is not possible. However, maybe there is another way? Any ideas?
Thanks!
With PHP’s session implementation, there can only be one session at a time. You can use session_id to check if there currently is a session:
if (session_id() === '') {
// no current session
}
Now if there is already an active session, you could end it with session_write_close, change the session ID’s name with session_name to avoid conflicts, start your session, and restore the old session when done:
$oldName = session_name();
if (session_id() !== '') {
session_write_close();
}
session_name('APPSID');
session_start();
// your session stuff …
session_write_close();
session_name($oldName);
session_start();
The only problem with this is that PHP’s session implementation does only send the session ID of the last started session back to the client. So you would need to set the transparent session ID (try output_add_rewrite_var) and/or session cookie (see setcookie) on your own.
Try setting a custom "name" parameter for your application.
The default is PHPSESSID. You can change it to PHPSESSID_MYAPP to avoid conflicts with the other app.
Add the following code before you want to use the Session feature:
#session_start();

Categories