├── .gitignore ├── .travis.yml ├── Controller └── FacebookController.php ├── DependencyInjection ├── Configuration.php ├── FOSFacebookExtension.php └── Security │ └── Factory │ └── FacebookFactory.php ├── FOSFacebookBundle.php ├── Facebook └── FacebookSessionPersistence.php ├── README.md ├── Resources ├── config │ ├── facebook.xml │ ├── routing.xml │ ├── schema │ │ └── facebook-1.0.xsd │ └── security.xml ├── doc │ ├── 1-basic-usage.md │ ├── 2-integration-with-fosuserbundle.md │ ├── 3-another-resources.md │ ├── 4-example-server-side-facebook-login-using-mobile-apps.md │ └── index.md ├── meta │ └── LICENSE └── views │ ├── initialize.html.php │ ├── initialize.html.twig │ ├── loginButton.html.php │ └── loginButton.html.twig ├── Security ├── Authentication │ ├── Provider │ │ └── FacebookProvider.php │ └── Token │ │ └── FacebookUserToken.php ├── EntryPoint │ └── FacebookAuthenticationEntryPoint.php ├── Firewall │ └── FacebookListener.php └── User │ └── UserManagerInterface.php ├── Templating └── Helper │ └── FacebookHelper.php ├── Tests ├── Controller │ └── FacebookControllerTest.php ├── DependencyInjection │ ├── ConfigurationTest.php │ ├── FOSFacebookExtensionTest.php │ └── Security │ │ └── Factory │ │ └── FacebookFactoryTest.php ├── FacebookApiException.php ├── Fixtures │ └── App │ │ └── app │ │ ├── AppKernel.php │ │ └── config │ │ ├── config.yml │ │ └── routing.yml ├── Kernel.php ├── Security │ ├── Authentication │ │ ├── Provider │ │ │ └── FacebookProviderTest.php │ │ └── Token │ │ │ └── FacebookUserTokenTest.php │ ├── EntryPoint │ │ └── FacebookAuthenticationEntryPointTest.php │ └── Firewall │ │ └── FacebookListenerTest.php ├── Templating │ └── Helper │ │ └── FacebookHelperTest.php ├── Twig │ └── Extension │ │ └── FacebookExtensionTest.php └── bootstrap.php ├── Twig └── Extension │ └── FacebookExtension.php ├── composer.json └── phpunit.xml.dist /.gitignore: -------------------------------------------------------------------------------- 1 | phpunit.xml 2 | coverage 3 | vendor 4 | bin 5 | composer.phar 6 | composer.lock 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | 7 | before_script: 8 | - composer install --dev --prefer-dist 9 | 10 | script: phpunit --coverage-text 11 | 12 | notifications: 13 | email: 14 | - friendsofsymfony-dev@googlegroups.com 15 | -------------------------------------------------------------------------------- /Controller/FacebookController.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Controller; 13 | 14 | use Symfony\Component\DependencyInjection\ContainerAware; 15 | use Symfony\Component\HttpFoundation\Response; 16 | 17 | class FacebookController extends ContainerAware 18 | { 19 | /** 20 | * public function channelAction() 21 | * 22 | * This function mimics the channel.html file suggested by facebook. 23 | * 24 | * References : 25 | * https://developers.facebook.com/docs/reference/javascript/ 26 | * 27 | * @version 1.0 28 | * 29 | * @author Antoine Durieux 30 | * 31 | * @return Response 32 | */ 33 | public function channelAction() 34 | { 35 | // Retrieve parameters from the container. 36 | $culture = $this->container->getParameter('fos_facebook.culture'); 37 | $cacheExpire = $this->container->getParameter('fos_facebook.channel.expire'); 38 | 39 | // Compute expiration date. 40 | $date = new \DateTime(); 41 | $date->modify('+'.$cacheExpire.' seconds'); 42 | 43 | // Generate new response, and set parameters recommended by Facebook. 44 | $response = new Response(); 45 | $response->headers->set("Pragma", "public"); 46 | $response->setMaxAge($cacheExpire); 47 | $response->setExpires($date); 48 | $response->setContent(''); 49 | 50 | return $response; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\DependencyInjection; 13 | 14 | use Symfony\Component\Config\Definition\Builder\TreeBuilder, 15 | Symfony\Component\Config\Definition\ConfigurationInterface; 16 | 17 | /** 18 | * This class contains the configuration information for the bundle 19 | * 20 | * This information is solely responsible for how the different configuration 21 | * sections are normalized, and merged. 22 | * 23 | * @author Lukas Kahwe Smith 24 | */ 25 | class Configuration implements ConfigurationInterface 26 | { 27 | /** 28 | * Generates the configuration tree. 29 | * 30 | * @return TreeBuilder 31 | */ 32 | public function getConfigTreeBuilder() 33 | { 34 | $treeBuilder = new TreeBuilder(); 35 | $rootNode = $treeBuilder->root('fos_facebook'); 36 | 37 | $rootNode 38 | ->fixXmlConfig('permission', 'permissions') 39 | ->children() 40 | ->scalarNode('app_id')->isRequired()->cannotBeEmpty()->end() 41 | ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end() 42 | ->scalarNode('cookie')->defaultFalse()->end() 43 | ->scalarNode('domain')->defaultNull()->end() 44 | ->scalarNode('alias')->defaultNull()->end() 45 | ->scalarNode('logging')->defaultValue('%kernel.debug%')->end() 46 | ->scalarNode('culture')->defaultValue('en_US')->end() 47 | ->arrayNode('class') 48 | ->addDefaultsIfNotSet() 49 | ->children() 50 | ->scalarNode('api')->defaultValue('FOS\FacebookBundle\Facebook\FacebookSessionPersistence')->end() 51 | ->scalarNode('helper')->defaultValue('FOS\FacebookBundle\Templating\Helper\FacebookHelper')->end() 52 | ->scalarNode('twig')->defaultValue('FOS\FacebookBundle\Twig\Extension\FacebookExtension')->end() 53 | ->end() 54 | ->end() 55 | ->arrayNode('channel') 56 | ->addDefaultsIfNotSet() 57 | ->children() 58 | ->scalarNode('expire')->defaultValue(60*60*24*365)->end() 59 | ->end() 60 | ->end() 61 | ->arrayNode('permissions')->prototype('scalar')->end() 62 | ->end(); 63 | 64 | return $treeBuilder; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /DependencyInjection/FOSFacebookExtension.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\DependencyInjection; 13 | 14 | use Symfony\Component\Config\Definition\Processor; 15 | use Symfony\Component\HttpKernel\DependencyInjection\Extension; 16 | use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; 17 | use Symfony\Component\DependencyInjection\ContainerBuilder; 18 | use Symfony\Component\Config\FileLocator; 19 | 20 | class FOSFacebookExtension extends Extension 21 | { 22 | protected $resources = array( 23 | 'facebook' => 'facebook.xml', 24 | 'security' => 'security.xml', 25 | ); 26 | 27 | public function load(array $configs, ContainerBuilder $container) 28 | { 29 | $processor = new Processor(); 30 | $configuration = new Configuration(); 31 | $config = $processor->processConfiguration($configuration, $configs); 32 | 33 | $this->loadDefaults($container); 34 | 35 | if (isset($config['alias'])) { 36 | $container->setAlias($config['alias'], 'fos_facebook.api'); 37 | } 38 | 39 | foreach (array('api', 'helper', 'twig') as $attribute) { 40 | $container->setParameter('fos_facebook.'.$attribute.'.class', $config['class'][$attribute]); 41 | } 42 | 43 | foreach (array('app_id', 'secret', 'cookie', 'domain', 'logging', 'culture', 'permissions') as $attribute) { 44 | $container->setParameter('fos_facebook.'.$attribute, $config[$attribute]); 45 | } 46 | 47 | $container->setParameter('fos_facebook.channel.expire', $config['channel']['expire']); 48 | 49 | if (isset($config['file']) && $container->hasDefinition('fos_facebook.api')) { 50 | $facebookApi = $container->getDefinition('fos_facebook.api'); 51 | $facebookApi->setFile($config['file']); 52 | } 53 | } 54 | 55 | /** 56 | * @codeCoverageIgnore 57 | */ 58 | public function getXsdValidationBasePath() 59 | { 60 | return __DIR__ . '/../Resources/config/schema'; 61 | } 62 | 63 | /** 64 | * @codeCoverageIgnore 65 | */ 66 | public function getNamespace() 67 | { 68 | return 'http://symfony.com/schema/dic/fos_facebook'; 69 | } 70 | 71 | /** 72 | * @codeCoverageIgnore 73 | */ 74 | protected function loadDefaults($container) 75 | { 76 | $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); 77 | 78 | foreach ($this->resources as $resource) { 79 | $loader->load($resource); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /DependencyInjection/Security/Factory/FacebookFactory.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\DependencyInjection\Security\Factory; 13 | 14 | use Symfony\Component\DependencyInjection\ContainerBuilder; 15 | use Symfony\Component\DependencyInjection\Reference; 16 | use Symfony\Component\DependencyInjection\DefinitionDecorator; 17 | use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\AbstractFactory; 18 | 19 | class FacebookFactory extends AbstractFactory 20 | { 21 | public function __construct() 22 | { 23 | $this->addOption('display', 'page'); 24 | $this->addOption('app_url'); 25 | $this->addOption('server_url'); 26 | $this->addOption('create_user_if_not_exists', false); 27 | $this->addOption('redirect_to_facebook_login', true); 28 | } 29 | 30 | public function getPosition() 31 | { 32 | return 'pre_auth'; 33 | } 34 | 35 | public function getKey() 36 | { 37 | return 'fos_facebook'; 38 | } 39 | 40 | protected function getListenerId() 41 | { 42 | return 'fos_facebook.security.authentication.listener'; 43 | } 44 | 45 | protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId) 46 | { 47 | $authProviderId = 'fos_facebook.auth.'.$id; 48 | 49 | $definition = $container 50 | ->setDefinition($authProviderId, new DefinitionDecorator('fos_facebook.auth')) 51 | ->replaceArgument(0, $id); 52 | 53 | // with user provider 54 | if (isset($config['provider'])) { 55 | $definition 56 | ->addArgument(new Reference($userProviderId)) 57 | ->addArgument(new Reference('security.user_checker')) 58 | ->addArgument($config['create_user_if_not_exists']) 59 | ; 60 | } 61 | 62 | return $authProviderId; 63 | } 64 | 65 | protected function createEntryPoint($container, $id, $config, $defaultEntryPointId) 66 | { 67 | $entryPointId = 'fos_facebook.security.authentication.entry_point.'.$id; 68 | $container 69 | ->setDefinition($entryPointId, new DefinitionDecorator('fos_facebook.security.authentication.entry_point')) 70 | ->replaceArgument(1, $config) 71 | ; 72 | 73 | // set options to container for use by other classes 74 | $container->setParameter('fos_facebook.options.'.$id, $config); 75 | 76 | return $entryPointId; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /FOSFacebookBundle.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle; 13 | 14 | use FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory; 15 | use Symfony\Component\DependencyInjection\ContainerBuilder; 16 | use Symfony\Component\HttpKernel\Bundle\Bundle; 17 | 18 | class FOSFacebookBundle extends Bundle 19 | { 20 | public function build(ContainerBuilder $container) 21 | { 22 | parent::build($container); 23 | 24 | $extension = $container->getExtension('security'); 25 | $extension->addSecurityListenerFactory(new FacebookFactory()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Facebook/FacebookSessionPersistence.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class FacebookSessionPersistence extends \BaseFacebook 14 | { 15 | const PREFIX = '_fos_facebook_'; 16 | 17 | protected $session; 18 | protected $prefix; 19 | protected static $kSupportedKeys = array('state', 'code', 'access_token', 'user_id'); 20 | 21 | /** 22 | * @param array $config 23 | * @param Session $session 24 | * @param string $prefix 25 | */ 26 | public function __construct($config, Session $session, $prefix = self::PREFIX) 27 | { 28 | $this->session = $session; 29 | $this->prefix = $prefix; 30 | 31 | $this->setAppId($config['appId']); 32 | $this->setAppSecret($config['secret']); 33 | if (isset($config['fileUpload'])) { 34 | $this->setFileUploadSupport($config['fileUpload']); 35 | } 36 | // Add trustProxy configuration 37 | $this->trustForwarded = isset($config['trustForwarded']) ? $config['trustForwarded'] : Request::getTrustedProxies(); 38 | } 39 | 40 | /** 41 | * @param array $params 42 | * @return string 43 | */ 44 | public function getLoginUrl($params = array()) 45 | { 46 | $this->establishCSRFTokenState(); 47 | $currentUrl = $this->getCurrentUrl(); 48 | 49 | // if 'scope' is passed as an array, convert to comma separated list 50 | $scopeParams = isset($params['scope']) ? $params['scope'] : null; 51 | if ($scopeParams && is_array($scopeParams)) { 52 | $params['scope'] = implode(',', $scopeParams); 53 | } 54 | 55 | return $this->getUrl( 56 | 'www', 57 | 'dialog/oauth', 58 | array_merge( 59 | array( 60 | 'client_id' => $this->getAppId(), 61 | 'redirect_uri' => $currentUrl, // possibly overwritten 62 | 'state' => $this->getState(), 63 | ), 64 | $params 65 | ) 66 | ); 67 | } 68 | 69 | /** 70 | * @return bool|mixed 71 | */ 72 | protected function getCode() 73 | { 74 | if (isset($_REQUEST['code'])) { 75 | if ($this->getState() !== null && 76 | isset($_REQUEST['state']) && 77 | $this->getState() === $_REQUEST['state']) { 78 | 79 | // CSRF state has done its job, so clear it 80 | $this->setState(null); 81 | $this->clearPersistentData('state'); 82 | 83 | return $_REQUEST['code']; 84 | } else { 85 | self::errorLog('CSRF state token does not match one provided.'); 86 | 87 | return false; 88 | } 89 | } 90 | 91 | return false; 92 | } 93 | 94 | protected function establishCSRFTokenState() 95 | { 96 | if ($this->getState() === null) { 97 | $this->setState(md5(uniqid(mt_rand(), true))); 98 | } 99 | } 100 | 101 | /** 102 | * Stores the given ($key, $value) pair, so that future calls to 103 | * getPersistentData($key) return $value. This call may be in another request. 104 | * 105 | * @param string $key 106 | * @param array $value 107 | * 108 | * @return void 109 | */ 110 | protected function setPersistentData($key, $value) 111 | { 112 | if (!in_array($key, self::$kSupportedKeys)) { 113 | self::errorLog('Unsupported key passed to setPersistentData.'); 114 | 115 | return; 116 | } 117 | 118 | $this->session->set($this->constructSessionVariableName($key), $value); 119 | } 120 | 121 | /** 122 | * Get the data for $key, persisted by BaseFacebook::setPersistentData() 123 | * 124 | * @param string $key The key of the data to retrieve 125 | * @param boolean $default The default value to return if $key is not found 126 | * 127 | * @return mixed 128 | */ 129 | protected function getPersistentData($key, $default = false) 130 | { 131 | if (!in_array($key, self::$kSupportedKeys)) { 132 | self::errorLog('Unsupported key passed to getPersistentData.'); 133 | 134 | return $default; 135 | } 136 | 137 | $sessionVariableName = $this->constructSessionVariableName($key); 138 | if ($this->session->has($sessionVariableName)) { 139 | return $this->session->get($sessionVariableName); 140 | } 141 | 142 | return $default; 143 | } 144 | 145 | /** 146 | * Clear the data with $key from the persistent storage 147 | * 148 | * @param string $key 149 | * @return void 150 | */ 151 | protected function clearPersistentData($key) 152 | { 153 | if (!in_array($key, self::$kSupportedKeys)) { 154 | self::errorLog('Unsupported key passed to clearPersistentData.'); 155 | 156 | return; 157 | } 158 | 159 | $this->session->remove($this->constructSessionVariableName($key)); 160 | } 161 | 162 | /** 163 | * Clear all data from the persistent storage 164 | * 165 | * @return void 166 | */ 167 | protected function clearAllPersistentData() 168 | { 169 | foreach ($this->session->all() as $k => $v) { 170 | if (0 !== strpos($k, $this->prefix)) { 171 | continue; 172 | } 173 | 174 | $this->session->remove($k); 175 | } 176 | } 177 | 178 | protected function constructSessionVariableName($key) 179 | { 180 | return $this->prefix.implode( 181 | '_', 182 | array( 183 | 'fb', 184 | $this->getAppId(), 185 | $key, 186 | ) 187 | ); 188 | } 189 | 190 | private function getState() 191 | { 192 | return $this->getPersistentData('state', null); 193 | } 194 | 195 | private function setState($state) 196 | { 197 | $this->setPersistentData('state', $state); 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DEPRECATED 2 | ========== 3 | 4 | See [HWIOAuthBundle](https://github.com/hwi/HWIOAuthBundle) instead 5 | ------------------------------------------------------------------- 6 | 7 | FOSFacebookBundle 8 | ================= 9 | 10 | This Bundle provides a Symfony2 authentication provider so that users can login to a 11 | Symfony2 application via Facebook. Furthermore via custom user provider support 12 | the Facebook login can also be integrated with other data sources like the 13 | database based solution provided by FOSUserBundle. 14 | 15 | 16 | [![Build Status](https://secure.travis-ci.org/FriendsOfSymfony/FOSFacebookBundle.png?branch=master)](http://travis-ci.org/FriendsOfSymfony/FOSFacebookBundle) 17 | [![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/FriendsOfSymfony/FOSFacebookBundle/badges/quality-score.png?s=15e53e898985730302ecb079408c7640d3b7291b)](https://scrutinizer-ci.com/g/FriendsOfSymfony/FOSFacebookBundle/) 18 | 19 | 20 | Prerequisites 21 | ------------- 22 | 23 | This version (1.3) requires at least Symfony 2.2. If you are using Symfony 2.1, you can use the 1.1 version. 24 | 25 | 26 | Documentation 27 | ------------- 28 | 29 | The bulk of the documentation is stored in the `Resources/doc/index.md` 30 | file in this bundle: 31 | 32 | [Read the Documentation for master](Resources/doc/index.md) 33 | 34 | 35 | License 36 | ------- 37 | 38 | This bundle is under the MIT license. See the complete license in the bundle: 39 | 40 | Resources/meta/LICENSE 41 | -------------------------------------------------------------------------------- /Resources/config/facebook.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | %fos_facebook.app_id% 12 | %fos_facebook.secret% 13 | %fos_facebook.cookie% 14 | %fos_facebook.domain% 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | %fos_facebook.logging% 24 | %fos_facebook.culture% 25 | %fos_facebook.permissions% 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Resources/config/routing.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | FOSFacebookBundle:Facebook:channel 9 | GET 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Resources/config/schema/facebook-1.0.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Resources/config/security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | %fos_facebook.permissions% 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Resources/doc/1-basic-usage.md: -------------------------------------------------------------------------------- 1 | Basic usage 2 | =========== 3 | 4 | 5 | 1. Add the following lines in your composer.json: 6 | 7 | ```json 8 | { 9 | "require": { 10 | "friendsofsymfony/facebook-bundle": "1.3.*" 11 | } 12 | } 13 | ``` 14 | 15 | 2. Run the composer to download the bundle: 16 | ```bash 17 | $ php composer.phar update friendsofsymfony/facebook-bundle 18 | ``` 19 | 20 | 21 | 3. Add this bundle to your application's kernel: 22 | 23 | ```php 24 | // app/ApplicationKernel.php 25 | public function registerBundles() 26 | { 27 | return array( 28 | // ... 29 | new FOS\FacebookBundle\FOSFacebookBundle(), 30 | // ... 31 | ); 32 | } 33 | ``` 34 | 35 | 4. Add the following routes to your application and point them at actual controller actions 36 | 37 | ```yaml 38 | #application/config/routing.yml 39 | _security_check: 40 | pattern: /login_check 41 | _security_logout: 42 | pattern: /logout 43 | fos_facebook_channel: 44 | resource: "@FOSFacebookBundle/Resources/config/routing.xml" 45 | ``` 46 | 47 | ```xml 48 | #application/config/routing.xml 49 | 50 | 51 | 52 | ``` 53 | 54 | 5. Configure the `facebook` service in your config: 55 | ```yaml 56 | # application/config/config.yml 57 | fos_facebook: 58 | alias: facebook 59 | app_id: 123456879 60 | secret: s3cr3t 61 | cookie: true 62 | permissions: [email, user_birthday, user_location] 63 | ``` 64 | 65 | ```xml 66 | # application/config/config.xml 67 | 73 | email 74 | user_birthday 75 | user_location 76 | 77 | ``` 78 | 79 | 80 | 6. Add this configuration if you want to use the `security component`: 81 | 82 | ```yaml 83 | # application/config/security.yml 84 | security: 85 | firewalls: 86 | public: 87 | # since anonymous is allowed users will not be forced to login 88 | pattern: ^/.* 89 | fos_facebook: 90 | app_url: "http://apps.facebook.com/appName/" 91 | server_url: "http://localhost/facebookApp/" 92 | anonymous: true 93 | 94 | access_control: 95 | - { path: ^/secured/.*, role: [IS_AUTHENTICATED_FULLY] } # This is the route secured with fos_facebook 96 | - { path: ^/.*, role: [IS_AUTHENTICATED_ANONYMOUSLY] } 97 | ``` 98 | 99 | You have to add `/secured/` in your routing for this to work. An example would be... 100 | 101 | ```yaml 102 | _facebook_secured: 103 | pattern: /secured/ 104 | defaults: { _controller: AcmeDemoBundle:Welcome:index } 105 | ``` 106 | 107 | 7. Optionally define a custom user provider class and use it as the provider or define path for login: 108 | ```yaml 109 | # application/config/config.yml 110 | security: 111 | providers: 112 | # choose the provider name freely 113 | my_fos_facebook_provider: 114 | id: my.facebook.user # see "Example Custom User Provider using the FOS\UserBundle" chapter further down 115 | 116 | firewalls: 117 | public: 118 | pattern: ^/.* 119 | fos_facebook: 120 | app_url: "http://apps.facebook.com/appName/" 121 | server_url: "http://localhost/facebookApp/" 122 | login_path: /login 123 | check_path: /login_check 124 | default_target_path: / 125 | provider: my_fos_facebook_provider 126 | anonymous: true 127 | 128 | # application/config/config_dev.yml 129 | security: 130 | firewalls: 131 | public: 132 | fos_facebook: 133 | app_url: "http://apps.facebook.com/appName/" 134 | server_url: "http://localhost/facebookApp/app_dev.php/" 135 | ``` 136 | 137 | 8. Optionally use access control to secure specific URLs: 138 | 139 | ```yaml 140 | # application/config/config.yml 141 | security: 142 | # ... 143 | 144 | access_control: 145 | - { path: ^/facebook/, role: [ROLE_FACEBOOK] } 146 | - { path: ^/.*, role: [IS_AUTHENTICATED_ANONYMOUSLY] } 147 | ``` 148 | 149 | The role `ROLE_FACEBOOK` has to be added in your User class (see Acme\MyBundle\Entity\User::setFBData() below). 150 | > Note that the order of access control rules matters! 151 | 152 | 153 | Setting up the JavaScript SDK 154 | ----------------------------- 155 | 156 | A templating helper is included for loading the Facebook JavaScript SDK and 157 | initializing it with parameters from your service container. To setup the 158 | Facebook JavaScript environment, add the following to your layout just after 159 | the opening `body` tag: 160 | ```php 161 | 162 | initialize(array('xfbml' => true, 'fbAsyncInit' => 'onFbInit();')) ?> 163 | ``` 164 | ```html+jinja 165 | 166 | {{ facebook_initialize({'xfbml': true, 'fbAsyncInit': 'onFbInit();'}) }} 167 | ``` 168 | Note that `fbAsyncInit` is a parameter helping you to execute JavaScript within 169 | the function initializing the connection with Facebook, just after the `FB.init();` 170 | call. `onFbInit();` is a JavaScript function defined furthermore to execute functions 171 | which need `FB` initialized. 172 | 173 | If you will be adding XFBML markup to your site you may also declare the 174 | namespace, perhaps in the opening `html` tag: 175 | ```html 176 | 177 | ``` 178 | Include the login button in your templates 179 | ------------------------------------------ 180 | 181 | Add the following code in one of your templates: 182 | ```php 183 | 184 | loginButton(array('autologoutlink' => true)) ?> 185 | ``` 186 | ```jinja 187 | {# inside a twig template #} 188 | {{ facebook_login_button({'autologoutlink': true}) }} 189 | ``` 190 | If you want customize the login button, you can set these parameters: 191 | 192 | - label : The text that shows in the button. 193 | - showFaces : Specifies whether to show faces underneath the Login button. 194 | - width : The width of the plugin in pixels. Default width: 200px. 195 | - maxRows : The maximum number of rows of profile pictures to display. Default value: 1. 196 | - scope : A comma separated list of extended permissions. 197 | - registrationUrl : Registration page url. If the user has not registered for your site, they will be redirected to the URL you specify in the registrationUrl parameter. 198 | - size : Different sized buttons: small, medium, large, xlarge (default: medium). 199 | - onlogin : Set a URL to be redirected after successful login 200 | 201 | 202 | Note that with this approach, only the login and connecting with Facebook will 203 | be handled. The step of logging in (and out) the user into your Symfony2 application 204 | still needs to be triggered. To do this you will in most cases simply subscribe 205 | to the `auth.statusChange` event and then redirect to the `check_path`: 206 | 207 | ```html+jinja 208 | 225 | ``` 226 | 227 | Note that we need to include this code before the initialization of the Facebook 228 | Javascript SDK Initialization in order to have the onFbInit() event listener 229 | correctly triggered (in this case between the beginning of the 'body' tag and 230 | the templating helper provided by this bundle) 231 | 232 | We wait 500ms before redirecting to let the browser deal with the Facebook cookie. 233 | You can avoid this step, but you might get this error message: 234 | *"The Facebook user could not be retrieved from the session."* 235 | 236 | The `_security_check` route would need to point to a `/login_check` pattern 237 | to match the above configuration. 238 | 239 | Next: [Integration with FOSUserBundle](2-integration-with-fosuserbundle.md) 240 | -------------------------------------------------------------------------------- /Resources/doc/2-integration-with-fosuserbundle.md: -------------------------------------------------------------------------------- 1 | Integration with FOSUserBundle 2 | ------------------------------ 3 | 4 | If you still want to use the FOSUserBundle form login, add the "chain_provider" configuration parameter to your ```security.yml```: 5 | 6 | ```yaml 7 | providers: 8 | chain_provider: 9 | chain: 10 | providers: [fos_userbundle, my_fos_facebook_provider] 11 | fos_user_bundle: ... 12 | my_fos_facebook_provider: 13 | id: my.facebook.user 14 | ``` 15 | 16 | You need to have separate ```login_path``` and ```check_path```'s than your ```FOSUserBundle``` firewall. In the ```security.yml``` be sure it looks something like this: 17 | 18 | ```yaml 19 | firewalls: 20 | secured_area: 21 | fos_facebook: 22 | login_path: _security_login 23 | check_path: _security_check 24 | ``` 25 | 26 | Both `login_path` and `check_path` need to be the routes that are defined in ```routing.yml```: 27 | 28 | ```yaml 29 | _security_login: 30 | pattern: /loginfb 31 | 32 | _security_check: 33 | pattern: /loginfb_check 34 | ``` 35 | 36 | This requires adding a service for the custom user provider, which is then set 37 | to the provider id in the "provider" section in ```config.yml```: 38 | 39 | ```yaml 40 | services: 41 | my.facebook.user: 42 | class: Acme\MyBundle\Security\User\Provider\FacebookProvider 43 | arguments: 44 | facebook: "@fos_facebook.api" 45 | userManager: "@fos_user.user_manager" 46 | validator: "@validator" 47 | ``` 48 | 49 | ```php 50 | facebook = $facebook; 86 | $this->userManager = $userManager; 87 | $this->validator = $validator; 88 | } 89 | 90 | public function supportsClass($class) 91 | { 92 | return $this->userProvider->supportsClass($class); 93 | } 94 | 95 | public function findUserByFbId($fbId) 96 | { 97 | return $this->userManager->findUserBy(array('facebookId' => $fbId)); 98 | } 99 | 100 | public function loadUserByUsername($username) 101 | { 102 | $user = $this->findUserByFbId($username); 103 | 104 | try { 105 | $fbdata = $this->facebook->api('/me'); 106 | } catch (FacebookApiException $e) { 107 | $fbdata = null; 108 | } 109 | 110 | if (!empty($fbdata)) { 111 | if (empty($user)) { 112 | $user = $this->userManager->createUser(); 113 | $user->setEnabled(true); 114 | $user->setPassword(''); 115 | } 116 | 117 | // TODO use http://developers.facebook.com/docs/api/realtime 118 | $user->setFBData($fbdata); 119 | 120 | if (count($this->validator->validate($user, 'Facebook'))) { 121 | // TODO: the user was found obviously, but doesnt match our expectations, do something smart 122 | throw new UsernameNotFoundException('The facebook user could not be stored'); 123 | } 124 | $this->userManager->updateUser($user); 125 | } 126 | 127 | if (empty($user)) { 128 | throw new UsernameNotFoundException('The user is not authenticated on facebook'); 129 | } 130 | 131 | return $user; 132 | } 133 | 134 | public function refreshUser(UserInterface $user) 135 | { 136 | if (!$this->supportsClass(get_class($user)) || !$user->getFacebookId()) { 137 | throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); 138 | } 139 | 140 | return $this->loadUserByUsername($user->getFacebookId()); 141 | } 142 | } 143 | ``` 144 | 145 | Finally, one also needs to add getFacebookId() and setFBData() methods to the User model. 146 | The following example also adds "firstname" and "lastname" properties, using the Doctrine ORM: 147 | 148 | ```php 149 | facebookId, parent::serialize())); 182 | } 183 | 184 | public function unserialize($data) 185 | { 186 | list($this->facebookId, $parentData) = unserialize($data); 187 | parent::unserialize($parentData); 188 | } 189 | 190 | /** 191 | * @return string 192 | */ 193 | public function getFirstname() 194 | { 195 | return $this->firstname; 196 | } 197 | 198 | /** 199 | * @param string $firstname 200 | */ 201 | public function setFirstname($firstname) 202 | { 203 | $this->firstname = $firstname; 204 | } 205 | 206 | /** 207 | * @return string 208 | */ 209 | public function getLastname() 210 | { 211 | return $this->lastname; 212 | } 213 | 214 | /** 215 | * @param string $lastname 216 | */ 217 | public function setLastname($lastname) 218 | { 219 | $this->lastname = $lastname; 220 | } 221 | 222 | /** 223 | * Get the full name of the user (first + last name) 224 | * @return string 225 | */ 226 | public function getFullName() 227 | { 228 | return $this->getFirstname() . ' ' . $this->getLastname(); 229 | } 230 | 231 | /** 232 | * @param string $facebookId 233 | * @return void 234 | */ 235 | public function setFacebookId($facebookId) 236 | { 237 | $this->facebookId = $facebookId; 238 | $this->setUsername($facebookId); 239 | } 240 | 241 | /** 242 | * @return string 243 | */ 244 | public function getFacebookId() 245 | { 246 | return $this->facebookId; 247 | } 248 | 249 | /** 250 | * @param Array 251 | */ 252 | public function setFBData($fbdata) 253 | { 254 | if (isset($fbdata['id'])) { 255 | $this->setFacebookId($fbdata['id']); 256 | $this->addRole('ROLE_FACEBOOK'); 257 | } 258 | if (isset($fbdata['first_name'])) { 259 | $this->setFirstname($fbdata['first_name']); 260 | } 261 | if (isset($fbdata['last_name'])) { 262 | $this->setLastname($fbdata['last_name']); 263 | } 264 | if (isset($fbdata['email'])) { 265 | $this->setEmail($fbdata['email']); 266 | } 267 | } 268 | } 269 | ``` 270 | 271 | Next: [Additional resources](3-another-resources.md) 272 | -------------------------------------------------------------------------------- /Resources/doc/3-another-resources.md: -------------------------------------------------------------------------------- 1 | Additional Resources 2 | ==================== 3 | 4 | 5 | Avoiding redirect to Facebook login page 6 | ---------------------------------------- 7 | 8 | When you're using only Facebook as your firewall and a user goes to a protected page on your application 9 | without being logged in, they will be redirected to the Facebook login page. 10 | If you want to avoid this behavior and redirect the user to another page, you can set this option on the ```security.yml```, as the example above: 11 | 12 | ```yaml 13 | firewalls: 14 | public: 15 | ... 16 | fos_facebook: 17 | ... 18 | redirect_to_facebook_login: false 19 | ``` 20 | 21 | When you set this option, any request not authenticated will be redirected to the default login page. 22 | 23 | Next: [Example Server-Side Facebook Login using Mobile Apps](4-example-server-side-facebook-login-using-mobile-apps.md) 24 | -------------------------------------------------------------------------------- /Resources/doc/4-example-server-side-facebook-login-using-mobile-apps.md: -------------------------------------------------------------------------------- 1 | Example Server-Side Facebook Login using Mobile Apps 2 | ---------------------------------------------------- 3 | 4 | If you use the JavaScript SDK to login by web, the normal flow would be as follows: 5 | 6 | 1. Click Facebook login button from your page. 7 | 2. It will go to Facebook OAuth API 8 | 9 | ``` 10 | https://www.facebook.com/dialog/oauth?client_id=&redirect_uri=&state=&scope= 11 | ``` 12 | 3. After user accepts the Facebook application, it will go back to your site's `redirect_uri`: 13 | 14 | ``` 15 | https://localhost/facebookApp/login_check?state=&code=#_=_ 16 | ``` 17 | 18 | This flow is also described by [Technical Guide from Facebook Developers](https://developers.facebook.com/docs/howtos/login/server-side-login/). 19 | 20 | However, if you are developing server-side Facebook login using mobile apps for 21 | Apple iOS or Google Android, their respective SDKs obtain access tokens from 22 | mobile devices. In this case, the only API call required from mobile side is: 23 | 24 | ``` 25 | https://localhost/facebookApp/login_check?access_token= 26 | ``` 27 | 28 | __ATTENTION__: Since an access token provides secure access to Facebook APIs on 29 | behalf of the user, we must always pass the token using HTTPS. Please read 30 | the section Sharing of Access Tokens from [Facebook Developers](https://developers.facebook.com/docs/concepts/login/access-tokens-and-types/) 31 | before using this mechanism. 32 | -------------------------------------------------------------------------------- /Resources/doc/index.md: -------------------------------------------------------------------------------- 1 | Getting started with FOSFacebookBundle 2 | ==================================== 3 | 4 | 5 | To use FOSFacebookBundle, it's important to understand the Facebook login process, which requires the following steps: 6 | 7 | 1. the user must be logged into Facebook 8 | 2. the user must connect his Facebook account to your app 9 | 3. once the user has done 1. and 2., your app must trigger the login 10 | 11 | Before continuing, you should go in your application settings on Facebook Developers page and select the option "OAuth Migration". You will have problems if you don't enable it. 12 | 13 | To handle authentication, you have two options: 14 | 15 | * Use the JavaScript SDK to authenticate the user on the client side; 16 | * Let FOSFacebookBundle redirect to the Facebook login page 17 | 18 | Note that the later happens automatically if the first provider in your first 19 | firewall configuration is configured to FOSFacebookBundle and the user access 20 | a page that requires authentication without being authenticated. 21 | 22 | Before you go ahead and use FOSFacebookBundle you should considerer take a look at Facebook and Symfony SecurityBundle documentation: 23 | 24 | * [Facebook documentation](https://developers.facebook.com/docs/guides/web/) 25 | * [SecurityBundle documentation](http://symfony.com/doc/current/book/security.html) 26 | 27 | 28 | 29 | Usage guide 30 | ----------- 31 | 32 | 1. [Basic usage](1-basic-usage.md) 33 | 2. [Integration with FOSUserBundle](2-integration-with-fosuserbundle.md) 34 | 3. [Additional resources](3-another-resources.md) 35 | 4. [Example Server-Side Facebook Login using Mobile Apps](4-example-server-side-facebook-login-using-mobile-apps.md) 36 | -------------------------------------------------------------------------------- /Resources/meta/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Kris Wallsmith 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Resources/views/initialize.html.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 29 | -------------------------------------------------------------------------------- /Resources/views/initialize.html.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if not async %} 3 | 4 | {% endif %} 5 | 24 | -------------------------------------------------------------------------------- /Resources/views/loginButton.html.php: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Resources/views/loginButton.html.twig: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Security/Authentication/Provider/FacebookProvider.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Security\Authentication\Provider; 13 | 14 | use FOS\FacebookBundle\Security\User\UserManagerInterface; 15 | 16 | use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; 17 | 18 | use Symfony\Component\Security\Core\User\UserInterface; 19 | use Symfony\Component\Security\Core\User\UserCheckerInterface; 20 | use Symfony\Component\Security\Core\User\UserProviderInterface; 21 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 22 | use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 23 | use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; 24 | 25 | use FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken; 26 | 27 | class FacebookProvider implements AuthenticationProviderInterface 28 | { 29 | /** 30 | * @var \BaseFacebook 31 | */ 32 | protected $facebook; 33 | protected $providerKey; 34 | protected $userProvider; 35 | protected $userChecker; 36 | protected $createIfNotExists; 37 | 38 | public function __construct($providerKey, \BaseFacebook $facebook, UserProviderInterface $userProvider = null, UserCheckerInterface $userChecker = null, $createIfNotExists = false) 39 | { 40 | if (null !== $userProvider && null === $userChecker) { 41 | throw new \InvalidArgumentException('$userChecker cannot be null, if $userProvider is not null.'); 42 | } 43 | 44 | if ($createIfNotExists && !$userProvider instanceof UserManagerInterface) { 45 | throw new \InvalidArgumentException('The $userProvider must implement UserManagerInterface if $createIfNotExists is true.'); 46 | } 47 | 48 | $this->providerKey = $providerKey; 49 | $this->facebook = $facebook; 50 | $this->userProvider = $userProvider; 51 | $this->userChecker = $userChecker; 52 | $this->createIfNotExists = $createIfNotExists; 53 | } 54 | 55 | public function authenticate(TokenInterface $token) 56 | { 57 | if (!$this->supports($token)) { 58 | return null; 59 | } 60 | 61 | $user = $token->getUser(); 62 | if ($user instanceof UserInterface) { 63 | $this->userChecker->checkPostAuth($user); 64 | 65 | $newToken = new FacebookUserToken($this->providerKey, $user, $user->getRoles(), $token->getAccessToken()); 66 | $newToken->setAttributes($token->getAttributes()); 67 | 68 | return $newToken; 69 | } 70 | 71 | if (!is_null($token->getAccessToken())) { 72 | $this->facebook->setAccessToken($token->getAccessToken()); 73 | } 74 | 75 | if ($uid = $this->facebook->getUser()) { 76 | $newToken = $this->createAuthenticatedToken($uid,$token->getAccessToken()); 77 | $newToken->setAttributes($token->getAttributes()); 78 | 79 | return $newToken; 80 | } 81 | 82 | throw new AuthenticationException('The Facebook user could not be retrieved from the session.'); 83 | } 84 | 85 | public function supports(TokenInterface $token) 86 | { 87 | return $token instanceof FacebookUserToken && $this->providerKey === $token->getProviderKey(); 88 | } 89 | 90 | protected function createAuthenticatedToken($uid, $accessToken = null) 91 | { 92 | if (null === $this->userProvider) { 93 | return new FacebookUserToken($this->providerKey, $uid, array(), $accessToken); 94 | } 95 | 96 | try { 97 | $user = $this->userProvider->loadUserByUsername($uid); 98 | if ($user instanceof UserInterface) { 99 | $this->userChecker->checkPostAuth($user); 100 | } 101 | } catch (UsernameNotFoundException $ex) { 102 | if (!$this->createIfNotExists) { 103 | throw $ex; 104 | } 105 | 106 | $user = $this->userProvider->createUserFromUid($uid); 107 | } 108 | 109 | if (!$user instanceof UserInterface) { 110 | throw new AuthenticationException('User provider did not return an implementation of user interface.'); 111 | } 112 | 113 | return new FacebookUserToken($this->providerKey, $user, $user->getRoles(), $accessToken); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /Security/Authentication/Token/FacebookUserToken.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Security\Authentication\Token; 13 | 14 | use Symfony\Component\Security\Core\Authentication\Token\AbstractToken; 15 | 16 | class FacebookUserToken extends AbstractToken 17 | { 18 | private $providerKey; 19 | 20 | protected $accessToken; 21 | 22 | public function __construct($providerKey, $uid = '', array $roles = array(), $accessToken = null) 23 | { 24 | parent::__construct($roles); 25 | 26 | $this->setUser($uid); 27 | 28 | if (!empty($uid)) { 29 | $this->setAuthenticated(true); 30 | } 31 | 32 | $this->providerKey = $providerKey; 33 | 34 | $this->accessToken = $accessToken; 35 | } 36 | 37 | public function getCredentials() 38 | { 39 | return ''; 40 | } 41 | 42 | public function getProviderKey() 43 | { 44 | return $this->providerKey; 45 | } 46 | 47 | public function getAccessToken() 48 | { 49 | return $this->accessToken; 50 | } 51 | 52 | public function serialize() 53 | { 54 | return serialize(array($this->providerKey, parent::serialize())); 55 | } 56 | 57 | public function unserialize($str) 58 | { 59 | list($this->providerKey, $parentStr) = unserialize($str); 60 | parent::unserialize($parentStr); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Security/EntryPoint/FacebookAuthenticationEntryPoint.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Security\EntryPoint; 13 | 14 | use Symfony\Component\HttpFoundation\ParameterBag; 15 | use Symfony\Component\HttpFoundation\Request; 16 | use Symfony\Component\HttpFoundation\Response; 17 | use Symfony\Component\HttpFoundation\RedirectResponse; 18 | use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; 19 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 20 | 21 | /** 22 | * FacebookAuthenticationEntryPoint starts an authentication via Facebook. 23 | * 24 | * @author Thomas Adam 25 | */ 26 | class FacebookAuthenticationEntryPoint implements AuthenticationEntryPointInterface 27 | { 28 | protected $facebook; 29 | protected $options; 30 | protected $permissions; 31 | 32 | /** 33 | * Constructor 34 | * 35 | * @param BaseFacebook $facebook 36 | * @param array $options 37 | */ 38 | public function __construct(\BaseFacebook $facebook, array $options = array(), array $permissions = array()) 39 | { 40 | $this->facebook = $facebook; 41 | $this->permissions = $permissions; 42 | $this->options = new ParameterBag($options); 43 | } 44 | 45 | /** 46 | * {@inheritdoc} 47 | */ 48 | public function start(Request $request, AuthenticationException $authException = null) 49 | { 50 | 51 | $redirect_to_facebook = $this->options->get('redirect_to_facebook_login'); 52 | if ($redirect_to_facebook == false) { 53 | $loginPath = $this->options->get('login_path'); 54 | 55 | return new RedirectResponse($loginPath); 56 | } 57 | 58 | $redirect_uri = $request->getUriForPath($this->options->get('check_path', '')); 59 | if ($this->options->get('server_url') && $this->options->get('app_url')) { 60 | $redirect_uri = str_replace($this->options->get('server_url'), $this->options->get('app_url'), $redirect_uri); 61 | } 62 | 63 | $loginUrl = $this->facebook->getLoginUrl( 64 | array( 65 | 'display' => $this->options->get('display', 'page'), 66 | 'scope' => implode(',', $this->permissions), 67 | 'redirect_uri' => $redirect_uri, 68 | )); 69 | 70 | if ($this->options->get('server_url') && $this->options->get('app_url')) { 71 | return new Response(''); 72 | } 73 | 74 | return new RedirectResponse($loginUrl); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Security/Firewall/FacebookListener.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Security\Firewall; 13 | 14 | use FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken; 15 | use Symfony\Component\Security\Http\Firewall\AbstractAuthenticationListener; 16 | use Symfony\Component\HttpFoundation\Request; 17 | 18 | /** 19 | * Facebook authentication listener. 20 | */ 21 | class FacebookListener extends AbstractAuthenticationListener 22 | { 23 | protected function attemptAuthentication(Request $request) 24 | { 25 | $accessToken = $request->get('access_token'); 26 | 27 | return $this->authenticationManager->authenticate(new FacebookUserToken($this->providerKey, '', array(), $accessToken)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Security/User/UserManagerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Templating\Helper; 13 | 14 | use Symfony\Component\Templating\Helper\Helper; 15 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; 16 | use Symfony\Component\Templating\EngineInterface; 17 | 18 | class FacebookHelper extends Helper 19 | { 20 | protected $templating; 21 | protected $logging; 22 | protected $urlGenerator; 23 | protected $culture; 24 | protected $scope; 25 | protected $facebook; 26 | 27 | public function __construct(EngineInterface $templating, \BaseFacebook $facebook, UrlGeneratorInterface $urlGenerator, $logging = true, $culture = 'en_US', array $scope = array()) 28 | { 29 | $this->templating = $templating; 30 | $this->logging = $logging; 31 | $this->urlGenerator = $urlGenerator; 32 | $this->culture = $culture; 33 | $this->scope = $scope; 34 | $this->facebook = $facebook; 35 | } 36 | 37 | /** 38 | * Returns the HTML necessary for initializing the JavaScript SDK. 39 | * 40 | * The default template includes the following parameters: 41 | * 42 | * * async 43 | * * fbAsyncInit 44 | * * appId 45 | * * xfbml 46 | * * oauth 47 | * * status 48 | * * cookie 49 | * * logging 50 | * * culture 51 | * 52 | * @param array $parameters An array of parameters for the initialization template 53 | * @param string $name A template name 54 | * 55 | * @return string An HTML string 56 | */ 57 | public function initialize($parameters = array(), $name = null) 58 | { 59 | $name = $name ?: 'FOSFacebookBundle::initialize.html.php'; 60 | 61 | return $this->templating->render($name, $parameters + array( 62 | 'async' => true, 63 | 'fbAsyncInit' => '', 64 | 'appId' => (string) $this->facebook->getAppId(), 65 | 'xfbml' => false, 66 | 'oauth' => true, 67 | 'status' => false, 68 | 'cookie' => true, 69 | 'logging' => $this->logging, 70 | 'channelUrl' => $this->urlGenerator->generate('fos_facebook_channel', array(), true), 71 | 'culture' => $this->culture, 72 | )); 73 | } 74 | 75 | public function loginButton($parameters = array(), $name = null) 76 | { 77 | $name = $name ?: 'FOSFacebookBundle::loginButton.html.php'; 78 | 79 | return $this->templating->render($name, $parameters + array( 80 | 'autologoutlink' => 'false', 81 | 'label' => '', 82 | 'showFaces' => 'false', 83 | 'width' => '', 84 | 'maxRows' => '1', 85 | 'scope' => implode(',', $this->scope), 86 | 'registrationUrl' => '', 87 | 'size' => 'medium', 88 | 'onlogin' => '' 89 | )); 90 | } 91 | 92 | public function logoutUrl($parameters = array(), $name = null) 93 | { 94 | return $this->facebook->getLogoutUrl($parameters); 95 | } 96 | 97 | /** 98 | * @codeCoverageIgnore 99 | */ 100 | public function getName() 101 | { 102 | return 'facebook'; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Tests/Controller/FacebookControllerTest.php: -------------------------------------------------------------------------------- 1 | request('GET', '/channel.html'); 13 | $response = $client->getResponse(); 14 | $this->assertEquals(200, $response->getStatusCode()); 15 | $maxAge = static::$kernel->getContainer()->getParameter('fos_facebook.channel.expire'); 16 | $this->assertEquals($maxAge, $response->getMaxAge()); 17 | } 18 | } -------------------------------------------------------------------------------- /Tests/DependencyInjection/ConfigurationTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\DependencyInjection; 13 | 14 | use FOS\FacebookBundle\DependencyInjection\Configuration; 15 | 16 | class ConfigurationTest extends \PHPUnit_Framework_TestCase 17 | { 18 | public function testThatCanGetConfigTreeBuilder() 19 | { 20 | $configuration = new Configuration(); 21 | $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\TreeBuilder', $configuration->getConfigTreeBuilder()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/FOSFacebookExtensionTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\DependencyInjection; 13 | 14 | use FOS\FacebookBundle\DependencyInjection\FOSFacebookExtension; 15 | 16 | class FOSFacebookExtensionTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @covers FOS\FacebookBundle\DependencyInjection\FOSFacebookExtension::load 20 | */ 21 | public function testLoadFailure() 22 | { 23 | $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder') 24 | ->disableOriginalConstructor() 25 | ->getMock(); 26 | 27 | $extension = $this->getMockBuilder('FOS\\FacebookBundle\\DependencyInjection\\FOSFacebookExtension') 28 | ->getMock(); 29 | 30 | $extension->load(array(array()), $container); 31 | } 32 | 33 | /** 34 | * @covers FOS\FacebookBundle\DependencyInjection\FOSFacebookExtension::load 35 | */ 36 | public function testLoadSetParameters() 37 | { 38 | $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder') 39 | ->disableOriginalConstructor() 40 | ->getMock(); 41 | 42 | $parameterBag = $this->getMockBuilder('Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag') 43 | ->disableOriginalConstructor() 44 | ->getMock(); 45 | 46 | $parameterBag 47 | ->expects($this->any()) 48 | ->method('add'); 49 | 50 | $container 51 | ->expects($this->any()) 52 | ->method('getParameterBag') 53 | ->will($this->returnValue($parameterBag)); 54 | 55 | $extension = new FOSFacebookExtension(); 56 | $configs = array( 57 | array('class' => array('api' => 'foo')), 58 | array('app_id' => 'foo'), 59 | array('secret' => 'foo'), 60 | array('cookie' => 'foo'), 61 | array('domain' => 'foo'), 62 | array('logging' => 'foo'), 63 | array('culture' => 'foo'), 64 | array('channel' => array('expire' => 100)), 65 | array('permissions' => array('email')), 66 | ); 67 | $extension->load($configs, $container); 68 | } 69 | 70 | /** 71 | * @covers FOS\FacebookBundle\DependencyInjection\FOSFacebookExtension::load 72 | */ 73 | public function testThatCanSetContainerAlias() 74 | { 75 | $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder') 76 | ->disableOriginalConstructor() 77 | ->getMock(); 78 | $container->expects($this->once()) 79 | ->method('setAlias') 80 | ->with($this->equalTo('facebook_alias'), $this->equalTo('fos_facebook.api')); 81 | 82 | $configs = array( 83 | array('class' => array('api' => 'foo')), 84 | array('app_id' => 'foo'), 85 | array('secret' => 'foo'), 86 | array('cookie' => 'foo'), 87 | array('domain' => 'foo'), 88 | array('logging' => 'foo'), 89 | array('culture' => 'foo'), 90 | array('channel' => array('expire' => 100)), 91 | array('permissions' => array('email')), 92 | array('alias' => 'facebook_alias') 93 | ); 94 | $extension = new FOSFacebookExtension(); 95 | $extension->load($configs, $container); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Tests/DependencyInjection/Security/Factory/FacebookFactoryTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\DependencyInjection\Security\Factory; 13 | 14 | use FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory; 15 | 16 | class FacebookFactoryTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @var FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory 20 | */ 21 | private $factory = null; 22 | 23 | public function setUp() 24 | { 25 | $this->factory = new FacebookFactory(); 26 | } 27 | 28 | public function testThatCanGetPosition() 29 | { 30 | $this->assertEquals('pre_auth', $this->factory->getPosition()); 31 | } 32 | 33 | public function testThatCanGetKey() 34 | { 35 | $this->assertEquals('fos_facebook', $this->factory->getKey()); 36 | } 37 | 38 | /** 39 | * @covers FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory::createAuthProvider 40 | */ 41 | public function testThatCreateUserAuthProviderWhenDefinedInConfig() 42 | { 43 | $idsArray = $this->facebookFactoryCreate(array('provider' => true, 'remember_me' => false, 'create_user_if_not_exists' => false)); 44 | $this->assertEquals('fos_facebook.auth.l3l0', $idsArray[0]); 45 | } 46 | 47 | /** 48 | * @covers FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory::createAuthProvider 49 | */ 50 | public function testThatCreateUserAuthProviderEvenWhenNotDefinedInConfig() 51 | { 52 | $idsArray = $this->facebookFactoryCreate(array('remember_me' => false)); 53 | $this->assertEquals('fos_facebook.auth.l3l0', $idsArray[0]); 54 | } 55 | 56 | /** 57 | * @covers FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory::createAuthProvider 58 | */ 59 | public function testThatCreateDifferentUserAuthProviderForDifferentFirewalls() 60 | { 61 | $idsArray = $this->facebookFactoryCreate(array('remember_me' => false)); 62 | $this->assertEquals('fos_facebook.auth.l3l0', $idsArray[0]); 63 | 64 | $idsArray = $this->facebookFactoryCreate(array('remember_me' => false), 'main'); 65 | $this->assertEquals('fos_facebook.auth.main', $idsArray[0]); 66 | } 67 | 68 | /** 69 | * @covers FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory::createEntryPoint 70 | */ 71 | public function testThatCreateEntryPoint() 72 | { 73 | $idsArray = $this->facebookFactoryCreate(array('remember_me' => false)); 74 | $this->assertEquals('fos_facebook.security.authentication.entry_point.l3l0', $idsArray[2]); 75 | } 76 | 77 | /** 78 | * @covers FOS\FacebookBundle\DependencyInjection\Security\Factory\FacebookFactory::getListenerId 79 | */ 80 | public function testThatListenerForListenerId() 81 | { 82 | $idsArray = $this->facebookFactoryCreate(array('remember_me' => false)); 83 | $this->assertEquals('fos_facebook.security.authentication.listener.l3l0', $idsArray[1]); 84 | } 85 | 86 | /** 87 | * @param array $config 88 | * @return array 89 | */ 90 | private function facebookFactoryCreate($config = array(), $id = 'l3l0') 91 | { 92 | $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition', array('addArgument', 'replaceArgument')); 93 | $definition->expects($this->any()) 94 | ->method('replaceArgument') 95 | ->will($this->returnValue($definition)); 96 | $definition->expects($this->any()) 97 | ->method('addArgument') 98 | ->will($this->returnValue($definition)); 99 | $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder', array('setDefinition')); 100 | $container->expects($this->any()) 101 | ->method('setDefinition') 102 | ->will($this->returnValue($definition)); 103 | 104 | return $this->factory->create($container, $id, $config, 'l3l0.user.provider', null); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Tests/FacebookApiException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | class FacebookApiException extends \Exception 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /Tests/Fixtures/App/app/AppKernel.php: -------------------------------------------------------------------------------- 1 | load(__DIR__.'/config/config.yml'); 21 | } 22 | 23 | /** 24 | * @return string 25 | */ 26 | public function getCacheDir() 27 | { 28 | return sys_get_temp_dir().'/FOSFacebookBundle/cache'; 29 | } 30 | 31 | /** 32 | * @return string 33 | */ 34 | public function getLogDir() 35 | { 36 | return sys_get_temp_dir().'/FOSFacebookBundle/logs'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Tests/Fixtures/App/app/config/config.yml: -------------------------------------------------------------------------------- 1 | framework: 2 | secret: FOSFacebookBundle 3 | router: { resource: "%kernel.root_dir%/config/routing.yml" } 4 | templating: { engines: ['twig'] } #assets_version: SomeVersionScheme 5 | form: false 6 | csrf_protection: false 7 | default_locale: en 8 | translator: { fallback: en } 9 | profiler: { only_exceptions: false } 10 | test: ~ 11 | session: 12 | storage_id: session.storage.filesystem 13 | 14 | fos_facebook: 15 | alias: facebook 16 | app_id: 123456879 17 | secret: s3cr3t 18 | cookie: true 19 | permissions: [email] 20 | -------------------------------------------------------------------------------- /Tests/Fixtures/App/app/config/routing.yml: -------------------------------------------------------------------------------- 1 | fos_facebook_bundle: 2 | resource: "@FOSFacebookBundle/Resources/config/routing.xml" 3 | -------------------------------------------------------------------------------- /Tests/Kernel.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests; 13 | 14 | use Symfony\Component\HttpKernel\Kernel as BaseKernel; 15 | use Symfony\Component\Config\Loader\LoaderInterface; 16 | use Symfony\Component\Filesystem\Filesystem; 17 | use Symfony\Component\ClassLoader\UniversalClassLoader; 18 | 19 | class Kernel extends BaseKernel 20 | { 21 | public function __construct() 22 | { 23 | $this->tmpDir = sys_get_temp_dir().'/sf2_'.rand(1, 9999); 24 | if (!is_dir($this->tmpDir)) { 25 | if (false === @mkdir($this->tmpDir)) { 26 | die(sprintf('Unable to create a temporary directory (%s)', $this->tmpDir)); 27 | } 28 | } elseif (!is_writable($this->tmpDir)) { 29 | die(sprintf('Unable to write in a temporary directory (%s)', $this->tmpDir)); 30 | } 31 | 32 | parent::__construct('env', true); 33 | 34 | require_once __DIR__.'/FacebookApiException.php'; 35 | 36 | $loader = new UniversalClassLoader(); 37 | $loader->loadClass('\FacebookApiException'); 38 | $loader->register(); 39 | } 40 | 41 | public function __destruct() 42 | { 43 | $fs = new Filesystem(); 44 | $fs->remove($this->tmpDir); 45 | } 46 | 47 | public function registerRootDir() 48 | { 49 | return $this->tmpDir; 50 | } 51 | 52 | public function registerBundles() 53 | { 54 | return array( 55 | new \Symfony\Bundle\FrameworkBundle\FrameworkBundle(), 56 | ); 57 | } 58 | 59 | public function registerBundleDirs() 60 | { 61 | return array( 62 | ); 63 | } 64 | 65 | public function registerContainerConfiguration(LoaderInterface $loader) 66 | { 67 | $loader->load(function ($container) { 68 | $container->setParameter('kernel.compiled_classes', array()); 69 | }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Tests/Security/Authentication/Provider/FacebookProviderTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\Security\Authentication\Provider; 13 | 14 | use FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken; 15 | 16 | use FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider; 17 | use Symfony\Component\Security\Core\Exception\AuthenticationException; 18 | 19 | class FacebookProviderTest extends \PHPUnit_Framework_TestCase 20 | { 21 | /** 22 | * @expectedException \InvalidArgumentException 23 | */ 24 | public function testThatUserCheckerCannotBeNullWhenUserProviderIsNotNull() 25 | { 26 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 27 | ->disableOriginalConstructor() 28 | ->getMock(); 29 | new FacebookProvider('main', $facebookMock, $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface')); 30 | } 31 | 32 | /** 33 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::authenticate 34 | */ 35 | public function testThatCannotAuthenticateWhenTokenIsNotFacebookUserToken() 36 | { 37 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 38 | ->disableOriginalConstructor() 39 | ->getMock(); 40 | $facebookProvider = new FacebookProvider('main', $facebookMock); 41 | $this->assertNull($facebookProvider->authenticate($this->getMock('Symfony\Component\Security\Core\Authentication\Token\TokenInterface'))); 42 | } 43 | 44 | /** 45 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::authenticate 46 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::supports 47 | */ 48 | public function testThatCannotAuthenticateWhenTokenFromOtherFirewall() 49 | { 50 | $providerKeyForProvider = 'main'; 51 | $providerKeyForToken = 'connect'; 52 | 53 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 54 | ->disableOriginalConstructor() 55 | ->getMock(); 56 | $facebookProvider = new FacebookProvider($providerKeyForProvider, $facebookMock); 57 | 58 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getProviderKey'), array($providerKeyForToken)); 59 | $tokenMock->expects($this->any()) 60 | ->method('getProviderKey') 61 | ->will($this->returnValue($providerKeyForToken)); 62 | 63 | $this->assertFalse($facebookProvider->supports($tokenMock)); 64 | $this->assertNull($facebookProvider->authenticate($tokenMock)); 65 | } 66 | 67 | /** 68 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::authenticate 69 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::supports 70 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::createAuthenticatedToken 71 | */ 72 | public function testThatCanAuthenticateUserWithoutUserProvider() 73 | { 74 | $providerKey = 'main'; 75 | 76 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 77 | ->disableOriginalConstructor() 78 | ->setMethods(array('getUser')) 79 | ->getMock(); 80 | $facebookMock->expects($this->once()) 81 | ->method('getUser') 82 | ->will($this->returnValue('123')); 83 | 84 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock); 85 | 86 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getAttributes', 'getProviderKey'), array($providerKey)); 87 | $tokenMock->expects($this->once()) 88 | ->method('getAttributes') 89 | ->will($this->returnValue(array())); 90 | $tokenMock->expects($this->any()) 91 | ->method('getProviderKey') 92 | ->will($this->returnValue($providerKey)); 93 | 94 | $this->assertTrue($facebookProvider->supports($tokenMock)); 95 | $this->assertEquals('123', $facebookProvider->authenticate($tokenMock)->getUser()); 96 | } 97 | 98 | /** 99 | * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException 100 | */ 101 | public function testThatCannotAuthenticateWhenUserProviderThrowsAuthenticationException() 102 | { 103 | $providerKey = 'main'; 104 | 105 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 106 | ->disableOriginalConstructor() 107 | ->setMethods(array('getUser')) 108 | ->getMock(); 109 | $facebookMock->expects($this->once()) 110 | ->method('getUser') 111 | ->will($this->returnValue('123')); 112 | 113 | $userProviderMock = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); 114 | $userProviderMock->expects($this->once()) 115 | ->method('loadUserByUsername') 116 | ->with('123') 117 | ->will($this->throwException(new AuthenticationException('test'))); 118 | 119 | $userCheckerMock = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); 120 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getProviderKey'), array($providerKey)); 121 | $tokenMock->expects($this->any()) 122 | ->method('getProviderKey') 123 | ->will($this->returnValue($providerKey)); 124 | 125 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock, $userProviderMock, $userCheckerMock); 126 | $facebookProvider->authenticate($tokenMock); 127 | } 128 | 129 | /** 130 | * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException 131 | */ 132 | public function testThatCannotAuthenticateWhenUserProviderDoesNotReturnUserInterface() 133 | { 134 | $providerKey = 'main'; 135 | 136 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 137 | ->disableOriginalConstructor() 138 | ->setMethods(array('getUser')) 139 | ->getMock(); 140 | $facebookMock->expects($this->once()) 141 | ->method('getUser') 142 | ->will($this->returnValue('123')); 143 | 144 | $userProviderMock = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); 145 | $userProviderMock->expects($this->once()) 146 | ->method('loadUserByUsername') 147 | ->with('123') 148 | ->will($this->returnValue('234')); 149 | 150 | $userCheckerMock = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); 151 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getProviderKey'), array($providerKey)); 152 | $tokenMock->expects($this->any()) 153 | ->method('getProviderKey') 154 | ->will($this->returnValue($providerKey)); 155 | 156 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock, $userProviderMock, $userCheckerMock); 157 | $facebookProvider->authenticate($tokenMock); 158 | } 159 | 160 | /** 161 | * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException 162 | */ 163 | public function testThatCannotAuthenticateWhenCannotRetrieveFacebookUserFromSession() 164 | { 165 | $providerKey = 'main'; 166 | 167 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 168 | ->disableOriginalConstructor() 169 | ->setMethods(array('getUser')) 170 | ->getMock(); 171 | $facebookMock->expects($this->once()) 172 | ->method('getUser') 173 | ->will($this->returnValue(false)); 174 | 175 | $userProviderMock = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); 176 | $userCheckerMock = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); 177 | 178 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getProviderKey'), array($providerKey)); 179 | $tokenMock->expects($this->any()) 180 | ->method('getProviderKey') 181 | ->will($this->returnValue($providerKey)); 182 | 183 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock, $userProviderMock, $userCheckerMock); 184 | $facebookProvider->authenticate($tokenMock); 185 | } 186 | 187 | /** 188 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::authenticate 189 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::createAuthenticatedToken 190 | */ 191 | public function testThatCanAutenticateUsingUserProvider() 192 | { 193 | $providerKey = 'main'; 194 | 195 | $userMock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); 196 | $userMock->expects($this->once()) 197 | ->method('getUsername') 198 | ->will($this->returnValue('l3l0')); 199 | $userMock->expects($this->once()) 200 | ->method('getRoles') 201 | ->will($this->returnValue(array())); 202 | 203 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 204 | ->disableOriginalConstructor() 205 | ->setMethods(array('getUser')) 206 | ->getMock(); 207 | $facebookMock->expects($this->once()) 208 | ->method('getUser') 209 | ->will($this->returnValue('123')); 210 | 211 | $userProviderMock = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); 212 | $userProviderMock->expects($this->once()) 213 | ->method('loadUserByUsername') 214 | ->with('123') 215 | ->will($this->returnValue($userMock)); 216 | 217 | $userCheckerMock = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); 218 | $userCheckerMock->expects($this->once()) 219 | ->method('checkPostAuth'); 220 | 221 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getAttributes', 'getProviderKey'), array($providerKey)); 222 | $tokenMock->expects($this->once()) 223 | ->method('getAttributes') 224 | ->will($this->returnValue(array())); 225 | $tokenMock->expects($this->any()) 226 | ->method('getProviderKey') 227 | ->will($this->returnValue($providerKey)); 228 | 229 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock, $userProviderMock, $userCheckerMock); 230 | $this->assertEquals('l3l0', $facebookProvider->authenticate($tokenMock)->getUsername()); 231 | } 232 | 233 | /** 234 | * @expectedException Symfony\Component\Security\Core\Exception\AuthenticationException 235 | */ 236 | public function testThatAccessTokenIsSetToFacebookSessionPersistenceWithAccessTokenFromFacebookUserToken() 237 | { 238 | $providerKey = 'main'; 239 | $accessToken = 'AbCd'; 240 | 241 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 242 | ->disableOriginalConstructor() 243 | ->setMethods(array('setAccessToken','getUser')) 244 | ->getMock(); 245 | $facebookMock->expects($this->once()) 246 | ->method('setAccessToken') 247 | ->with($accessToken); 248 | $facebookMock->expects($this->once()) 249 | ->method('getUser'); 250 | 251 | $userProviderMock = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); 252 | 253 | $userCheckerMock = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); 254 | 255 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getProviderKey','getAccessToken'), array($providerKey,'',array(),$accessToken)); 256 | $tokenMock->expects($this->any()) 257 | ->method('getProviderKey') 258 | ->will($this->returnValue($providerKey)); 259 | $tokenMock->expects($this->any()) 260 | ->method('getAccessToken') 261 | ->will($this->returnValue($accessToken)); 262 | 263 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock, $userProviderMock, $userCheckerMock); 264 | $facebookProvider->authenticate($tokenMock); 265 | } 266 | 267 | /** 268 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::authenticate 269 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::createAuthenticatedToken 270 | */ 271 | public function testThatAccessTokenIsSetToNewFacebookUserTokenWhenAuthenticateWithUserProvider() 272 | { 273 | $providerKey = 'main'; 274 | $accessToken = 'AbCd'; 275 | 276 | $userMock = $this->getMock('Symfony\Component\Security\Core\User\UserInterface'); 277 | $userMock->expects($this->once()) 278 | ->method('getRoles') 279 | ->will($this->returnValue(array())); 280 | 281 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 282 | ->disableOriginalConstructor() 283 | ->setMethods(array('getUser')) 284 | ->getMock(); 285 | 286 | $facebookMock->expects($this->once()) 287 | ->method('getUser') 288 | ->will($this->returnValue('123')); 289 | 290 | $userProviderMock = $this->getMock('Symfony\Component\Security\Core\User\UserProviderInterface'); 291 | $userProviderMock->expects($this->once()) 292 | ->method('loadUserByUsername') 293 | ->with('123') 294 | ->will($this->returnValue($userMock)); 295 | 296 | $userCheckerMock = $this->getMock('Symfony\Component\Security\Core\User\UserCheckerInterface'); 297 | $userCheckerMock->expects($this->once()) 298 | ->method('checkPostAuth'); 299 | 300 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getAttributes', 'getProviderKey'), array($providerKey,'',array(),$accessToken)); 301 | $tokenMock->expects($this->once()) 302 | ->method('getAttributes') 303 | ->will($this->returnValue(array())); 304 | $tokenMock->expects($this->any()) 305 | ->method('getProviderKey') 306 | ->will($this->returnValue($providerKey)); 307 | 308 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock, $userProviderMock, $userCheckerMock); 309 | $this->assertEquals($accessToken, $facebookProvider->authenticate($tokenMock)->getAccessToken()); 310 | } 311 | 312 | /** 313 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::authenticate 314 | * @covers FOS\FacebookBundle\Security\Authentication\Provider\FacebookProvider::createAuthenticatedToken 315 | */ 316 | public function testThatAccessTokenIsSetToNewFacebookUserTokenWhenAuthenticateWithoutUserProvider() 317 | { 318 | $providerKey = 'main'; 319 | $accessToken = 'AbCd'; 320 | 321 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 322 | ->disableOriginalConstructor() 323 | ->setMethods(array('getUser')) 324 | ->getMock(); 325 | $facebookMock->expects($this->once()) 326 | ->method('getUser') 327 | ->will($this->returnValue('123')); 328 | 329 | $facebookProvider = new FacebookProvider($providerKey, $facebookMock); 330 | 331 | $tokenMock = $this->getMock('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken', array('getAttributes', 'getProviderKey'), array($providerKey,'',array(),$accessToken)); 332 | $tokenMock->expects($this->once()) 333 | ->method('getAttributes') 334 | ->will($this->returnValue(array())); 335 | $tokenMock->expects($this->any()) 336 | ->method('getProviderKey') 337 | ->will($this->returnValue($providerKey)); 338 | 339 | $this->assertEquals($accessToken, $facebookProvider->authenticate($tokenMock)->getAccessToken()); 340 | 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /Tests/Security/Authentication/Token/FacebookUserTokenTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\Security\Authentication\Token; 13 | 14 | use FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken; 15 | 16 | class FacebookUserTokenTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @dataProvider provider 20 | */ 21 | public function testThatAlwaysReturnEmptyCredentials($uid, $roles) 22 | { 23 | $token = new FacebookUserToken('main', $uid, $roles); 24 | 25 | $this->assertEquals('', $token->getCredentials()); 26 | } 27 | 28 | /** 29 | * @return array 30 | */ 31 | public static function provider() 32 | { 33 | return array( 34 | array('', array()), 35 | array('l3l0', array()), 36 | array('', array('role1', 'role2')), 37 | array('l3l0', array('role1', 'role2')) 38 | ); 39 | } 40 | 41 | public function testThatProviderKeyIsNotEmptyAfterDeserialization() 42 | { 43 | $providerKey = 'main'; 44 | $token = unserialize(serialize(new FacebookUserToken($providerKey))); 45 | 46 | $this->assertEquals($providerKey, $token->getProviderKey()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Tests/Security/EntryPoint/FacebookAuthenticationEntryPointTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\Security\EntryPoint; 13 | 14 | use FOS\FacebookBundle\Security\EntryPoint\FacebookAuthenticationEntryPoint; 15 | 16 | class FacebookAuthenticationEntryPointTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @covers FOS\FacebookBundle\Security\EntryPoint\FacebookAuthenticationEntryPoint::start 20 | */ 21 | public function testThatRedirectResponseWithFacebookLoginUrlIsCreated() 22 | { 23 | $requestMock = $this->getMock('Symfony\Component\HttpFoundation\Request', array('getUriForPath')); 24 | $requestMock->expects($this->once()) 25 | ->method('getUriForPath') 26 | ->with($this->equalTo('/index')) 27 | ->will($this->returnValue('http://localhost/index')); 28 | 29 | $options = array('check_path' => '/index', 'redirect_to_facebook_login' => true); 30 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 31 | ->disableOriginalConstructor() 32 | ->setMethods(array('getLoginUrl')) 33 | ->getMock(); 34 | $facebookMock->expects($this->once()) 35 | ->method('getLoginUrl') 36 | ->with($this->equalTo(array( 37 | 'display' => 'page', 38 | 'scope' => 'email,user_website', 39 | 'redirect_uri' => 'http://localhost/index' 40 | ))) 41 | ->will($this->returnValue('http://localhost/facebook-redirect/index')); 42 | 43 | $facebookAuthentication = new FacebookAuthenticationEntryPoint($facebookMock, $options, array('email', 'user_website')); 44 | $response = $facebookAuthentication->start($requestMock); 45 | 46 | $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response, 'RedirectResponse is returned'); 47 | $this->assertEquals($response->headers->get('location'), 'http://localhost/facebook-redirect/index', 'RedirectResponse has defined expected location'); 48 | } 49 | 50 | /** 51 | * @covers FOS\FacebookBundle\Security\EntryPoint\FacebookAuthenticationEntryPoint::start 52 | */ 53 | public function testThatRedirectResponseWithoutFacebookLoginUrlIsCreated() 54 | { 55 | $requestMock = $this->getMock('Symfony\Component\HttpFoundation\Request', array('getUriForPath')); 56 | $requestMock->expects($this->never()) 57 | ->method('getUriForPath'); 58 | 59 | $options = array( 60 | 'check_path' => '/index', 61 | 'login_path' => '/login', 62 | 'redirect_to_facebook_login' => false 63 | ); 64 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 65 | ->disableOriginalConstructor() 66 | ->setMethods(array('getLoginUrl')) 67 | ->getMock(); 68 | $facebookMock->expects($this->never()) 69 | ->method('getLoginUrl'); 70 | 71 | $facebookAuthentication = new FacebookAuthenticationEntryPoint($facebookMock, $options, array('email', 'user_website')); 72 | $response = $facebookAuthentication->start($requestMock); 73 | 74 | $this->assertInstanceOf('Symfony\Component\HttpFoundation\RedirectResponse', $response, 'RedirectResponse is returned'); 75 | $this->assertEquals($response->headers->get('location'), '/login', 'RedirectResponse has defined expected location'); 76 | } 77 | 78 | /** 79 | * @covers FOS\FacebookBundle\Security\EntryPoint\FacebookAuthenticationEntryPoint::start 80 | */ 81 | public function testThatRedirectionToFacebookLoginUrlIsCreated() 82 | { 83 | $requestMock = $this->getMock('Symfony\Component\HttpFoundation\Request', array('getUriForPath')); 84 | 85 | $options = array( 86 | 'check_path' => '/index', 87 | 'server_url' => 'http://server.url', 88 | 'app_url' => 'http://app.url', 89 | 'redirect_to_facebook_login' => true 90 | ); 91 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 92 | ->disableOriginalConstructor() 93 | ->setMethods(array('getLoginUrl')) 94 | ->getMock(); 95 | $facebookMock->expects($this->once()) 96 | ->method('getLoginUrl') 97 | ->will($this->returnValue('http://localhost/facebook-redirect/index')); 98 | 99 | $facebookAuthentication = new FacebookAuthenticationEntryPoint($facebookMock, $options, array()); 100 | $response = $facebookAuthentication->start($requestMock); 101 | 102 | $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response, 'Response is returned'); 103 | $this->assertRegExp('/location\.href="http:\/\/localhost\/facebook-redirect\/index/', $response->getContent(), 'Javascript redirection is in response'); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Tests/Security/Firewall/FacebookListenerTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\Security\Firewall\FacebookListener; 13 | 14 | use FOS\FacebookBundle\Security\Firewall\FacebookListener; 15 | 16 | class FacebookListenerTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @covers FOS\FacebookBundle\Security\Firewall\FacebookListener::attemptAuthentication 20 | */ 21 | public function testThatCanAttemptAuthenticationWithFacebook() 22 | { 23 | $listener = new FacebookListener( 24 | $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface'), 25 | $this->getAuthenticationManager(), 26 | $this->getMock('Symfony\Component\Security\Http\Session\SessionAuthenticationStrategyInterface'), 27 | $this->getHttpUtils(), 28 | 'providerKey', 29 | $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface'), 30 | $this->getMock('Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface') 31 | ); 32 | $listener->handle($this->getResponseEvent()); 33 | } 34 | 35 | /** 36 | * @return Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface 37 | */ 38 | private function getAuthenticationManager() 39 | { 40 | $authenticationManagerMock = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface'); 41 | $authenticationManagerMock->expects($this->once()) 42 | ->method('authenticate') 43 | ->with($this->isInstanceOf('FOS\FacebookBundle\Security\Authentication\Token\FacebookUserToken')); 44 | 45 | return $authenticationManagerMock; 46 | } 47 | 48 | /** 49 | * @return Symfony\Component\Security\Http\HttpUtils 50 | */ 51 | private function getHttpUtils() 52 | { 53 | $httpUtils = $this->getMock('Symfony\Component\Security\Http\HttpUtils'); 54 | $httpUtils->expects($this->once()) 55 | ->method('checkRequestPath') 56 | ->will($this->returnValue(true)); 57 | 58 | return $httpUtils; 59 | } 60 | 61 | /** 62 | * @return Symfony\Component\HttpKernel\Event\GetResponseEvent 63 | */ 64 | private function getResponseEvent() 65 | { 66 | $responseEventMock = $this->getMock('Symfony\Component\HttpKernel\Event\GetResponseEvent', array('getRequest'), array(), '', false); 67 | $responseEventMock->expects($this->any()) 68 | ->method('getRequest') 69 | ->will($this->returnValue($this->getRequest())); 70 | 71 | return $responseEventMock; 72 | } 73 | 74 | /** 75 | * @return Symfony\Component\HttpFoundation\Request 76 | */ 77 | private function getRequest() 78 | { 79 | $requestMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') 80 | ->disableOriginalClone() 81 | ->getMock(); 82 | $requestMock->expects($this->any()) 83 | ->method('hasSession') 84 | ->will($this->returnValue('true')); 85 | $requestMock->expects($this->any()) 86 | ->method('hasPreviousSession') 87 | ->will($this->returnValue('true')); 88 | 89 | return $requestMock; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Tests/Templating/Helper/FacebookHelperTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\Templating\Helper; 13 | 14 | use FOS\FacebookBundle\Templating\Helper\FacebookHelper; 15 | 16 | class FacebookHelperTest extends \PHPUnit_Framework_TestCase 17 | { 18 | /** 19 | * @covers FOS\FacebookBundle\Templating\Helper\FacebookHelper::initialize 20 | */ 21 | public function testInitialize() 22 | { 23 | $expected = new \stdClass(); 24 | 25 | $templating = $this->getMockBuilder('Symfony\Component\Templating\DelegatingEngine') 26 | ->disableOriginalConstructor() 27 | ->getMock(); 28 | $templating 29 | ->expects($this->once()) 30 | ->method('render') 31 | ->with('FOSFacebookBundle::initialize.html.php', array( 32 | 'appId' => 123, 33 | 'async' => true, 34 | 'cookie' => false, 35 | 'culture' => 'en_US', 36 | 'fbAsyncInit' => '', 37 | 'logging' => true, 38 | 'oauth' => true, 39 | 'status' => false, 40 | 'channelUrl' => '/channel.html', 41 | 'xfbml' => false, 42 | )) 43 | ->will($this->returnValue($expected)); 44 | 45 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 46 | ->disableOriginalConstructor() 47 | ->setMethods(array('getAppId')) 48 | ->getMock(); 49 | 50 | $routing = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface') 51 | ->disableOriginalConstructor() 52 | ->getMock(); 53 | $routing 54 | ->expects($this->once()) 55 | ->method('generate') 56 | ->will($this->returnValue('/channel.html')); 57 | 58 | $facebookMock->expects($this->once()) 59 | ->method('getAppId') 60 | ->will($this->returnValue('123')); 61 | 62 | $helper = new FacebookHelper($templating, $facebookMock, $routing); 63 | $this->assertSame($expected, $helper->initialize(array('cookie' => false))); 64 | } 65 | 66 | /** 67 | * @covers FOS\FacebookBundle\Templating\Helper\FacebookHelper::loginButton 68 | */ 69 | public function testLoginButton() 70 | { 71 | $expected = new \stdClass(); 72 | 73 | $templating = $this->getMockBuilder('Symfony\Component\Templating\DelegatingEngine') 74 | ->disableOriginalConstructor() 75 | ->getMock(); 76 | $templating 77 | ->expects($this->once()) 78 | ->method('render') 79 | ->with('FOSFacebookBundle::loginButton.html.php', array( 80 | 'autologoutlink' => 'false', 81 | 'label' => 'testLabel', 82 | 'showFaces' => 'false', 83 | 'width' => '', 84 | 'maxRows' => '1', 85 | 'scope' => '1,2,3', 86 | 'registrationUrl' => '', 87 | 'size' => 'medium', 88 | 'onlogin' => '' 89 | )) 90 | ->will($this->returnValue($expected)); 91 | 92 | $facebookMock = $this->getMockBuilder('FOS\FacebookBundle\Facebook\FacebookSessionPersistence') 93 | ->disableOriginalConstructor() 94 | ->setMethods(array('getAppId')) 95 | ->getMock(); 96 | 97 | $routing = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface') 98 | ->disableOriginalConstructor() 99 | ->getMock(); 100 | 101 | $facebookMock->expects($this->any()) 102 | ->method('getAppId'); 103 | 104 | $helper = new FacebookHelper($templating, $facebookMock, $routing, true, 'en_US', array(1,2,3) ); 105 | $this->assertSame($expected, $helper->loginButton(array('label' => 'testLabel'))); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Tests/Twig/Extension/FacebookExtensionTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Tests\Twig\Extension; 13 | 14 | use FOS\FacebookBundle\Twig\Extension\FacebookExtension; 15 | use FOS\FacebookBundle\Templating\Helper\FacebookHelper; 16 | 17 | class FacebookExtensionTest extends \PHPUnit_Framework_TestCase 18 | { 19 | /** 20 | * @covers FOS\FacebookBundle\Twig\Extension\FacebookExtension::getName 21 | */ 22 | public function testGetName() 23 | { 24 | $containerMock = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); 25 | $extension = new FacebookExtension($containerMock); 26 | $this->assertSame('facebook', $extension->getName()); 27 | } 28 | 29 | /** 30 | * @covers FOS\FacebookBundle\Twig\Extension\FacebookExtension::getFunctions 31 | */ 32 | public function testGetFunctions() 33 | { 34 | $containerMock = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); 35 | $extension = new FacebookExtension($containerMock); 36 | $functions = $extension->getFunctions(); 37 | $this->assertInstanceOf('\Twig_Function_Method', $functions['facebook_initialize']); 38 | $this->assertInstanceOf('\Twig_Function_Method', $functions['facebook_login_button']); 39 | } 40 | 41 | /** 42 | * @covers FOS\FacebookBundle\Twig\Extension\FacebookExtension::renderInitialize 43 | */ 44 | public function testRenderInitialize() 45 | { 46 | $helperMock = $this->getMockBuilder('FOS\FacebookBundle\Templating\Helper\FacebookHelper') 47 | ->disableOriginalConstructor() 48 | ->getMock(); 49 | $helperMock->expects($this->once()) 50 | ->method('initialize') 51 | ->will($this->returnValue('returnedValue')); 52 | $containerMock = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); 53 | $containerMock->expects($this->once()) 54 | ->method('get') 55 | ->with('fos_facebook.helper') 56 | ->will($this->returnValue($helperMock)); 57 | 58 | $extension = new FacebookExtension($containerMock); 59 | $this->assertSame('returnedValue', $extension->renderInitialize()); 60 | } 61 | 62 | /** 63 | * @covers FOS\FacebookBundle\Twig\Extension\FacebookExtension::renderloginButton 64 | */ 65 | public function testRenderLoginButton() 66 | { 67 | $helperMock = $this->getMockBuilder('FOS\FacebookBundle\Templating\Helper\FacebookHelper') 68 | ->disableOriginalConstructor() 69 | ->getMock(); 70 | $helperMock->expects($this->once()) 71 | ->method('loginButton') 72 | ->will($this->returnValue('returnedValueLogin')); 73 | $containerMock = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); 74 | $containerMock->expects($this->once()) 75 | ->method('get') 76 | ->with('fos_facebook.helper') 77 | ->will($this->returnValue($helperMock)); 78 | 79 | $extension = new FacebookExtension($containerMock); 80 | $this->assertSame('returnedValueLogin', $extension->renderLoginButton()); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | $file = __DIR__.'/../vendor/autoload.php'; 13 | if (!file_exists($file)) { 14 | throw new RuntimeException('Install dependencies to run test suite.'); 15 | } 16 | 17 | $autoload = require_once $file; 18 | -------------------------------------------------------------------------------- /Twig/Extension/FacebookExtension.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace FOS\FacebookBundle\Twig\Extension; 13 | 14 | use FOS\FacebookBundle\Templating\Helper\FacebookHelper; 15 | use Symfony\Component\DependencyInjection\ContainerInterface; 16 | 17 | class FacebookExtension extends \Twig_Extension 18 | { 19 | protected $container; 20 | 21 | /** 22 | * Constructor. 23 | * 24 | * @param ContainerInterface $container 25 | */ 26 | public function __construct(ContainerInterface $container) 27 | { 28 | $this->container = $container; 29 | } 30 | 31 | /** 32 | * Returns a list of global functions to add to the existing list. 33 | * 34 | * @return array An array of global functions 35 | */ 36 | public function getFunctions() 37 | { 38 | return array( 39 | 'facebook_initialize' => new \Twig_Function_Method($this, 'renderInitialize', array('is_safe' => array('html'))), 40 | 'facebook_login_button' => new \Twig_Function_Method($this, 'renderLoginButton', array('is_safe' => array('html'))), 41 | 'facebook_logout_url' => new \Twig_Function_Method($this, 'renderLogoutUrl', array('is_safe' => array('html'))), 42 | ); 43 | } 44 | 45 | /** 46 | * Returns the name of the extension. 47 | * 48 | * @return string The extension name 49 | */ 50 | public function getName() 51 | { 52 | return 'facebook'; 53 | } 54 | 55 | /** 56 | * @see FacebookHelper::initialize() 57 | */ 58 | public function renderInitialize($parameters = array(), $name = null) 59 | { 60 | return $this->container->get('fos_facebook.helper')->initialize($parameters, $name ?: 'FOSFacebookBundle::initialize.html.twig'); 61 | } 62 | 63 | /** 64 | * @see FacebookHelper::loginButton() 65 | */ 66 | public function renderLoginButton($parameters = array(), $name = null) 67 | { 68 | return $this->container->get('fos_facebook.helper')->loginButton($parameters, $name ?: 'FOSFacebookBundle::loginButton.html.twig'); 69 | } 70 | 71 | /** 72 | * @see FacebookHelper::logoutUrl() 73 | */ 74 | public function renderLogoutUrl($parameters = array(), $name = null) 75 | { 76 | return $this->container->get('fos_facebook.helper')->logoutUrl($parameters); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "friendsofsymfony/facebook-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Integrate the Facebook Platform into your Symfony2 application.", 5 | "keywords": ["facebook"], 6 | "homepage": "http://friendsofsymfony.github.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name":"Kris Wallsmith", 11 | "email":"kris.wallsmith@gmail.com", 12 | "homepage":"http://kriswallsmith.net/" 13 | }, 14 | { 15 | "name": "FriendsOfSymfony Community", 16 | "homepage": "https://github.com/friendsofsymfony/FOSFacebookBundle/contributors" 17 | } 18 | ], 19 | "require": { 20 | "php": ">=5.3.2", 21 | "symfony/http-foundation": "~2.2", 22 | "symfony/security": "~2.2", 23 | "facebook/php-sdk": "3.2.*" 24 | }, 25 | "require-dev": { 26 | "symfony/framework-bundle": "~2.2", 27 | "symfony/security-bundle": "~2.2", 28 | "symfony/twig-bundle": "~2.2", 29 | "symfony/finder": "~2.2", 30 | "symfony/browser-kit": "~2.2", 31 | "symfony/form": "~2.2", 32 | "phpunit/phpunit": "3.7.*" 33 | }, 34 | "config": { 35 | "bin-dir": "bin" 36 | }, 37 | "autoload": { 38 | "psr-0": { "FOS\\FacebookBundle": "" } 39 | }, 40 | "extra": { 41 | "branch-alias": { 42 | "dev-master": "1.3.x-dev" 43 | } 44 | }, 45 | "target-dir": "FOS/FacebookBundle" 46 | } 47 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ./Tests 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ./ 16 | 17 | ./Resources 18 | ./Tests 19 | ./vendor 20 | 21 | 22 | 23 | 24 | --------------------------------------------------------------------------------