Search code examples
iossymfonyoauthfacebook-ios-sdk

FOSOAuthServerBundle - generate manually an access token


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


Solution

  • 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' }