Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FOSFacebookBundle and FOSUserBundle

I'm trying to setup FOSFacebookBundle and FOSUserBundle, so users can login with registered accounts or facebook accounts.

Here relevant codes:

config.yml:

fos_user:
db_driver: orm 
firewall_name: public
user_class: Fam\DiaBundle\Entity\User
from_email:
    address:        [email protected]
    sender_name:    Staff
registration:
    confirmation:
        enabled:    true

fos_facebook:

    file:   %kernel.root_dir%/../vendor/facebook/src/base_facebook.php
    alias:  facebook
    app_id: 1234567890
    secret: abcdefg1234567890
    cookie: true
    permissions: [email]
    culture: us_US

security.yml

#
# app/config/security.yml
#
#

services:
    my.facebook.user:
        class: Fam\Dia\Security\User\Provider\FacebookProvider
        arguments:
            facebook: "@fos_facebook.api"
            userManager: "@fos_user.user_manager"
            validator: "@validator"
            container: "@service_container"
security:
    factories:
        - "%kernel.root_dir%/../vendor/bundles/FOS/FacebookBundle/Resources/config/security_factories.xml"

    providers:
        chain_provider:
            providers: [fos_userbundle, my_fos_facebook_provider]
        fos_userbundle:
            id: fos_user.user_manager
        my_fos_facebook_provider:
            id: my.facebook.user

encoders:
        "FOS\UserBundle\Model\UserInterface": sha512

    firewalls:
        public:
          pattern:   ^/
          fos_facebook:
            app_url: "http://apps.facebook.com/dia/"
            server_url: "http://diafam.com/facebookApp/"
            login_path: /login
            check_path: /login_check
            default_target_path: /
            provider: my_fos_facebook_provider
          form_login:
            login_path: /login
            check_path: /login_check
            provider: fos_userbundle
          anonymous: true
          logout:    true            


    access_control:
        - { path: ^/secured/.*, role: [IS_AUTHENTICATED_FULLY] } # This is the route secured with     fos_facebook
        - { path: ^/facebook/,   role: [ROLE_FACEBOOK] }
        - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, role: ROLE_ADMIN }
        # FOS facebook
        - { path: ^/login_check, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/.*, role: [IS_AUTHENTICATED_ANONYMOUSLY] }
        #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

routing.yml

_security_check:
      pattern:  /login_check
_security_logout:
      pattern:  /logout

_security_login:
      pattern:   /login

FacebookProvider.php

<?php

// src/Fam\DiaBundle\Security\User\Provider/FacebookProvider.php

namespace Fam\DiaBundle\Security\User\Provider;

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;
use \BaseFacebook;
use \FacebookApiException;

class FacebookProvider implements UserProviderInterface
{
    /**
     * @var \Facebook
     */
    protected $facebook;
protected $userManager;
protected $validator;

public function __construct(BaseFacebook $facebook, $userManager, $validator)
{
    $this->facebook = $facebook;
    $this->userManager = $userManager;
    $this->validator = $validator;
}

public function supportsClass($class)
{
    return $this->userManager->supportsClass($class);
}

public function findUserByFbId($fbId)
{
    return $this->userManager->findUserBy(array('facebookId' => $fbId));
}

public function loadUserByUsername($username)
{
    $user = $this->findUserByFbId($username);

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

    if (!empty($fbdata)) {
        if (empty($user)) {
            $user = $this->userManager->createUser();
            $user->setEnabled(true);
            $user->setPassword('');
        }

        // TODO use http://developers.facebook.com/docs/api/realtime
        $user->setFBData($fbdata);

        if (count($this->validator->validate($user, 'Facebook'))) {
            // TODO: the user was found obviously, but doesnt match our expectations, do something smart
            throw new UsernameNotFoundException('The facebook user could not be stored');
        }
        $this->userManager->updateUser($user);
    }

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

    return $user;
}

public function refreshUser(UserInterface $user)
{
    if (!$this->supportsClass(get_class($user)) || !$user->getFacebookId()) {
        throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user)));
    }

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

login.html.twig

{% extends '::base.html.twig' %}


{% block body %}
{{ facebook_initialize({'xfbml': true, 'fbAsyncInit': 'onFbInit();'}) }}
{{ facebook_login_button({'autologoutlink': true}) }}
<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>


    {% for key, message in app.session.getFlashes() %}
    <div class="{{ key }}">
        {{ message|trans({}, 'FOSUserBundle') }}
    </div>
    {% endfor %}


{% if error %}
    <div>{{ error }}</div>
{% endif %}

<form action="{{ path("fos_user_security_check") }}" method="post">
    <h5><label for="username">{{ 'security.login.username'|trans({}, 'FOSUserBundle') }}</label><br/>
    <input type="text" id="username" name="_username" value="{{ last_username }}" size=30 /><p>

    <label for="password">{{ 'security.login.password'|trans({}, 'FOSUserBundle') }}</label><br/>
    <input type="password" id="password" name="_password" size=30 /><p>

    <input type="checkbox" id="remember_me" name="_remember_me" value="on" />
    <label for="remember_me">{{ 'security.login.remember_me'|trans({}, 'FOSUserBundle') }}</label><p>

    <input type="submit" id="_submit" name="_submit" value="Entra" />
</form>
        </div>

{% endblock body %}

May you help me?

like image 293
Vittore Avatar asked Jan 28 '12 16:01

Vittore


2 Answers

Here the solution:

in routing.yml

_security_check:
     pattern:  /loginFb

in security.yml:

      fos_facebook:
        check_path: /loginFb

in default controller:

    /**
 * Dummy controller.
 *
 * @Route("/loginFb")
 * @Template
 *
 * 
 * */
public function loginFbAction() {
}
like image 111
Vittore Avatar answered Oct 07 '22 16:10

Vittore


https://github.com/FriendsOfSymfony/FOSFacebookBundle/tree/2.0#include-the-login-button-in-your-templates says:

Note that we wait 500ms before redirecting to let the browser dealing with the Facebook cookie. You can avoid this step but you might get this error message: "The Facebook user could not be retrieved from the session."

like image 22
ButterDog Avatar answered Oct 07 '22 18:10

ButterDog