FriendsOfSymfony / FOSFacebookBundle

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

Using FOSFacebookBundle to bind "fosuserbundle users" to facebook accounts #145

Open Andy0763 opened 12 years ago

Andy0763 commented 12 years ago

Currently, the custom provider presented in the documentation creates a new user in the FOSUserBundle database, with all its user info extracted from facebook. (basically, the facebookId, email, first and last name)

Would there be an accessible way to use this bundle so that, when a user that has logged in through the form login connects itself for the first time with the facebook button, it updates its database record with new info (in appropriate nullable fields added in the user entity), instead of creating yet another user?

Therefore a user could only login to the website through the form, but this user would then be able to "bind" their website account to their facebook account, if they want to.

Yet I cannot seem to get a firm conviction that this bundle allows to process such a thing without fiddling consistently with its core components...

daFish commented 12 years ago

I got this feature working today and it was easier than I thought. I already begun writing some documentation but I'm unsure if this would fit in the current README.md or better be split up in an separate document? Any thoughts @stof or @lsmith77?

lsmith77 commented 12 years ago

I think for now its fine to put it into the README. splitting things up should imho be done in a second step if necessary.

daFish commented 12 years ago

Ok, great. This will also fix an issue when a user is already registered and wants to login with his Facebook account having the same email adress.

Andy0763 commented 12 years ago

Thanks for the help!

I also thought of using the email address for identifying already registered users. I think the problem with this solution is that email match is an effective but not sufficient condition: what if the user registered to his facebook account with a different email address than the one he used for the website?

One solution I thought of is trying to store the user's ID in the session before the authentication process hits and the "check_path" disconnects the user, so that I can use the stored ID in the FacebookProvider to identify the user.

An other more "handcrafty" solution would be to design a different facebook button which does not even use authentication on symfony. After facebook oauth, the button would point to a controller which would recover the info stored in the "fbsr_" cookie using the facebook SDK, and modify the user entry in the manager.

What do you think would be the most efficient?

daFish commented 12 years ago

I used the email condition to prevent an validation error as email_canonical is defined as unique. But I agree it isn't sufficient.

Another, third, solution would be: Still have the normal and Facebook login page but add a new button to the users profile edit page to connect the account. This could be handled independently from the registration process.

Chrysweel commented 12 years ago

Hello!

I'm crazy with this bundle. I have did all the indications of Readme. But I don't know how I can associate my users of my site web, with FOSFacebookBundle. The entity of FOSUserBundle has fields facebook_uid and following the documentation of FOSFacebookBundle I created a field facebookId. But my question is: How can user associate his count of my web with his count of facebook?

I use symfony2.1.3-dev. My config.yml is:

fos_facebook:
    file: %kernel.root_dir%/../vendor/facebook/php-sdk/src/base_facebook.php
    alias: facebook
    app_id: myid
    secret: mysecret
    cookie: tre
    permissions: [email, user_birthday, user_location]
services:
    my.facebook.user:
        class: project\myBundle\Security\User\Provider\FacebookProvider
        arguments:
            facebook: "@fos_facebook.api"
            userManager: "@fos_user.user_manager"

routing.yml

#FosFacebookBundle
_security_check:
      pattern:  /login_check_fb
_security_logout:
      pattern:  /logout

security.yml

providers:
        fos_userbundle:
            id: fos_user.user_provider.username
        my_fos_facebook_provider:
              id: my.facebook.user
    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
        admin:
            switch_user: true
            context: user
            pattern: /admin(.*)
            form_login:
                provider: fos_userbundle
                login_path: /admin/login
                use_forward: false
                check_path: /admin/login_check
                failure_path: null
                use_referer: true #redirige al usuario a la pagina que venia antes de hacer login
            logout:
                path: /admin/logout
                target: / #url a la que va a ir despues de logout

            anonymous: true
       main:
            pattern: ^/*
            form_login:
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
            fos_facebook:
                app_url: "http://apps.facebook.com/subireventos/"
                server_url: "http://localhost/workspace/web/app_dev.php/"
                login_path: /login
                check_path: /login_check_fb
                provider: my_fos_facebook_provider
            logout:
                handlers: ["fos_facebook.logout_handler"]
            anonymous:    true

In my base.html.twig I included:

{{ facebook_initialize({'xfbml': true, 'fbAsyncInit': 'onFbInit();'}) }}

And in one of the page of login(FOSUserBundle) included: ( with this line code, the user can log on facebook, from my web)

{{ 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>

But I don't know how complete the field facebookId and asociate an user facebook - my web I tried several changes, but nothing works. I can log in my web or from facebook, but is separate. Have I what to do anything in app facebook? PLEASE HELP! : )