Search code examples
symfony1doctrinefacebook-likesymfony-1.4sfguard

Facebook cannot communicate with Symfony app due to sfGuardAuth authentication required


I'm building a music website on Symfony 1.4 and Doctrine 1.2. I'm trying to integrate facebook plugins (like, send, post a message buttons) on my pages. For example, I want users to be able to like a song on a song page in my song module. But the problem is, I've used sfDoctrineGuard to secure all modules on my app except for the landing page. So if a user logs in and uses the facebook like button to like a song on the song page, because that song module is secured by sfGuardAuth, facebook API can't talk to it and gets forwarded to the landing page. This means that all likes on my app get posted on facebook activity feed as if the user liked my landing page.

Is there a way to build an exception into sfGuard so that any traffic coming from facebook domain can access that page? Is there a workaround to this? I want to be able to show all the facebook meta data from my secured pages, for whichever song is liked, on a facebook wall. If I disable all sfGuard security, it works fine.

Any help would be great as I'm stumped and haven't found any one else with this problem.


Solution

  • Well, it could be a huge security hole if you want to allow request from Facebook to be able to by pass your sfGuard security. If someone click that link on Facebook, it will also have access to your website without having to be logged in.

    You might find a work around by tweaking the Facebook bot who scrape your page. The user agent of the scraper is: "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)". So it could be easy to allow access to its request by looking at the user agent. BUT, any one can spoof a user agent easily today.

    Maybe you have to find an other way. I though about a kind of light page wich can be accessible for every one and where you display the minimum information (like only the artist and the song name without being able to play it. But just to be sure that, if someone not logged in try to see the page, it won't be redirect to the login page but to this light page. You get the point?

    Then, you can put a huge button to allow new people to register to see the full page.

    Anyway, in any case you will find, you should implement it using filter (in filters.yml). Filters are executed before any action. So it's the perfect place for this kind of check.

    You will find info about filters:

    • on the official website (they are 2 links)
    • here an implementation of a ssl requirement (sorry a googlecache page)
    • here a basic implementation

    edit:

    I will go on sth like that. First, create a user called "facebook bot", and put its id in the /apps/frontend/config/app.yml:

    all:
       facebook_bot_id: 56 // sf_guard_user_id
    

    Then create a simple filter lib/filter/facebookBotFilter.php

    <?php
    
    class facebookBotFilter extends sfFilter
    {
      public function execute ($filterChain)
      {
        $context    = $this->getContext();
        $controller = $context->getController();
        $request    = $context->getRequest();
        $user       = $context->getUser();
    
        // get the user agent
        $pathArray = $request->getPathInfoArray();
        $useragent = isset($pathArray['HTTP_USER_AGENT']) ? $pathArray['HTTP_USER_AGENT'] : '';
    
        if (preg_math('/facebookexternalhit', $useragent))
        {
          $member = Doctrine_Core::getTable('sfGuardUser')->find(sfConfig::get('app_facebook_bot_id'));
          // logged in the facebook bot
          $user->signIn($member);
        }
    
        // execute next filter
        $filterChain->execute();
      }
    }
    

    Don't forget to enabled the filter in apps/frontend/config/filters.yml:

    rendering: ~
    
    facebookBotFilter:
      class: facebookBotFilter
    
    security:  ~