I'm building a PHP site that uses Facebook OAuth as the login mechanism. The problem is that when the user logs out and is directed back to my site, the site is still effectively logged (at least in appearance) in until the user manually refreshes the page.
I suspect the reason for this is because the Facebook cookies are removed only once the return page has finished rendering. I accept I'm not fully versed in the way sessions work.
User logs out
-> Redirect to Facebook
-> Redirect back to site (logout.php)
-> Clear local session
-> Redirect to home page (index.php)
-> Page renders (still logged in)
-> Cookies removed
-> Manual refresh (index.php)
-> Page renders (no longer logged in).
I had a similar issue with an ASP.NET MVC site a little while ago. My fix then was to parse the page with JavaScript after the page had loaded and once the cookies had finally been removed.
I am working on the assumption that I'm doing something wrong. I simply want index.php to recognise that Facebook is logged out without having to refresh.
I use header() to redirect from logout.php to index.php.
header("Location: index.php");
EDIT:
I have tried appending the current time to the redirect url in order to side step caching problems. This has not helped.
EDIT:
Watching cookie activity in FireCookie backs up my suspision that the Auth cookie is removed after the page is rendered. This is obviously not conclusive as FireCookie doesn't show me what's happening server side.
JS Workaround:
My current workaround is to run the following snippet on page load, where $fbUid is the Facebook User ID. It's not ideal though, because it relies on JavaScript.
FB.getLoginStatus(function(response) {
if (<?php echo $fbUid ? "true" : "false" ?> && response.session == null)
window.location.reload();
});
Rich
Probably a cacheing issue. Add some randomly generated value to the query string in the redirect, so it'll appear as a "new" page to the browser, something like:
header('Location: index.php?cachebuster=' . microtime(true));
That should force the browser to fetch a fresh copy, which would then not have the "logged in" content anymore.
Cracked it with help from Delete facebook session cookie from my application on users logout and the SDK source.
Adding this code snippet to the logout page ensures that the authentication is properly removed.
$facebook = new Facebook(array(
'appId' => FB_APP_ID,
'secret' => FB_SECRET,
'cookie' => true,
));
$fbCookieName = 'fbs_' . $facebook->getAppId();
$domain = $facebook->getBaseDomain();
if ($domain) {
$domain = '.' . $domain;
}
setcookie($fbCookieName, '', time() - 3600, '/', $domain);
$facebook->setSession();
The code empties the cookie and expires it at the same time. The session is then explicitly removed.
Rich
hi i have same this issue but i resolve this issue
buy using this
FB.Event.subscribe('auth.login', function(response) {
window.location.reload();
});
FB.Event.subscribe('auth.logout', function(response) {
window.location.reload();
});
please add this script where you have to write your login code. and enjoy
Related
The application is okay and works perfectly. But the issue that we were facing firstly was if a user logged out and tried to log in the next day from a saved/pinned browser tab (route: https://domain/login) the page redirected to the 419 (expired) page. And the user had to use the browser's back button to go back and log in again. So we used redirection to the handler.
$this->renderable(function (\Exception $e) {
if ($e->getPrevious() instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->away(request()->getSchemeAndHttpHost());
};
});
So, on the first login attempt, the handler redirects immediately to the main domain (root path), and because of having no auth session, it is redirected to the https://domain/login page again. So users need to attempt to log in again (2nd time). It's so annoying.
We searched and tested different solutions from the answers to similar issues. On config/session.php we changed multiple things as,
'path' => '/;samesite=none',
'lifetime' => env('SESSION_LIFETIME', 420),
'domain' => env('SESSION_DOMAIN', null), (not set)
'secure' => env('SESSION_SECURE_COOKIE') (not set),
'same_site' => 'lax',
So, the question is, if the token is already expired why the exception handler doesn't simply do its attempt to redirect when the browser opens, the saved/pinned tab is already loaded? Is that handler not working on routes? In that case, how to check if the page is expired or for the login route? Please help me with a solution.
I have a laravel built blog, and to comment on a post (if you're logged out) you must login. I put a link like this:
login to do this.
This redirects to the login form, which once filled out and user is authenticated, I have this:
return Redirect::intended('/');
Which takes the user to the homepage, not the page they intended to be on, in this case, the page with the post that they clicked the login link from to be able to comment. How can I return them back to the intended url in this case?
Actually, Redirect::intended('/') works if there is a key available in the session as url.intended otherwise it redirects to the default URL which is in your case '/', so definitely you didn't put the URL in the session. To accomplish this, you may put the URL in the session using something like this:
Session::put('url.intended', 'url...');
So, probably, in the login link, you may add a query string like this:
login
So, you can track the redirect and in that route's method (before return View) just put the previous URL in the session, using something like this:
if(Input::get('intended')) {
Session::put('url.intended', URL::previous());
}
Then before you redirect from there, you should remove the URL from the session using something like this:
$intendedUrl = Session::get('url.intended', url('/'));
Session::forget('url.intended');
return Redirect::to($intendedUrl);
This should solve the issue. Also, you may check this answer, could be helpful.
Redirect::intended requires two parts to work. The first is when the user tries to access a restricted page /orders but they aren't logged in you redirect them to the login page via:
redirect()->guest('/login');
Then on your login post-back if authentication is successful you call:
redirect()->intended('/dashboard');
I am using Symfony 1.4 with sfGuardDoctrinePlugin. The problem is:
Lets us say the current page URL is www.pg.com/blog/edit.php
Now the session times-out and I click the blog index link
This redirects to www.pg.com/blog but since I need to login, the template for login_module and login_action is served on the same URL (www.pg.com/blog)
Post login, the user is taken to blog index (or even if the user clicks that link), the login template is served since it is cached for the "blog/index".
I suspect that somewhere in sfAuth plugin, there is a forward instead of a redirect that is serving the login template on the other page URL. How can I prevent this?
EDIT: I even got the line where it is happening, but I do not wish to modify Symfony source code. Can I do it outside?
Jul 31 10:02:59 symfony [info] {sfBasicSecurityFilter} Action "blog/index" requires authentication, forwarding to "sfGuardAuth/signin"
The user has to wait for quite some time or clear cache to avoid this.
Thanks
The forwarding is done by the sfBasicSecurityFilter filter. If you want to change the forward to a redirect, you will have to overwrite the forwardToLoginAction in your own security filter:
class mySecurityFilter extends sfBasicSecurityFilter
{
protected function forwardToLoginAction()
{
$this->getContext()->getController()->redirect(sfConfig::get('sf_login_module') . '/' . sfConfig::get('sf_login_action'));
throw new sfStopException();
}
}
I am trying to replace a rather clumpsy ajax-login of Magento from an external site. The site uses Magento as a shop. Both the site and the magento-shop has their own logins, therefor when a user logs in it is important that both are synchronized. This was done with an ajax-call each page reload, keeping the user logged into Magento. I want to remove this so I created a check on each page reload which will do everything server-side.
My problem is, the following code does not work properly:
//Get Magento session-object
Mage::getSingleton("core/session", array("name"=>"frontend"));
$session = Mage::getSingleton("customer/session", array("name"=>"frontend"));
//Check if logged in
if(!$session->isLoggedIn()){
//Not logged in, therefor log in
$mpassword = $this->getMagentoPassword();
$musername = $this->getAddress();
try
{
$session->login($musername, $mpassword);
}catch(Exception $e){
echo $e->getMessage();
}
}
Looking at cookies, there aren't any created, the ajax-login actually made a "frontend"-cookie. I know the code above actually logs in a user, but there aren't any session cookies created. Any suggestions?
Magento only initializes the session with your code if the $_SESSION variable isn't set, i.e. session_start() wasn't called before the core session is instantiated.
Reference Mage_Core_Model_Session_Abstract_Varien::start() for details.
As a solution, the easiest way would be to start the Magento session during a request before the other session of your site is started.
Otherwise you will have to duplicate the code that sets the session name to frontend and initializes the Magento session cookie.
I'm building a website with Facebook Connect and therefore using the Facebook Javascript SDK.
Problem: when using Firefox, the page doesn't reload properly once logged in or logged out.
FB.Event.subscribe(
'{% if current_user %}auth.logout{% else %}auth.login{% endif %}',
function(response){
window.location.reload();
});
Obviously, it looks like a known problem (just type "window location reload not working on firefox" and you'll get a lot of results)
More precisely, Firefox doesn't seem to send the right cookie when reloading the page...
- When I click to login, once Facebook logged me in and sets a cookie, Firefox doesn't send any cookie
- When I click to logout, once Facebook has logged me out and remove the cookie, Firefox sends the cookie that was previously there.
I conclude it uses some "cache functions".
I tried to make a workaround as described here and implemented this:
redirect_url = encodeURIComponent(window.location.href);
url = window.location.href + "account/login?redirect_url=" + redirect_url;
window.location.replace(url);
But the problem remains (the cache I guess...) Can you help me out with this?
Thanks.
Try wrapping the window.location.reload() call in a setTimeout() with a zero delay. Apparently, Firefox fires the event before setting the cookie. The wrapping should place the reload call in the event queue and allow the cookies to be set correctly.
Incase there was anymore confusion over this, for Firefox, the above referenced example of setTimeout() works perfectly. Simply include your reload call, or if it's easier just replace:
document.location.reload();
with:
setTimeout('document.location.reload()',0);
Using the most recent version of Firefox released, I have tested every example above, and this is the only one that has actually worked consistently. Basically, you just need to "pause" the JavaScript just for a moment to let the rest of the script catch up. I did not test this on Chrome or IE, but it does work flawlessly on Firefox.
We are using the work-around with
window.location.href = url;
instead of
window.location.replace(url);
Works fine in Firefox, too.
For anyone using Rails and Koala, you can just check for the cookies and redirect to the same action if they are not present:
def fb_authenticate
#fb_cookies ||= Koala::Facebook::OAuth.new.get_user_info_from_cookie(cookies)
if #fb_cookies
#login user or create new user
else
redirect_to :controller => 'account', :action => 'fb_authenticate'
end
end
Try redirect to a different URL each time:
top.location.href = 'https://apps.facebook.com/YOUR_APP_NAME/?t=' + <?php echo time(); ?>;
, I use PHP but you can replace with JS ( Math.round(+new Date()/1000) I guess ).