From 441597568aacac0194d0b695587b5a3aae0186f2 Mon Sep 17 00:00:00 2001 From: Serghei Luchianenco Date: Sun, 8 Jan 2017 00:12:00 +0100 Subject: [PATCH 1/3] Bitbucket Client added --- README.md | 18 ++++++ composer.json | 3 +- src/Client/Provider/BitbucketClient.php | 35 +++++++++++ .../KnpUOAuth2ClientExtension.php | 2 + .../BitbucketProviderConfigurator.php | 54 +++++++++++++++++ tests/Client/OAuth2ClientTest.php | 58 ++++++++++++++----- tests/FunctionalTest.php | 7 +++ .../Authenticator/SocialAuthenticatorTest.php | 37 ++++++++++++ .../FinishRegistrationExceptionTest.php | 23 ++++++++ .../NoAuthCodeAuthenticationExceptionTest.php | 23 ++++++++ .../Helper/FinishRegistrationBehaviorTest.php | 40 +++++++++++++ .../Security/Helper/PreviousUrlHelperTest.php | 32 ++++++++++ 12 files changed, 318 insertions(+), 14 deletions(-) create mode 100644 src/Client/Provider/BitbucketClient.php create mode 100644 src/DependencyInjection/Providers/BitbucketProviderConfigurator.php create mode 100644 tests/Security/Exception/FinishRegistrationExceptionTest.php create mode 100644 tests/Security/Exception/NoAuthCodeAuthenticationExceptionTest.php create mode 100644 tests/Security/Helper/FinishRegistrationBehaviorTest.php create mode 100644 tests/Security/Helper/PreviousUrlHelperTest.php diff --git a/README.md b/README.md index bf273bb7..a48148d6 100644 --- a/README.md +++ b/README.md @@ -427,6 +427,24 @@ knpu_oauth2_client: # whether to check OAuth2 "state": defaults to true # use_state: true + + # will create service: "knpu.oauth2.client.bitbucket" + # an instance of: KnpU\OAuth2ClientBundle\Client\Provider\BitbucketClient + # composer require stevenmaguire/oauth2-bitbucket + instagram: + # must be "bitbucket" - it activates that type! + type: bitbucket + # add and configure client_id and client_secret in parameters.yml + client_id: %bitbucket_client_id% + client_secret: %bitbucket_client_secret% + # a route name you'll create + redirect_route: connect_bitbucket_check + redirect_params: {} + + # whether to check OAuth2 "state": defaults to true + # use_state: true + + ``` ## Configuring a Generic Provider diff --git a/composer.json b/composer.json index 4b077bb1..0452341e 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,8 @@ "symfony/dependency-injection": "^2.8|^3.0", "symfony/routing": "^2.7|^3.0", "symfony/http-foundation": "^2.7|^3.0", - "league/oauth2-client": "^1.0" + "league/oauth2-client": "^1.0", + "stevenmaguire/oauth2-bitbucket": "^0.1.2" }, "autoload": { "psr-4": { "KnpU\\OAuth2ClientBundle\\": "src/" } diff --git a/src/Client/Provider/BitbucketClient.php b/src/Client/Provider/BitbucketClient.php new file mode 100644 index 00000000..73703983 --- /dev/null +++ b/src/Client/Provider/BitbucketClient.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace KnpU\OAuth2ClientBundle\Client\Provider; + +use KnpU\OAuth2ClientBundle\Client\OAuth2Client; +use League\OAuth2\Client\Token\AccessToken; +use Stevenmaguire\OAuth2\Client\Provider\BitbucketResourceOwner; + +class BitbucketClient extends OAuth2Client +{ + /** + * @param AccessToken $accessToken + * @return BitbucketResourceOwner + */ + public function fetchUserFromToken(AccessToken $accessToken) + { + return parent::fetchUserFromToken($accessToken); + } + + /** + * @return BitbucketResourceOwner + */ + public function fetchUser() + { + return parent::fetchUser(); + } +} diff --git a/src/DependencyInjection/KnpUOAuth2ClientExtension.php b/src/DependencyInjection/KnpUOAuth2ClientExtension.php index 3f243fb0..c07fd708 100644 --- a/src/DependencyInjection/KnpUOAuth2ClientExtension.php +++ b/src/DependencyInjection/KnpUOAuth2ClientExtension.php @@ -10,6 +10,7 @@ namespace KnpU\OAuth2ClientBundle\DependencyInjection; +use KnpU\OAuth2ClientBundle\DependencyInjection\Providers\BitbucketProviderConfigurator; use KnpU\OAuth2ClientBundle\DependencyInjection\Providers\EveOnlineProviderConfigurator; use KnpU\OAuth2ClientBundle\DependencyInjection\Providers\FacebookProviderConfigurator; use KnpU\OAuth2ClientBundle\DependencyInjection\Providers\GenericProviderConfigurator; @@ -46,6 +47,7 @@ class KnpUOAuth2ClientExtension extends Extension 'google' => GoogleProviderConfigurator::class, 'eve_online' => EveOnlineProviderConfigurator::class, 'instagram' => InstagramProviderConfigurator::class, + 'bitbucket' => BitbucketProviderConfigurator::class, 'generic' => GenericProviderConfigurator::class, ]; diff --git a/src/DependencyInjection/Providers/BitbucketProviderConfigurator.php b/src/DependencyInjection/Providers/BitbucketProviderConfigurator.php new file mode 100644 index 00000000..c5404ad0 --- /dev/null +++ b/src/DependencyInjection/Providers/BitbucketProviderConfigurator.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace KnpU\OAuth2ClientBundle\DependencyInjection\Providers; + +use Symfony\Component\Config\Definition\Builder\NodeBuilder; + +class BitbucketProviderConfigurator implements ProviderConfiguratorInterface +{ + public function buildConfiguration(NodeBuilder $node) + { + // no custom options + } + + public function getProviderClass(array $config) + { + return 'Stevenmaguire\OAuth2\Client\Provider\Bitbucket'; + } + + public function getProviderOptions(array $config) + { + return [ + 'clientId' => $config['client_id'], + 'clientSecret' => $config['client_secret'], + ]; + } + + public function getPackagistName() + { + return 'stevenmaguire/oauth2-bitbucket'; + } + + public function getLibraryHomepage() + { + return 'https://github.com/stevenmaguire/oauth2-bitbucket'; + } + + public function getProviderDisplayName() + { + return 'Bitbucket'; + } + + public function getClientClass(array $config) + { + return 'KnpU\OAuth2ClientBundle\Client\Provider\BitbucketClient'; + } +} diff --git a/tests/Client/OAuth2ClientTest.php b/tests/Client/OAuth2ClientTest.php index b652db61..72e1bca8 100644 --- a/tests/Client/OAuth2ClientTest.php +++ b/tests/Client/OAuth2ClientTest.php @@ -11,6 +11,7 @@ namespace KnpU\OAuth2ClientBundle\Tests\Client; use KnpU\OAuth2ClientBundle\Client\OAuth2Client; +use League\OAuth2\Client\Provider\FacebookUser; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; @@ -166,20 +167,51 @@ public function testGetAccessTokenThrowsInvalidStateException() $client->getAccessToken(); } - /** - * @expectedException \KnpU\OAuth2ClientBundle\Exception\MissingAuthorizationCodeException + /** + * @expectedException \KnpU\OAuth2ClientBundle\Exception\MissingAuthorizationCodeException */ - public function testGetAccessTokenThrowsMissingAuthCodeException() - { - $this->request->query->set('state', 'ACTUAL_STATE'); - $this->session->get(OAuth2Client::OAUTH2_SESSION_STATE_KEY) + public function testGetAccessTokenThrowsMissingAuthCodeException() + { + $this->request->query->set('state', 'ACTUAL_STATE'); + $this->session->get(OAuth2Client::OAUTH2_SESSION_STATE_KEY) ->willReturn('ACTUAL_STATE'); - // don't set a code query parameter - $client = new OAuth2Client( - $this->provider->reveal(), - $this->requestStack - ); - $client->getAccessToken(); - } + // don't set a code query parameter + $client = new OAuth2Client( + $this->provider->reveal(), + $this->requestStack + ); + $client->getAccessToken(); + } + + public function testFetchUser() + { + $this->request->request->set('code', 'CODE_ABC'); + + $expectedToken = $this->prophesize('League\OAuth2\Client\Token\AccessToken'); + $this->provider->getAccessToken('authorization_code', ['code' => 'CODE_ABC']) + ->willReturn($expectedToken->reveal()); + + $client = new OAuth2Client( + $this->provider->reveal(), + $this->requestStack + ); + + $client->setAsStateless(); + $actualToken = $client->getAccessToken(); + + $resourceOwner = new FacebookUser([ + 'id' => '1', + 'name' => 'testUser', + 'first_name' => 'John', + 'last_name' => 'Doe', + 'email' => 'john@doe.com' + ]); + + $this->provider->getResourceOwner($actualToken)->willReturn($resourceOwner); + $user = $client->fetchUser($actualToken); + + $this->assertInstanceOf('League\OAuth2\Client\Provider\FacebookUser', $user); + $this->assertEquals('testUser', $user->getName()); + } } diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php index 0d5d337d..c312d6b3 100644 --- a/tests/FunctionalTest.php +++ b/tests/FunctionalTest.php @@ -30,5 +30,12 @@ public function testServicesAreUsable() ->getClient('my_facebook'); $this->assertSame($client, $client2); $this->assertTrue($container->has('oauth2.registry')); + + try { + $container->get('knpu.oauth2.registry')->getClient(''); + $this->assertEquals(false, true); + } catch (\InvalidArgumentException $e) { + $this->assertInstanceOf('\InvalidArgumentException', $e); + } } } diff --git a/tests/Security/Authenticator/SocialAuthenticatorTest.php b/tests/Security/Authenticator/SocialAuthenticatorTest.php index 69bbed52..3679cfea 100644 --- a/tests/Security/Authenticator/SocialAuthenticatorTest.php +++ b/tests/Security/Authenticator/SocialAuthenticatorTest.php @@ -16,6 +16,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; class SocialAuthenticatorTest extends \PHPUnit_Framework_TestCase @@ -43,6 +44,19 @@ public function testFetchAccessTokenThrowsAuthenticationException() $authenticator->doFetchAccessToken($client->reveal()); } + + public function testCheckCredentials() + { + $authenticator = new StubSocialAuthenticator(); + $user = new SomeUser(); + $this->assertEquals(true, $authenticator->checkCredentials('', $user)); + } + + public function testSupportsRememberMe() + { + $authenticator = new StubSocialAuthenticator(); + $this->assertEquals(true, $authenticator->supportsRememberMe()); + } } class StubSocialAuthenticator extends SocialAuthenticator @@ -68,3 +82,26 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token, { } } + +class SomeUser implements UserInterface +{ + public function getRoles() + { + } + + public function getPassword() + { + } + + public function getSalt() + { + } + + public function getUsername() + { + } + + public function eraseCredentials() + { + } +} diff --git a/tests/Security/Exception/FinishRegistrationExceptionTest.php b/tests/Security/Exception/FinishRegistrationExceptionTest.php new file mode 100644 index 00000000..f99b8fb3 --- /dev/null +++ b/tests/Security/Exception/FinishRegistrationExceptionTest.php @@ -0,0 +1,23 @@ + '1', 'name' => 'testUser']; + $e = new FinishRegistrationException($userInfo, '', 0); + + $this->assertEquals($e->getUserInformation(), $userInfo); + $this->assertInternalType('string', $e->getMessageKey()); + } +} diff --git a/tests/Security/Exception/NoAuthCodeAuthenticationExceptionTest.php b/tests/Security/Exception/NoAuthCodeAuthenticationExceptionTest.php new file mode 100644 index 00000000..31e404d4 --- /dev/null +++ b/tests/Security/Exception/NoAuthCodeAuthenticationExceptionTest.php @@ -0,0 +1,23 @@ +assertInternalType('string', $e->getMessageKey()); + } +} diff --git a/tests/Security/Helper/FinishRegistrationBehaviorTest.php b/tests/Security/Helper/FinishRegistrationBehaviorTest.php new file mode 100644 index 00000000..b6d001cd --- /dev/null +++ b/tests/Security/Helper/FinishRegistrationBehaviorTest.php @@ -0,0 +1,40 @@ +traitObject = $this + ->getMockForTrait('KnpU\OAuth2ClientBundle\Security\Helper\FinishRegistrationBehavior'); + } + + public function testGetUserInfoFromSession() + { + $request = $this->prophesize('Symfony\Component\HttpFoundation\Request'); + $request->getSession()->willReturn(new StubSession()); + $res = $this->traitObject->getUserInfoFromSession($request->reveal()); + + $this->assertEquals($res, true); + } + +} + +class StubSession +{ + public function get() + { + return true; + } +} \ No newline at end of file diff --git a/tests/Security/Helper/PreviousUrlHelperTest.php b/tests/Security/Helper/PreviousUrlHelperTest.php new file mode 100644 index 00000000..916cc360 --- /dev/null +++ b/tests/Security/Helper/PreviousUrlHelperTest.php @@ -0,0 +1,32 @@ +traitObject = $this + ->getMockForTrait('KnpU\OAuth2ClientBundle\Security\Helper\PreviousUrlHelper'); + } + + public function testGetPreviousUrl() + { + $request = $this->prophesize('Symfony\Component\HttpFoundation\Request'); + $request->getSession()->willReturn(new StubSession()); + $res = $this->traitObject->getPreviousUrl($request->reveal(), ''); + + $this->assertEquals($res, true); + } +} From fb3c9a80b69cf979b5c61e231e18aedd148b4932 Mon Sep 17 00:00:00 2001 From: Serghei Luchianenco Date: Sun, 8 Jan 2017 00:15:05 +0100 Subject: [PATCH 2/3] readme updated --- README.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index a48148d6..8299cb38 100644 --- a/README.md +++ b/README.md @@ -54,16 +54,17 @@ via Composer: -| OAuth2 Provider | Install | -| -------------------------------------------------------------- | -------------------------------------------- | -| [Facebook](https://github.com/thephpleague/oauth2-facebook) | composer require league/oauth2-facebook | -| [GitHub](https://github.com/thephpleague/oauth2-github) | composer require league/oauth2-github | -| [GitLab](https://github.com/omines/oauth2-gitlab) | composer require omines/oauth2-gitlab | -| [LinkedIn](https://github.com/thephpleague/oauth2-linkedin) | composer require league/oauth2-linkedin | -| [Google](https://github.com/thephpleague/oauth2-google) | composer require league/oauth2-google | -| [Eve Online](https://github.com/evelabs/oauth2-eveonline) | composer require evelabs/oauth2-eveonline | -| [Instagram](https://github.com/thephpleague/oauth2-instagram) | composer require league/oauth2-instagram | -| generic | configure any unsupported provider | +| OAuth2 Provider | Install | +| -------------------------------------------------------------- | ------------------------------------------------- | +| [Facebook](https://github.com/thephpleague/oauth2-facebook) | composer require league/oauth2-facebook | +| [GitHub](https://github.com/thephpleague/oauth2-github) | composer require league/oauth2-github | +| [GitLab](https://github.com/omines/oauth2-gitlab) | composer require omines/oauth2-gitlab | +| [LinkedIn](https://github.com/thephpleague/oauth2-linkedin) | composer require league/oauth2-linkedin | +| [Google](https://github.com/thephpleague/oauth2-google) | composer require league/oauth2-google | +| [Eve Online](https://github.com/evelabs/oauth2-eveonline) | composer require evelabs/oauth2-eveonline | +| [Instagram](https://github.com/thephpleague/oauth2-instagram) | composer require league/oauth2-instagram | +| [Bitbucket](https://github.com/stevenmaguire/oauth2-bitbucket) | composer require stevenmaguire/oauth2-bitbucket | +| generic | configure any unsupported provider | @@ -431,7 +432,7 @@ knpu_oauth2_client: # will create service: "knpu.oauth2.client.bitbucket" # an instance of: KnpU\OAuth2ClientBundle\Client\Provider\BitbucketClient # composer require stevenmaguire/oauth2-bitbucket - instagram: + bitbucket: # must be "bitbucket" - it activates that type! type: bitbucket # add and configure client_id and client_secret in parameters.yml From c0d585f6e3bdf09aa290bf2aef2ac9068523ff32 Mon Sep 17 00:00:00 2001 From: Serghei Luchianenco Date: Sun, 8 Jan 2017 12:39:58 +0100 Subject: [PATCH 3/3] removed dependancy on bitbucket provider in composer --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0452341e..4b077bb1 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,7 @@ "symfony/dependency-injection": "^2.8|^3.0", "symfony/routing": "^2.7|^3.0", "symfony/http-foundation": "^2.7|^3.0", - "league/oauth2-client": "^1.0", - "stevenmaguire/oauth2-bitbucket": "^0.1.2" + "league/oauth2-client": "^1.0" }, "autoload": { "psr-4": { "KnpU\\OAuth2ClientBundle\\": "src/" }