benedmunds / CodeIgniter-Ion-Auth

Simple and Lightweight Auth System for CodeIgniter
http://benedmunds.com/ion_auth/
MIT License
2.34k stars 1.14k forks source link

auth.php logout not getting run when browser goes to auth/logout #398

Closed emilebourquin closed 11 years ago

emilebourquin commented 11 years ago

This problem occurs when using Chrome and Firefox (didn't test other browsers), whether the server is a local CentOS server, or on an Amazon EC2 server behind a load balancer;

The logout function in auth.php is (usually) not being run when a user clicks on the logout link that goes to auth/logout.

This is not one of those "I hit the Back button and can still see data" problems; I can see the session is still logged in, in the database, and the $this->ion_auth->is_admin() call is returning TRUE, because the logout function never runs.

What I believe is happening is that since the logout function returns no headers (I have no-cache, date-in-the-past expire headers, etc., on all other pages), the browser only sees the redirect to login, and caches that action, thus never running the sess_destroy stuff in logout.

Any idea what the proper fix might be? Possibly loading a real view, with no-cache headers for logout?

emilebourquin commented 11 years ago

I believe I have come up with a solution. In controllers/auth.php, I commented out the redirect to auth/login, and instead load a logout view. The logout view then sets no-cache, past-expire-date, and then redirects to /auth/login:

auth.php/logout:

... //redirect('auth/login', 'refresh'); $this->load->view('/auth/logout'); }

views/auth/logout.php

<?php header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Wed, 4 Jul 2012 05:00:00 GMT"); // Date in the past redirect('/auth/login'); ?>

benedmunds commented 11 years ago

That's really weird since I've never seen this and haven't heard of anyone seeing it. Maybe some kind of server config difference...

Great job figuring out a fix though!

emilebourquin commented 11 years ago

Yeah, very odd, that the browser doesn't even try to visit auth/logout, it just goes straight to auth/login .

For future reference, here's the output from Live HTTP Headers in Firefox 18.0.1:

https://www.DOMAIN.net/auth/login

GET /auth/login HTTP/1.1 Host: www.DOMAIN.net User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0 AlexaToolbar/alxf-2.17 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Cookie: my_session=ATMHOVwwXjBUf1QoATkAOAU%2FBD4FJVByVGdfJFEiBTlbMV ... Connection: keep-alive

HTTP/1.1 200 OK Date: Fri, 25 Jan 2013 19:52:43 GMT Server: Apache X-Powered-By: PHP/5.3.3 Cache-Control: no-store, no-cache, must-revalidate, no-transform, max-age=0, post-check=0, pre-check=0 Expires: Wed, 4 Jul 2012 05:00:00 GMT Pragma: no-cache Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 1626 Connection: close Content-Type: text/html; charset=UTF-8

emilebourquin commented 11 years ago

I only came across this issue because I load a header menu bar in every view, that has calls to $this->ion_auth->is_admin() in it. Is it possible that no one has come across it because auth/login, in its default form, doesn't make that call? Can you test the theory by placing a call to $this->ion_auth->is_admin() in the login view, such as: <?php if($this->ion_auth->is_admin()): ?>Admin logged in<?php endif; ?>

benedmunds commented 11 years ago

I just did this test locally and it works fine for me :/

Weird shit...

emilebourquin commented 11 years ago

Thanks for testing, Ben, I appreciate you taking the time to try it.

I think I have a bit more insight into the issue. It may be a server configuration issue, in that, since logout doesn't send any headers of its own, the cache time of that page is up to the defaults of the webserver. Using Live HTTP headers, I can see that on a good logout, these are two of the sent headers:

... Cache-Control: max-age=300 Expires: Sat, 26 Jan 2013 15:26:14 GMT ...

If I log in, then back out again, before the cache expire time (5 minutes, in this case), I get the "bad" logout, where the browser just goes straight to auth/login , without visiting auth/logout first. Once the cache expires, 5 minutes later, logout does the proper thing, going first to logout, then login. But then, I'm stuck for another 5 minutes.

The test, then , is to log in, log out, log in again, then log out one more time, within the cache expiration time. If the server is sending no-cache headers by default, the problem will not show up. However, if it has a cache time, the problem will arise. The solution would be to either set no-cache for all pages at the webserver level, or to have logout load an actual view, which can then send no-cache headers itself.

benedmunds commented 11 years ago

Very good work troubleshooting this down to the details... Couldn't you send the appropriate headers with PHP/CI in the controller without the need for an actual view?

emilebourquin commented 11 years ago

You are correct, and that is a great idea. For some reason I was thinking I'd get some sort of "Headers already sent" error if I tried to send no-cache headers in the controller, then the redirect, but that is exactly what the view is doing.

So now, the auth/logout function ends with:

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Wed, 4 Jul 2012 05:00:00 GMT"); // Date in the past redirect('auth/login', 'refresh');

Thanks for your help on this, and for all your hard work on Ion Auth 2. It has saved me a great deal of time and effort.

benedmunds commented 11 years ago

Thanks dude! I'll make sure to link people to this if anyone has this issue in the future.

umefarooq commented 11 years ago

yes i was facing the same problem thanks this solution work really great you have to check why browser cache is not getting clear when you hit logout and i was facing another problem when session expire on any link if you logged in back and try to access the same link it was always redirecting to login page

daparky commented 11 years ago

I'm using Phil Sturgeons template library (https://github.com/philsturgeon/codeigniter-template) and it has those cache headers in place when outputting a view:-

    $this->_ci->output->set_header('Expires: Sat, 01 Jan 2000 00:00:01 GMT');
    $this->_ci->output->set_header('Cache-Control: no-store, no-cache, must-revalidate');
    $this->_ci->output->set_header('Cache-Control: post-check=0, pre-check=0, max-age=0');
    $this->_ci->output->set_header('Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
    $this->_ci->output->set_header('Pragma: no-cache');
emilebourquin commented 11 years ago

That was the original problem, that auth/logout doesn't output anything. It does some internal stuff (session destruction, etc.) and then redirects to auth/login. Without any in-the-past/no-cache headers, my browser was bypassing auth/logout and going directly to auth/login.

umefarooq commented 11 years ago

i was using tank auth for my project in my last two projects i start using ion auth because most of CI community using it. i have test tank auth also there is no such a problem it always to auth/logout method killing sessions and redirecting to login page and destroying browser cache also

ajit-mohite commented 11 years ago

Hello, I am using flexi auth library and i am facing same problem, and your solution is working fine on local it's a windows machine and live server it's still not working.. i am getting stuck please let me know ASAP,

Thanks in advance.

benedmunds commented 11 years ago

If it works locally but not on the server just compare the differences in your setup. Start by inspecting the heads and see whats different between the two.

michaelrtm commented 11 years ago

Have you checked config/config.php - i had my local config on my server by accident the other, sessions were being stored for the wrong domain

ajit-mohite commented 11 years ago

Thanks @michaelrtm, i have checked config.php and already have added proper server URL and there no more dependency in URl..

ajit-mohite commented 11 years ago

Thanks @benedmunds for your reply, i had made 2 times installation for same but nothing got result positive, let me explain once again, I have installed flexi auth module on my local machine and it’s working fine, but on live server only logout is not working. Whenever i clicked on logout link i am redirecting to auth_admin/dashboard page, also i have print session after logout and it's empty. Before function logout() { // By setting the logout functions argument as 'TRUE', all browser sessions are logged out. $this->flexi_auth->logout(TRUE); // Set a message to the CI flashdata so that it is available after the page redirect. $this->session->set_flashdata('message', $this->flexi_auth->get_messages()); redirect('auth'); }

Now : Here i have replaced redirect to header, then it's going login page but when i click back button of browser it's showing past opened pages also i can able to open past link using by address bar. function logout() { // By setting the logout functions argument as 'TRUE', all browser sessions are logged out. $this->flexi_auth->logout(TRUE); header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Expires: Wed, 4 Jul 2012 05:00:00 GMT"); // Date in the past // Set a message to the CI flashdata so that it is available after the page redirect. $this->session->set_flashdata('message', $this->flexi_auth->get_messages()); header('Location:http://www.mydomain.com/auth/'); }

benedmunds commented 11 years ago

Ok good, thanks!

odikonoto commented 10 years ago

Dear,

I have the same problem, how to fix it?

ghost commented 10 years ago

i use ionauth on 3 sites it work fine , but now i am using it again and getting this problem ,user get log out , their is no more session but when user click the back button pages loaded and show the session again, i use the above mention solution but it didn't work for me

ghost commented 10 years ago

fixed it the issue was same as described above the browser chache the page and show it, after putting $this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate, no-transform, max-age=0, post-check=0, pre-check=0"); $this->output->set_header("Pragma: no-cache"); in controller it work fine.

odikonoto commented 10 years ago

@waseemmachloy, the part where the change was made?

ghost commented 10 years ago

i am using two separate controller for admin and user side like

class Admin_Controller extends MY_Controller class User_Controller extends MY_Controller

(My_Controller further extend to CI_Controller)

so i put the following code in above 2 classes constructors. i use this way bcz my site is small , and i have few hour to deliver it. but first you must try the solution provided by emilebourquin( second comment in this page) .

odikonoto commented 10 years ago

Yeah, it is working properly. but, when I first login, then logout and then log back on, logging out can not be done. This happens in all browsers (ie, ff, opera) except chrome (in chrome, runs well). what the cause?

umefarooq commented 10 years ago

this is really serious problem this library has, i was showing my project to client and it was logging off when i try to login, you guys can understand feeling in front of client

ghost commented 10 years ago

i dont think there is some issue in code ,bcz i use same lib 3 times. i suspect i do some thing wrong somewhere, may be you also.

benedmunds commented 10 years ago

Make sure you are setting the cache kc troll headers in your constructor.

odikonoto commented 10 years ago

Now the issue is resolved.

cause this :

$this->output->set_header("Cache-Control: no-store, no-cache, must-revalidate, no-transform, max-age=0, post-check=0, pre-check=0"); $this->output->set_header("Pragma: no-cache");

enough to provide a solution to the problem the following code inside each function controllers that load page:

header("Cache-Control: no-cache, must-revalidate");

ghost commented 10 years ago

@benedmunds is it good practice to use header("Cache-Control: no-cache, must-revalidate"); i think it will give performance issue if we didn't Cache any pages

benedmunds commented 10 years ago

It just depends on your needs. I use it if I have a site (usually in dev) that is changing often so caching doesnt cause an old version to appear. On most sites though I do use caching.

In practice having the ability to hit Back and see the last page you were on is not a real issue, it is just perceived that way. If you saw the page once you can see it again, but if you try to do anything on that page you will then be locked out as long as you are checking that the user is logged in before performing any actions.

ghost commented 10 years ago

yes i see noticed that , you can see the back page but as you try some action on that page you get redirected. thanks for your time :)

wasconet commented 10 years ago

I am still having a problem with is issue, i have a header that displays username, login/logout depending on if logged_in()... i noticed if i login with admin and then logout, then login with another user the username on the header will still be admin after redirected to base_url() when successfully logged in, untill i do a refresh on the browser then the username will change.

any fix? thanks

benedmunds commented 10 years ago

Are you using no cache headers on this page?

-Ben Edmunds

On Jan 20, 2014, at 6:51 PM, wasconet notifications@github.com wrote:

I am still having a problem with is issue, i have a header that displays username, login/logout depending on if logged_in()... i noticed if i login with admin and then logout, then login with another user the username on the header will still be admin after redirected to base_url() when successfully logged in, untill i do a refresh on the browser then the username will change.

any fix? thanks

— Reply to this email directly or view it on GitHubhttps://github.com/benedmunds/CodeIgniter-Ion-Auth/issues/398#issuecomment-32817082 .

ajit-mohite commented 10 years ago

Hi All,

I have made following changes and this issue is resolved my end

Step 1 : Open system/helpers/url_helper.php Step 2 : Find function redirect and replace it with this if ( ! function_exists('redirect')) { function redirect($uri = '', $method = 'location', $http_response_code = 302) { if ( ! preg_match('#^https?://#i', $uri)) { $uri = site_url($uri); }

    header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
    header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
    header( 'Cache-Control: no-store, no-cache, must-revalidate' );
    header( 'Cache-Control: post-check=0, pre-check=0', false );
    header( 'Pragma: no-cache' );   

    switch($method)
    {
        case 'refresh'  : header("Refresh:0;url=".$uri);
            break;
        default         : 
            header("Location: ".$uri, TRUE, $http_response_code);
            break;
    }
    exit;
}

}

Cheers, Ajit