166

How do I resolve the problem of losing a session after a redirect in PHP?

Recently, I encountered a very common problem of losing session after redirect. And after searching through this website I can still find no solution (although this came the closest).

Update

I have found the answer and I thought I'd post it here to help anyone experiencing the same problem.

Community
  • 1
  • 1
dayuloli
  • 16,205
  • 16
  • 71
  • 126
  • 2
    The question is how to resolve the problem of losing a session after a redirect in PHP. I figured out the answer already, just posting it here to let other people know. Because my solution isn't on StackOverflow. – dayuloli Jun 21 '13 at 18:53
  • 2
    That's fine, but this is a QA site. Please make your question a question. – jeremy Jun 21 '13 at 18:54
  • I didn't notice it was from you. Still, this site is for questions, not for answers to questions you already know. – Aris Jun 21 '13 at 18:59
  • 1
    @Aris: http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/ – Dave Chen Jun 21 '13 at 19:01
  • 29
    @Aris That's not true, when people have a question on coding, they come to StackOverflow for help. If there are no answers available, then they can't get the help they need. I am trying to provide that answer. – dayuloli Jun 21 '13 at 19:02
  • Yes, I should format the question in the form of a question, and have now done so. – dayuloli Jun 21 '13 at 19:03
  • since its in the book, my bad :) – Aris Jun 21 '13 at 19:04
  • did this error only occur on your server or other servers as well out of interest. also a important question can you choose your own answer? – amigura Jun 21 '13 at 19:04
  • As stated, this is the case on FatCow and iPage, and maybe other servers as well. And yes. – dayuloli Jun 21 '13 at 19:08
  • Similar: http://stackoverflow.com/questions/22079477/cakephp-session-is-lost-after-an-oauth-redirect – trante Feb 27 '14 at 22:15
  • I have same issue with yours when i redirect as a domain name instead of ip address which is already using for HTTP request. The inconsistency probably is the reason. – Chenhai-胡晨海 Mar 24 '17 at 19:17

39 Answers39

249

