FriendsOfSymfony / FOSFacebookBundle

NOT MAINTAINED - see https://github.com/hwi/HWIOAuthBundle
322 stars 140 forks source link

Can not login #244

Closed ghost closed 10 years ago

ghost commented 11 years ago

Hello,

I have followed the basic usage documentation, but there is something wrong with the login. When I click on the login button, I select Login with Facebook in the popup window which closes, but nothing more happens. Do you have any idea what could be the cause? Here is my code:

routing.yml

_security_check:
    pattern: /login_check
    defaults: { _controller: "TestBundle:Splash:check" }

_security_logout:
    pattern: /logout
    defaults: { _controller: "TestBundle:Splash:logout" }

SplashController.php

    public function checkAction()
    {
        // Call intercepted by the Security Component of Symfony
    }

    public function logoutAction()
    {
        // Call intercepted by the Security Component of Symfony
    }

config.yml

fos_facebook:
    alias:  facebook
    app_id: "%facebook_id%"
    secret: "%facebook_secret%"
    cookie: true
    permissions: []

paramters.yml

    facebook_id:       [hidden]
    facebook_secret:   [hidden]
    facebook_app:      http://localhost/test/web/app_dev.php/
    facebook_server:   http://localhost/test/web/app_dev.php/

security.yml

security:
    encoders:
        Test\TestBundle\Security\User\FacebookProvider: sha512

    role_hierarchy:
        ROLE_ADMIN: ROLE_USER

    providers:
        facebook_provider:
            id: facebook_user_provider

    firewalls:
        main:
            pattern: ^/
            fos_facebook:
                app_url: "%facebook_app%"
                server_url: "%facebook_server%"
                login_path: /
                check_path: /login_check
                default_target_path: /
                provider: facebook_provider
            logout:
                path: /logout
            anonymous: true

        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false

    access_control:
        - { path: ^/path, roles: ROLE_USER }
        - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

FacebookProvider.php

namespace Test\TestBundle\Security\User;

use \BaseFacebook;
use \FacebookApiException;
use Doctrine\ORM\EntityManager;
use Test\TestBundle\Entity\Person;
use Symfony\Bridge\Monolog\Logger;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;

class FacebookProvider implements UserProviderInterface
{
    protected $facebook;

    /**
     * Entity manager
     * 
     * @var EntityManager
     */
    protected $em;

    /**
     * 
     * @var Vali
     */
    protected $validator;

    /**
     * Logger
     * 
     * @var Logger
     */
    private $logger;

    public function __construct(BaseFacebook $facebook, EntityManager $em, $validator, Logger $logger)
    {
        $this->facebook = $facebook;
        $this->em = $em;
        $this->validator = $validator;
        $this->logger = $logger;

        $this->logger->debug('FacebookProvider created!');
    }

    public function loadUserByUsername($username)
    {
        $this->logger->debug('Load user by username: '.$username);

        // query user
        $query = $this->em->createQuery(
            'SELECT p
            FROM TestTestBundle:Person p
            WHERE p.id = :id')
            ->setParameter('id', $username);
        try
        {
            $person = $query->getSingleResult();
        }
        catch (NoResultException $e)
        {
            $person = null;

            $this->logger->debug('No user found in the database.');
        }

        $this->logger->debug('Try to get her data from Facebook.');

        try
        {
            $fbdata = $this->facebook->api('/me');
        }
        catch (FacebookApiException $e)
        {
            $fbdata = null;

            $this->logger->debug('Not data received from facebook.');
        }

        if (!empty($fbdata))
        {
            if (empty($person))
            {
                $this->logger->debug('Create user because she does not exist yet.');

                // create user because she does not exist
                $person = new Person();
                $this->em->persist($person);
            }

            // set data
            $person->setFBData($fbdata);

            // verify whether or not the data satisfies the constraints
            if (count($this->validator->validate($person)))
            {
                $this->logger->debug('The data could not be validated');

                // TO DO: the user was found obviously, but does not match our excpectations, do something smart
                throw new UsernameNotFoundException('The facebook user could not be stored.');
            }
            else
            {
                $this->logger->debug('Commit user (changes) to database.');

                // commit changes to database
                $this->em->flush();
            }
        }

        if (empty($person))
            throw new UsernameNotFoundException('The user is not authenticated on facebook.');

        return $person;
    }

    public function refreshUser(UserInterface $user)
    {
        $this->logger->debug('refreshUser() is called.');

        if (!$this->supportsClass(get_class($user)) || !$user->getId())
            throw new UnsupportedUserException(sprintf('Instances of %s are not supported.', get_class($user)));

        return $this->loadUserByUsername($user->getId());
    }

    public function supportsClass($class)
    {
        $this->logger->debug('supportsClass() is called.');

        return $class === 'Test\TestBundle\Entity\Person';
    }
}

index.html.twig

<html xmlns:fb="http://www.facebook.com/2008/fbml">

        {{ facebook_initialize({'xfbml': true, 'fbAsyncInit': 'onFbInit();'}) }}
        <script>
            function goLogIn(){
                window.location.href = "{{ path('_security_check') }}";
            }

            function onFbInit() {
                if (typeof(FB) != 'undefined' && FB != null ) {            
                    FB.Event.subscribe('auth.statusChange', function(response) {
                        if (response.session || response.authResponse) {
                            setTimeout(goLogIn, 500);
                        } else {
                            window.location.href = "{{ path('_security_logout') }}";
                        }
                    });
                }
            }
        </script>

{{ facebook_login_button({'autologoutlink': true}) }}
dupuchba commented 11 years ago

I already had this one, did you check if your facebook user as ADMIN/TEST role in facebook dashboard? If you don't find any solution on this one, it should be your security.yml . In this case you should check the LiipHelloBundle which implement facebook auth or read the doc again ;)

ghost commented 11 years ago

Yes, I am registrated as admin in the developer roles of the facebook app. And I have compared my code to the documentation already multiple times, but it will not work.

When I access the website tested locally from another computer in my local network, the login button changes to a logout button after the popup window closes! However, when I then try to access the /path path, which is under access control, I am redirected to the login page and the following error message is shown: "The Facebook user could not be retrieved from the session." Additionally, no user is created in the database by my facebook user provider.

dupuchba commented 11 years ago

@overthesun I don't have enough informations to help you, again it happened with me and I restart all the conf. again and it worked. Sry...

djepo commented 11 years ago

I have exactly the same problem. I really can't understand the source of that problem.

ghost commented 10 years ago

I am sorry to reply so late. Somehow it worked for me in Google Chrome but not in Mozilla Firefox. As it had been only a prototype, this workaround satisfied my needs. So I did not investigate the problem further and I did not update to the versions of Symfony and FOSFacebookBundle released later on.