4

I have a symfony2 website and a web service secured via oauth using FOSOAuthServerBundle accessible via an iOS app. On the website I use FOSUserBundle and FOSFacebookBundle.

The only thing I miss is giving the possibility to the user to login with facebook on the iOS app and to return him an access_token for my oauth linked to his user account so that he can access my api like other users.

So basically I want to send the user facebookID and facebook_access_token to my webservice, check that the user is correct (token matches my app) and return an authentication token.

QUESTION: is there an easy way to add a "Facebook" grant_type to FOSOAuthServerBundle ?

I know some people have done this seeing these questions:

But they do not explain how, they do not seem to use FOSOauthServerBundle and questions are quite old.

I have tried using this bundle: https://github.com/TheFootballSocialClub/FSCOAuth2FacebookGrantBundle

but this bundle has been downloaded only 9 times before me and is not fully suited to my app (it considers that a Facebook user username equals his facebookId for instance). So I guess what I want to do is re-implement the same kind of thing my own way.

If anyone has already done that our could provide any guidance it would be very much appreciated.

Thank you

Community
  • 1
  • 1
Jules Marcilhacy
  • 161
  • 1
  • 11

1 Answers1

2

To do this, you have to add a Grant Extensions, see the official document "Adding Grant Extensions" : https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/adding_grant_extensions.md

You can find my FacebookGrantExtension to get a token from a FB access_token :

class FacebookGrantExtension implements GrantExtensionInterface
{
protected $userManager = null;
protected $facebookSdk = null;

public function __construct(UserManager $userManager, \BaseFacebook $facebookSdk)
{
    $this->userManager = $userManager;
    $this->facebookSdk = $facebookSdk;
}

/**
 * @see OAuth2\IOAuth2GrantExtension::checkGrantExtension
 */
public function checkGrantExtension(IOAuth2Client $client, array $inputData, array $authHeaders)
{
    if (!isset($inputData['facebook_access_token'])) {
        return false;
    }

    $this->facebookSdk->setAccessToken($inputData['facebook_access_token']);
    try {
        // Try to get the user with the facebook token from Open Graph
        $fbData = $this->facebookSdk->api('/me');

        if (empty($fbData) || !isset($fbData['id'])) {
            return false;
        }

        // Check if a user match in database with the facebook id
        $user = $this->userManager->findUserBy(array(
            'facebookId' => $fbData['id']
        ));

        // If no user found, register a new user and grant token
        if (null === $user) {
            return false;
        } 
        // Else, return the access_token for the user            
        else {
            return array(
                'data' => $user
            );
        }
    } catch(\FacebookApiExceptionion $e) {
        return false;
    }
}
}

And the config.yml :

my.oauth.facebook_extension:
    class: My\CoreBundle\Oauth\FacebookGrantExtension
    arguments:
        userManager: "@fos_user.user_manager"
        facebookSdk: "@fos_facebook.api"
    tags:
        - { name: fos_oauth_server.grant_extension, uri: 'http://grants.api.mywebsite.com/facebook_access_token' }
PierrickM
  • 656
  • 6
  • 14
  • Ouha I had not seen your answer before. What I did was doing it manually in a controller when a user logs in with Facebook, once i get the facebook token I login/register the user manually and create an access_token that is set for the user and with all properties of the automatically generated one. What is the advantage of using grant extensions then? Thanks – Jules Marcilhacy Sep 29 '13 at 19:16
  • Using a grant extensions it's the "best way" to do this but your solution works also even if it's a little bit tricky and less adaptive – PierrickM Sep 30 '13 at 08:08
  • OK thanks! So I understand I can't avoid having 2 api requests anyway (one for facebook and one for my token then). – Jules Marcilhacy Sep 30 '13 at 22:10
  • No you can't avoid it on login/register process. – PierrickM Oct 01 '13 at 07:36
  • I am also using this grant extension now, but I am facing a problem. I am using it together with ember and this technique: https://github.com/simplabs/ember-simple-auth/blob/master/examples/7-external-oauth/index.html. With that my frontend calls facebook and the redirect url is then my backend. But at this time when my backend is called the access token from facebook might be new, which means that finding user by id and token fails. How have you handled this? – m0c Mar 09 '14 at 10:26
  • I just edited my answer, instead of searching user who matching FB Id and FB Access token on your database, search only user that match the FB ID. – PierrickM Apr 01 '14 at 16:14