First, carry out these usual checks:

  1. Make sure session_start(); is called before any sessions are being called. So a safe bet would be to put it at the beginning of your page, immediately after the opening <?php declaration before anything else. Also ensure there are no whitespaces/tabs before the opening <?php declaration.
  2. After the header redirect, end the current script using exit(); (Others have also suggested session_write_close(); and session_regenerate_id(true), you can try those as well, but I'd use exit();)
  3. Make sure cookies are enabled in the browser you are using to test it on.
  4. Ensure register_globals is off, you can check this on the php.ini file and also using phpinfo(). Refer to this as to how to turn it off.
  5. Make sure you didn't delete or empty the session
  6. Make sure the key in your $_SESSION superglobal array is not overwritten anywhere
  7. Make sure you redirect to the same domain. So redirecting from a www.yourdomain.com to yourdomain.com doesn't carry the session forward.
  8. Make sure your file extension is .php (it happens!)

Now, these are the most common mistakes, but if they didn't do the trick, the problem is most likely to do with your hosting company. If everything works on localhost but not on your remote/testing server, then this is most likely the culprit. So check the knowledge base of your hosting provider (also try their forums etc). For companies like FatCow and iPage, they require you to specify session_save_path. So like this:

session_save_path('"your home directory path"/cgi-bin/tmp');
session_start();

(replace "your home directory path" with your actual home directory path. This is usually within your control panel (or equivalent), but you can also create a test.php file on your root directory and type:

<?php echo $_SERVER['SCRIPT_FILENAME']; ?>

The bit before 'test.php' is your home directory path. And of course, make sure that the folder actually exists within your root directory. (Some programs do not upload empty folders when synchronizing)

John
  • 1
  • 13
  • 98
  • 177
dayuloli
  • 16,205
  • 16
  • 71
  • 126
  • 10
    Very well written +1, if all fails, just use cookies (randomly generate a string and store it in the db and use that as your cookie value). – Dave Chen Jun 21 '13 at 19:03
  • 2
    switching between http andn https might be also be an issue http://stackoverflow.com/questions/441496/session-lost-when-switching-from-http-to-https-in-php – dev.e.loper Jan 30 '14 at 17:12
  • 4
    Note that as of php 5.4.0 register_globals has been removed, so it will no longer cause a problem – anthonygore Mar 23 '14 at 05:16
  • 2
    Check the webserver error log too; in my case, there was an error "Failed to write session data (files). Please verify that the current setting of session.save_path is correct". The permissions were wrong on the save_path directory. – timbonicus May 03 '14 at 04:21
  • Any reason why my sessions would be stored somewhere other than in session.save_path? – Justin Jun 23 '15 at 20:39
  • My sessions between pages weren't not working in a subdomain. This is now working with: $some_name = session_name("some_name"); session_set_cookie_params(0, '/', $_SERVER['HTTP_HOST']); – Guillaume Renoult Aug 04 '15 at 02:25
  • I am using the exact same code from another site, running on the same server. Login redirects to Home.php.. which loads an inner shell... which loads header then the content. I record the value of the session variable I am tracking at the top of each of the 4 php scripts immediately after... if ( !isset( $_SESSION ) ) session_start() ; Which is the first line of all of my php scripts. So when the Login redirects me to Home... the variable is set properly. – IT Serenity Aug 19 '15 at 02:33
  • But when I click on a Menu link to take me to another page, that does the very same thing as Home and Login, the variable is undefined. I have done a find in files and there is only one place this one variable is set. Everywhere else it is simply evaluated. Two days now and no joy. No errors in php, javascript or on the server. – IT Serenity Aug 19 '15 at 02:38
  • Make sure you redirect to the same domain. So redirecting from a www.yourdomain.com to yourdomain.com doesn't carry the session forward. => This solved my problem. Thank you very much. – Gaurang Jun 27 '16 at 06:45
  • Can it be a problem when I register to subfolder but in the same domain? – arrowman Oct 21 '16 at 08:40
  • 1
    Make sure you redirect to the same domain. So redirecting from a `www.yourdomain.com` to `yourdomain.com` doesn't carry the session forward. ☚ Solved my problem – TheTechGuy Nov 28 '17 at 08:20
  • www subdomain was missing in my link. bam! thank you. – omikes Jan 08 '18 at 20:21
  • So, which of these _solutions_ solved your particular problem? – Phil Jan 30 '18 at 05:55
  • The `session_save_path('"your home directory path"/cgi-bin/tmp');` one :p – dayuloli Jan 30 '18 at 11:13
  • Point 2 above about using exit() after a header redirect proved an invaluable point on one site I've had this problem on. However, in my case I still need to additionally run session_write_close() at the top of my global include file just before my session_start() statement. Enabling session.auto_save breaks my sessions because I seem to need to have the session_write_save() function called first - not quite sure why. – Tony Barganski Mar 25 '18 at 15:29
  • Okay, found out why session_write_save() is also needed. Its because any changes to $_SESSION varibles are made when a script ends. A header redirect with exit() is essentially interupting the scripts execution - so the session needs to be written back to disk/db/redis 'before' the redirect and exit! In my case, redirects are internal to my application's domain and I use a global include script so its okay on my app to include the session_write_close statement at the very start of my include file instead of after very redirect - less typing. – Tony Barganski Mar 25 '18 at 15:48
  • I couldn't risk moving around session_start() (spaghetti legacy codebase), so I "solved" it by putting an ob_start() at the start of the bootstrap file - I can never thank you enough, great answer. – Hissvard Dec 22 '18 at 09:26
  • Thanks for posting this. Adding the missing 'exit()' after a location redirect sorted this problem for me. – funnyfish Sep 09 '21 at 11:43
29

you should use "exit" after header-call

header('Location: http://www.example.com/?blabla=blubb');
exit;
Cesar Bielich
  • 4,754
  • 9
  • 39
  • 81
KraftART Berlin
  • 339
  • 4
  • 3
  • There is a bug for Gecko (e.g. Waterfox, Firefox, SeaMonkey) where if there is any data output (e.g. `echo ' ';`) or whitespace of any kind it will completely ignore the location header. – John Mar 26 '20 at 06:13
  • I did not know that not having the exit()would cause so much trouble, but it does. It seems to prevent the session from being saved. – Ncoder Apr 03 '23 at 11:59
24

I tried all possible solutions, but none worked for me! Of course, I am using a shared hosting service.

In the end, I got around the problem by using 'relative url' inside the redirecting header !

header("location: http://example.com/index.php")

nullified the session cookies

header("location: index.php")

worked like a charm !

ali al-juanidi
  • 241
  • 2
  • 2
13

I had the same problem. I worked on it for several hours and it drove me crazy.

In my case the problem was a 404 called due to a missing favicon.ico in Chrome and Firefox only. The other navigators worked fine.

Jeremie
  • 196
  • 1
  • 11
  • Just wanted to thank you for this answer, made me realise that 404 requests for images were being forwarded by Varnish to PHP without any cookies and thus new sessions were being created constantly. May never have figured it out without you. – Pascal Zajac Jun 01 '17 at 12:55
  • 1
    I had the same issue, my favicon.ico was being redirect (302 redirect from subdomain to main domain) and thus, generated a new session every time. Thanks a lot! – simdrouin Jun 19 '18 at 02:03
8

I was having the same problem. All of a sudden SOME of my session variables would not persist to the next page. Problem turned out to be ( in php7.1) you header location must not have WWW in it, ex https://mysite. is ok, https://www.mysite. will lose that pages session variables. Not all, just that page.

Wynn
  • 183
  • 1
  • 2
  • That's because `www.mysite.com` is seen as a completely different domain than `blog.mysite.com` or simply `mysite.com` – dayuloli Feb 25 '17 at 13:45
  • Thank you. This answer saved me. I've been banging my head on this problem for two hours! – Dante Oct 18 '21 at 05:01
5

When i use relative path "dir/file.php" with in the header() function in works for me. I think that the session is not saved for some reason when you redirect using the full url...

//Does retain the session info for some reason
header("Location: dir");

//Does not retain the session for some reason
header("Location: https://mywebz.com/dir")
user2999967
  • 51
  • 1
  • 1
4

I had a similar problem, although my context was slightly different. I had a local development setup on a machine whose hostname was windows and IP address was 192.168.56.2.

I could access the system using either of:

After logging in, my PHP code would redirect using:

header('http://windows/');

If the previous domain name used to access the system was not windows, the session data would be lost. I solved this by changing the code to:

header('http://'.$_SERVER['HTTP_HOST'].'/');

It now works regardless of what local domain name or IP address the user puts in.

I hope this may be useful to someone.

3

I ran into this issue on one particular page. I was setting $_SESSION values in other pages right before redirecting and everything was working fine. But this particular page was not working.

Finally I realized that in this particular page, I was destroying the session at the beginning of the page but never starting it again. So my destroy function changed from:

function sessionKill(){

    session_destroy();

}

to:

function sessionKill(){

    session_destroy();
    session_start();

}

And everything worked!

NicB
  • 342
  • 2
  • 3
3

I've been struggling with this for days, checking/trying all the solutions, but my problem was I didn't call session_start(); again after the redirect. I just assumed the session was 'still alive'.

So don't forget that!

Jeffrey Roosendaal
  • 6,872
  • 8
  • 37
  • 55
  • Yes! this was my problem also. I thought starting a PHP session was like turning on a light for the whole house. I didn't realize you have to turn the switch for each room that you enter. – Dale Thompson Jun 07 '20 at 00:46
2

This stumped me for a long time (and this post was great to find!) but for anyone else who still can't get sessions between page redirects to work...I had to go into the php.ini file and turn cookies on:

session.use_cookies = 1 

I thought sessions worked without cookies...in fact I know they SHOULD...but this fixed my problem at least until I can understand what may be going on in the bigger picture.

sclarky
  • 721
  • 5
  • 11
  • I didn't know sessions can work without cookies! Learn something new everyday! http://www.programmerinterview.com/index.php/php-questions/can-sessions-work-without-cookies/ – dayuloli May 10 '14 at 04:19
  • of course they CAN work without cookies depends on your configuration. But you should know what you do. And have a good reason for doing so. Because it's less secure. and in case you have to work for what ever reason without cookies. You should at least configure ini_set('session.use_strict_mode', '1'); and generally have a short session time and after the user login use session_regenerate_id(). But be warned if some user post a link to a site on your server in a forum the folks who actually click on this link will take over the session. Maybe checking the ip is also a good idea. – Michael Jul 26 '16 at 19:06
2

Nothing worked for me but I found what caused the problem (and solved it):

Check your browser cookies and make sure that there are no php session cookies on different subdomains (like one for "www.website.com" and one for "website.com").

This was caused by a javascript that incorrectly used the subdomain to set cookies and to open pages in iframes.

Julius S.
  • 664
  • 9
  • 21
  • And also check that there are not multiple cookies on different folders - this is what the problem was for me. This can happen if you are manually setting the session cookie, as I was doing to set SameSite for the session cookie using the solution given here: https://stackoverflow.com/a/60341320/649497. Once I added path=/ into the Set-Cookie, the problem of multiple cookies was resolved. – BruceHill Apr 22 '21 at 07:44
2

KEY POINT'S

  1. Do not start a session on the return page.
  2. Don't use session variable and not include header.php which user session variable
  3. Just make a link go to home page or profile page after insert payment info and status
1

I had the same problem and found the easiest way. I simply redirected to a redirect .html with 1 line of JS

<!DOCTYPE html>
<html>
<script type="text/javascript">
<!--
window.location = "admin_index.php";
//–>
</script>
</html>

instead of PHP

header_remove();
header('Location: admin_login.php');
die;

I hope this helps.

Love Gram

Gramrock
  • 49
  • 7
1

Just for the record... I had this problem and after a few hours of trying everything the problem was that the disk was full, and php sessions could not be written into the tmp directory... so if you have this problem check that too...

iperich
  • 29
  • 5
  • This answer worked for me. We run an Amazon Machine Image with nginx. There seems to be a fault that the session folder isn't owned by the correct user (in our case `www`) so performing `chown -R www.www` on the sessions folder fixes the problem. – Joshua Jan 07 '16 at 00:51
1

If you are using session_set_cookie_params() you might want to check if you are passing the fourth param $secure as true. If you are, then you need to access the url using https.

The $secure param being true means the Session is only available within a secure request. This might affect you locally more than in stage or production environments.

Mentioning it because I just spent most of today trying to find this issue, and this is what solved it for me. I was just added to this project and no one mentioned that it required https.

So you can either use https locally, or you can set the $secure param to FALSE and then use http locally. Just be sure to set it back to true when you push your changes up.

Depending on your local server, you might have to edit DocumentRoot in the httpd-ssl.conf of the server so that your local url is served https.

1

Another possible reason:

That is my server storage space. My server disk space become full. So, I have removed few files and folders in my server and tried.

It was worked!!!

I am saving my session in AWS Dynamo DB, but it still expects some space in my server to process the session. Not sure why!!!

Jayaprakash
  • 1,407
  • 1
  • 9
  • 19
1

Make sure session_write_close is not called between session_start() and when you set your session.

session_start();

[...]

session_write_close();

[...]

$_SESSION['name']='Bob'; //<-- won't save
dayuloli
  • 16,205
  • 16
  • 71
  • 126
Jordan Daigle
  • 424
  • 4
  • 12
1
ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
session_start();

Too late to reply but this worked for me

Vipertecpro
  • 3,056
  • 2
  • 24
  • 43
  • 1
    This fixed my problem. Altogether ended up with this : `ini_set('session.cookie_samesite', 'Strict'); ini_set('session.cookie_secure', 1); ini_set('session.use_strict_mode', 1); ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));` – Bim May 17 '21 at 16:34
1

To me this was permission error and this resolved it:

chown -R nginx:nginx /var/opt/remi/php73/lib/php/session

I have tested a few hours on PHP and the last test I did was that I created two files session1.php and session2.php.

session1.php:

session_start();

$_SESSION["user"] = 123;

header("Location: session2.php");

session2.php:

session_start();

print_r($_SESSION);

and it was printing an empty array.

At this point, I thought it could be a server issue and in fact, it was.

Hope this helps someone.

temo
  • 612
  • 1
  • 9
  • 25
  • 1
    The chown is a BAD solution, as it will be changed back to default value on package update. See comments in default pool configuration (www.conf). Proper way if the use another directory than the apache one (ex: /var/lib/php/nginx/session) – Remi Collet Apr 08 '19 at 12:47
  • You are right. package update was the reason for my problem in the first place. But since that is the way it was done and I needed some quick solution this helped. My SYS admin resolved it, I'm not near good with Linux. – temo Apr 08 '19 at 13:23
1

Verify that your session is not Strict. If it is, when you come back, like coming back from Stripe, it regenerate the session.

Use This:

ini_set('session.cookie_samesite', 'Lax');

  • I had this same problem. I had to set it to None and Secure to On in my ini file. – Whip Apr 07 '22 at 09:03
  • You can still use samesite Strict. Instead of redirecting with PHP, redirect using Javascript: `` (do not start session on return page) – François J. May 09 '22 at 16:22
0

I also had the same issue with the redirect not working and tried all the solutions I could find, my header redirect was being used in a form.

I solved it by putting the header redirect in a different php page 'signin_action.php' and passing the variables parameters through I wanted in url parameters and then reassigning them in the 'signin_action.php' form.

signin.php

if($stmt->num_rows>0) {
$_SESSION['username'] = $_POST['username'];
echo '<script>window.location.href = "http://'.$root.'/includes/functions/signin_action.php?username='.$_SESSION['username'].'";</script>';
error_reporting(E_ALL);

signin_action.php

<?php
require('../../config/init.php');
$_SESSION['username'] = $_GET['username'];
if ($_SESSION['username']) {

echo '<script>window.location.href = "http://'.$root.'/user/index.php";</script>';
exit();
} else {
echo 'Session not set';
}

?>

It is not a beautiful work-around but it worked.

Stacker-flow
  • 1,251
  • 3
  • 19
  • 39
0

For me the error was that I tried to save an unserialisable object in the session so that an exception was thrown while trying to write the session. But since all my error handling code had already ceased any operation I never saw the error.

I could find it in the Apache error logs, though.

Björn Tantau
  • 1,564
  • 14
  • 13
0

For me, Firefox has stored session id (PHPSESSID) in a cookie, but Google Chrome has used GET or POST parameter. So you only have to ensure that the returning script (for me: paypal checkout) commit PHPSESSID in url or POST parameter.

almisoft
  • 2,153
  • 2
  • 25
  • 33
0

After trying many solutions here on SO and other blogs... what worked for me was adding .htaccess to my website root.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursitename.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursitename\.com" [R=301,L]
Vishal Kumar
  • 4,419
  • 1
  • 25
  • 31
0

If you're using Wordpress, I had to add this hook and start the session on init:

function register_my_session() {
    if (!session_id()) {
        session_start();
    }
}
add_action('init', 'register_my_session');
Jack
  • 3,271
  • 11
  • 48
  • 57
0

First of all, make sure you are calling session_start() before using $_SESSION variable.

If you have disabled error reporting, try to turn in on and see the result.

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

The most common reasons that aren't mentioned in @dayuloli's answer:

  1. Disk space problem. Make sure your disk space is not full, you need some space to store session files.

  2. Session directory may not be writable. You can check it with is_writable(session_save_path())

loler
  • 2,594
  • 1
  • 20
  • 30
0

I was having the same problem and I went nuts searching in my code for the answer. Finally I found my hosting recently updated the PHP version on my server and didn't correctly set up the session_save_path parameter on the php.ini file.

So, if someone reads this, please check php.ini config before anything else.

ata
  • 3,398
  • 5
  • 20
  • 31
0

If you are using Laravel and you experience this issue, what you need is to save your session data before redirecting.

session()->save();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;
0

Now that GDPR is a thing, people visiting this question probably use a cookie script. Well, that script caused the problem for me. Apparently, PHP uses a cookie called PHPSESSID to track the session. If that script deletes it, you lose your data.

I used this cookie script. It has an option to enable "essential" cookies. I added PHPSESSID to the list, the script stopped deleting the cookie, and everything started to work again.

You could probably enable some PHP setting to avoid using PHPSESSID, but if your cookie script is the cause of the problem, why not fix that.

dodov
  • 5,206
  • 3
  • 34
  • 65
0

I fixed this problem after many days of debugging and it was all because my return URL coming from PayPal Express Checkout didn't have a 'www'. Chrome recognized that the domains should be treated the same but other browsers sometimes didn't. When using sessions/cookies and absolute paths, don't forget the 'www'!

miapuffia
  • 31
  • 4
0

I fixed by giving group write permissions to the path where PHP store session files. You can find session path with session_save_path() function.

Francesco Gasparetto
  • 1,819
  • 16
  • 20
0

Today I had this problem in a project and I had to change this parameter to false (or remove the lines, by default is disabled):

ini_set( 'session.cookie_secure', 1 );

This happened because the actual project works over http and not https only. Found more info in the docs http://php.net/manual/en/session.security.ini.php

Oscar
  • 1
0

Quick and working solution for me, was just simply double redirect. I created 2 files: fb-go.php and fb-redirect.php

Where fb-go.php looked like:

session_start();

$_SESSION['FBRLH_state'] = 'some_unique_string_for_each_call';

header('Location: fb-redirect.php');

and fb-redirect:

session_start();

header('Location: FULL_facebook_url_with_' . $_SESSION['FBRLH_state'] . '_value');

Also worth to mention is Android Chrome browser behavior. Where user can see something like that:

Android

If user will chose Facebook app, then session is lost, because of opening in Facebook browser - not Chrome, which is storing user session data.

instead
  • 3,101
  • 2
  • 26
  • 35
0

OP didn't specify if he's redirecting to the same page (for example after login) if so server/browser caching could also be the problem

A simple workaround would be to append version number at the end of the URL (like you would when forcing .CSS file refresh)

Example:

header('Location: index.php?v='.time());

So the user is redirected to which is treated like a new page

domain.com/index.php?v=122234982323
Robert Sinclair
  • 4,550
  • 2
  • 44
  • 46
0

Here's my 2 cents on this problem as I don't see anyone mentioned this case..

If your application is functioning thru a load balancer on a multiple nodes you can't save session into files or need to share this path for all nodes otherwise each node will have its own session files and you will run into inconsistency.

So I'm refactoring my app to use database instead of file system.

Seva Kalashnikov
  • 4,262
  • 2
  • 21
  • 36
0

My problem was slightly different than the others.

I am trying to implement Google oAuth on my website.

My website's dev url is website.local, the Google redirecting url was 127.0.0.1.

As they're not the same domain, two different session_ids were created.

Alexandre Elshobokshy
  • 10,720
  • 6
  • 27
  • 57
0

Sometimes the issue involves the PHP INI session settings such as session.cookie_samesite not being set, or not being set to match your use case. Most cookie/session/security related errors appear in the developer console/network log of web browsers (F12 key in Windows), but keep in mind that each web browser handles things differently.

I had a site that kept dropping the user session in Microsoft Edge browser but not Firefox. The network log in Edge said my session SameSite setting was not set, which I didn't think was a problem until I added ini_set("session.cookie_samesite", "None"); to my application. Making that change fixed my issue of Edge dropping my user session. So if your session issues appear in one browser vs another, check the browser network logs for differences in security errors.

w. Patrick Gale
  • 1,643
  • 13
  • 22
-2
session_start();
error_reporting(E_ALL ^ (E_NOTICE | E_WARNING));
if(!isset($_SESSION['name_session'])){
    unset($_SESSION['name_session']);
    session_destroy();
    }   
if(isset($_SESSION['name_session'])){
    $username = $_SESSION['name_session'];
    }
Hellos
  • 1
  • 4
    Provide some explanation on what OP has done wrong so he can actually learn from it instead of just copying the code. – Granny Mar 26 '18 at 12:07
-5

Make sure a new session is created properly by first destroying the old session.

session_start();
session_unset();   // remove all session variables  
session_destroy(); // destroy the session
session_start();

$_SESSION['username'] = 'username';

Yes, session_start() is called twice. Once to call the unset and destroy commands and a second time to start a fresh session.

J.Do
  • 303
  • 6
  • 26
Joshua Ginn
  • 109
  • 2
  • 11