Files
Phraseanet/lib/Alchemy/Phrasea/Authentication/Provider/Github.php
Nicolas Le Goff 949bf06cac Merge branch '3.8'
Conflicts:
	CHANGELOG.md
	bin/console
	bin/developer
	bin/setup
	bower.json
	composer.json
	composer.lock
	features/bootstrap/FeatureContext.php
	features/bootstrap/GuiContext.php
	lib/Alchemy/Phrasea/Authentication/Token/TokenValidator.php
	lib/Alchemy/Phrasea/Command/BuildMissingSubdefs.php
	lib/Alchemy/Phrasea/Command/CreateCollection.php
	lib/Alchemy/Phrasea/Command/Developer/JavascriptBuilder.php
	lib/Alchemy/Phrasea/Controller/Admin/Collection.php
	lib/Alchemy/Phrasea/Controller/Admin/Databoxes.php
	lib/Alchemy/Phrasea/Controller/Admin/TaskManager.php
	lib/Alchemy/Phrasea/Controller/Api/V1.php
	lib/Alchemy/Phrasea/Controller/Client/Baskets.php
	lib/Alchemy/Phrasea/Controller/Client/Root.php
	lib/Alchemy/Phrasea/Controller/Prod/Basket.php
	lib/Alchemy/Phrasea/Controller/Prod/Export.php
	lib/Alchemy/Phrasea/Controller/Prod/Property.php
	lib/Alchemy/Phrasea/Controller/Prod/Records.php
	lib/Alchemy/Phrasea/Controller/Prod/Tools.php
	lib/Alchemy/Phrasea/Controller/Prod/Upload.php
	lib/Alchemy/Phrasea/Controller/Root/Login.php
	lib/Alchemy/Phrasea/Controller/Thesaurus/Thesaurus.php
	lib/Alchemy/Phrasea/Core/Event/ApiLoadEndEvent.php
	lib/Alchemy/Phrasea/Core/Event/ApiLoadStartEvent.php
	lib/Alchemy/Phrasea/Core/Provider/TaskManagerServiceProvider.php
	lib/Alchemy/Phrasea/Core/Version.php
	lib/Alchemy/Phrasea/Exception/XMLParseErrorException.php
	lib/Alchemy/Phrasea/Helper/DatabaseHelper.php
	lib/Alchemy/Phrasea/Helper/User/Edit.php
	lib/Alchemy/Phrasea/SearchEngine/Phrasea/PhraseaEngine.php
	lib/Alchemy/Phrasea/SearchEngine/SearchEngineOptions.php
	lib/Doctrine/Entities/AuthFailure.php
	lib/Doctrine/Entities/Basket.php
	lib/Doctrine/Entities/BasketElement.php
	lib/Doctrine/Entities/LazaretAttribute.php
	lib/Doctrine/Entities/LazaretCheck.php
	lib/Doctrine/Entities/LazaretFile.php
	lib/Doctrine/Entities/LazaretSession.php
	lib/Doctrine/Entities/Session.php
	lib/Doctrine/Entities/SessionModule.php
	lib/Doctrine/Entities/StoryWZ.php
	lib/Doctrine/Entities/UsrList.php
	lib/Doctrine/Entities/UsrListEntry.php
	lib/Doctrine/Entities/UsrListOwner.php
	lib/Doctrine/Entities/ValidationData.php
	lib/Doctrine/Entities/ValidationParticipant.php
	lib/Doctrine/Entities/ValidationSession.php
	lib/Doctrine/Logger/MonologSQLLogger.php
	lib/Doctrine/Repositories/BasketRepository.php
	lib/Doctrine/Repositories/ValidationParticipantRepository.php
	lib/Doctrine/Types/Binary.php
	lib/Doctrine/Types/Blob.php
	lib/Doctrine/Types/Enum.php
	lib/Doctrine/Types/LongBlob.php
	lib/Doctrine/Types/VarBinary.php
	lib/classes/API/OAuth2/Account.php
	lib/classes/API/OAuth2/Application.php
	lib/classes/API/OAuth2/Application/OfficePlugin.php
	lib/classes/API/OAuth2/AuthCode.php
	lib/classes/API/OAuth2/RefreshToken.php
	lib/classes/API/OAuth2/Token.php
	lib/classes/API/V1/Abstract.php
	lib/classes/API/V1/Interface.php
	lib/classes/API/V1/adapter.php
	lib/classes/API/V1/exception/abstract.php
	lib/classes/API/V1/exception/badrequest.php
	lib/classes/API/V1/exception/forbidden.php
	lib/classes/API/V1/exception/internalservererror.php
	lib/classes/API/V1/exception/maintenance.php
	lib/classes/API/V1/exception/methodnotallowed.php
	lib/classes/API/V1/exception/notfound.php
	lib/classes/API/V1/exception/unauthorized.php
	lib/classes/API/V1/result.php
	lib/classes/Exception/Feed/EntryNotFound.php
	lib/classes/Exception/Feed/ItemNotFound.php
	lib/classes/Exception/Feed/PublisherNotFound.php
	lib/classes/Feed/Abstract.php
	lib/classes/Feed/Adapter.php
	lib/classes/Feed/Aggregate.php
	lib/classes/Feed/Collection.php
	lib/classes/Feed/CollectionInterface.php
	lib/classes/Feed/Entry/Adapter.php
	lib/classes/Feed/Entry/Collection.php
	lib/classes/Feed/Entry/CollectionInterface.php
	lib/classes/Feed/Entry/Interface.php
	lib/classes/Feed/Entry/Item.php
	lib/classes/Feed/Entry/ItemInterface.php
	lib/classes/Feed/Interface.php
	lib/classes/Feed/Link.php
	lib/classes/Feed/LinkInterface.php
	lib/classes/Feed/Publisher/Adapter.php
	lib/classes/Feed/Publisher/Interface.php
	lib/classes/Feed/Token.php
	lib/classes/Feed/TokenAggregate.php
	lib/classes/Feed/XML/Abstract.php
	lib/classes/Feed/XML/Atom.php
	lib/classes/Feed/XML/Cooliris.php
	lib/classes/Feed/XML/Interface.php
	lib/classes/Feed/XML/RSS.php
	lib/classes/Feed/XML/RSS/Image.php
	lib/classes/Feed/XML/RSS/ImageInterface.php
	lib/classes/User/Adapter.php
	lib/classes/User/Interface.php
	lib/classes/appbox/register.php
	lib/classes/connection.php
	lib/classes/connection/abstract.php
	lib/classes/connection/interface.php
	lib/classes/connection/pdo.php
	lib/classes/connection/pdoStatementDebugger.php
	lib/classes/deprecated/countries.php
	lib/classes/deprecated/inscript.api.php
	lib/classes/eventsmanager/event/test.php
	lib/classes/ftpclient.php
	lib/classes/http/request.php
	lib/classes/media/subdef.php
	lib/classes/module/console/schedulerStart.php
	lib/classes/module/console/schedulerState.php
	lib/classes/module/console/schedulerStop.php
	lib/classes/module/console/taskState.php
	lib/classes/module/console/tasklist.php
	lib/classes/module/console/taskrun.php
	lib/classes/patch/320alpha4b.php
	lib/classes/patch/3715alpha1a.php
	lib/classes/patch/379alpha1a.php
	lib/classes/patch/380alpha10a.php
	lib/classes/patch/380alpha11a.php
	lib/classes/patch/380alpha13a.php
	lib/classes/patch/380alpha14a.php
	lib/classes/patch/380alpha15a.php
	lib/classes/patch/380alpha16a.php
	lib/classes/patch/380alpha17a.php
	lib/classes/patch/380alpha18a.php
	lib/classes/patch/380alpha3a.php
	lib/classes/patch/380alpha4a.php
	lib/classes/patch/380alpha6a.php
	lib/classes/patch/380alpha8a.php
	lib/classes/patch/380alpha9a.php
	lib/classes/patch/381alpha1b.php
	lib/classes/patch/381alpha2a.php
	lib/classes/patch/381alpha3a.php
	lib/classes/patch/381alpha4a.php
	lib/classes/patch/383alpha1a.php
	lib/classes/patch/383alpha2a.php
	lib/classes/patch/383alpha3a.php
	lib/classes/patch/383alpha4a.php
	lib/classes/record/adapter.php
	lib/classes/record/preview.php
	lib/classes/recordutils.php
	lib/classes/recordutils/audio.php
	lib/classes/recordutils/document.php
	lib/classes/recordutils/map.php
	lib/classes/recordutils/video.php
	lib/classes/registry.php
	lib/classes/registryInterface.php
	lib/classes/set/order.php
	lib/classes/system/url.php
	lib/classes/task/Scheduler.php
	lib/classes/task/appboxAbstract.php
	lib/classes/task/databoxAbstract.php
	lib/classes/task/manager.php
	lib/classes/task/period/RecordMover.php
	lib/classes/task/period/apibridge.php
	lib/classes/task/period/apiwebhooks.php
	lib/classes/task/period/archive.php
	lib/classes/task/period/cindexer.php
	lib/classes/task/period/emptyColl.php
	lib/classes/task/period/ftp.php
	lib/classes/task/period/ftpPull.php
	lib/classes/task/period/subdef.php
	lib/classes/task/period/test.php
	lib/classes/task/period/writemeta.php
	lib/conf.d/PhraseaFixture/AbstractWZ.php
	lib/conf.d/PhraseaFixture/Basket/LoadFiveBaskets.php
	lib/conf.d/PhraseaFixture/Basket/LoadOneBasket.php
	lib/conf.d/PhraseaFixture/Basket/LoadOneBasketEnv.php
	lib/conf.d/PhraseaFixture/Lazaret/LoadOneFile.php
	lib/conf.d/PhraseaFixture/Story/LoadOneStory.php
	lib/conf.d/PhraseaFixture/UsrLists/ListAbstract.php
	lib/conf.d/PhraseaFixture/UsrLists/UsrList.php
	lib/conf.d/PhraseaFixture/UsrLists/UsrListEntry.php
	lib/conf.d/PhraseaFixture/UsrLists/UsrListOwner.php
	lib/conf.d/PhraseaFixture/ValidationParticipant/LoadOneParticipant.php
	lib/conf.d/PhraseaFixture/ValidationParticipant/LoadParticipantWithSession.php
	lib/conf.d/PhraseaFixture/ValidationSession/LoadOneValidationSession.php
	templates/web/admin/collection/collection.html.twig
	templates/web/common/dialog_export.html.twig
	templates/web/common/menubar.html.twig
	templates/web/prod/actions/Tools/index.html.twig
	templates/web/prod/index.html.twig
	templates/web/prod/upload/upload-flash.html.twig
	templates/web/prod/upload/upload.html.twig
	templates/web/report/report_layout_child.html.twig
	templates/web/setup/step2.html.twig
	templates/web/thesaurus/new-synonym-dialog.html.twig
	templates/web/thesaurus/properties.html.twig
	templates/web/thesaurus/search.html.twig
	tests/Alchemy/Tests/Phrasea/Application/ApiAbstract.php
	tests/Alchemy/Tests/Phrasea/Cache/FactoryTest.php
	tests/Alchemy/Tests/Phrasea/Controller/Admin/AdminCollectionTest.php
	tests/Alchemy/Tests/Phrasea/Controller/Client/RootTest.php
2015-02-05 18:38:49 +01:00

303 lines
12 KiB
PHP

<?php
/*
* This file is part of Phraseanet
*
* (c) 2005-2015 Alchemy
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Alchemy\Phrasea\Authentication\Provider;
use Alchemy\Phrasea\Authentication\Provider\Token\Token;
use Alchemy\Phrasea\Authentication\Provider\Token\Identity;
use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Guzzle\Http\Client as Guzzle;
use Guzzle\Http\ClientInterface;
use Guzzle\Common\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class Github extends AbstractProvider
{
private $client;
private $key;
private $secret;
public function __construct(UrlGenerator $generator, SessionInterface $session, ClientInterface $client, $key, $secret)
{
$this->generator = $generator;
$this->session = $session;
$this->client = $client;
$this->key = $key;
$this->secret = $secret;
}
/**
* @param ClientInterface $client
*
* @return Github
*/
public function setGuzzleClient(ClientInterface $client)
{
$this->client = $client;
return $this;
}
/**
* @return ClientInterface
*/
public function getGuzzleClient()
{
return $this->client;
}
/**
* {@inheritdoc}
*/
public function getId()
{
return 'github';
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'Github';
}
/**
* {@inheritdoc}
*/
public function authenticate()
{
$state = $this->createState();
$this->session->set('github.provider.state', $state);
return new RedirectResponse('https://github.com/login/oauth/authorize?' . http_build_query([
'client_id' => $this->key,
'scope' => 'user,user:email',
'state' => $state,
'redirect_uri' => $this->generator->generate(
'login_authentication_provider_callback',
['providerId' => $this->getId()],
UrlGenerator::ABSOLUTE_URL
),
], '', '&'));
}
/**
* {@inheritdoc}
*/
public function logout()
{
// GitHub does not support tokens revocation
}
/**
* {@inheritdoc}
*/
public function onCallback(Request $request)
{
if (!$this->session->has('github.provider.state')) {
throw new NotAuthenticatedException('No state value in session ; CSRF try ?');
}
if ($request->query->get('state') !== $this->session->remove('github.provider.state')) {
throw new NotAuthenticatedException('Invalid state value ; CSRF try ?');
}
try {
$guzzleRequest = $this->client->post('access_token');
$guzzleRequest->addPostFields([
'code' => $request->query->get('code'),
'redirect_uri' => $this->generator->generate(
'login_authentication_provider_callback',
['providerId' => $this->getId()],
UrlGenerator::ABSOLUTE_URL
),
'client_id' => $this->key,
'client_secret' => $this->secret,
]);
$guzzleRequest->setHeader('Accept', 'application/json');
$response = $guzzleRequest->send();
} catch (GuzzleException $e) {
throw new NotAuthenticatedException('Guzzle error while authentication', $e->getCode(), $e);
}
if (200 !== $response->getStatusCode()) {
throw new NotAuthenticatedException('Error while getting access_token');
}
$data = @json_decode($response->getBody(true), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Error while retrieving user info, unable to parse JSON.');
}
$this->session->remove('github.provider.state');
$this->session->set('github.provider.access_token', $data['access_token']);
try {
$request = $this->client->get('https://api.github.com/user');
$request->getQuery()->add('access_token', $data['access_token']);
$request->setHeader('Accept', 'application/json');
$response = $request->send();
} catch (GuzzleException $e) {
throw new NotAuthenticatedException('Guzzle error while authentication', $e->getCode(), $e);
}
$data = @json_decode($response->getBody(true), true);
if (200 !== $response->getStatusCode()) {
throw new NotAuthenticatedException('Error while retrieving user info, invalid status code.');
}
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Error while retrieving user info, unable to parse JSON.');
}
$this->session->set('github.provider.id', $data['id']);
}
/**
* {@inheritdoc}
*/
public function getToken()
{
if ('' === trim($this->session->get('github.provider.id'))) {
throw new NotAuthenticatedException('Github has not authenticated');
}
return new Token($this, $this->session->get('github.provider.id'));
}
/**
* {@inheritdoc}
*/
public function getIdentity()
{
$identity = new Identity();
try {
$request = $this->client->get('https://api.github.com/user');
$request->getQuery()->add('access_token', $this->session->get('github.provider.access_token'));
$request->setHeader('Accept', 'application/json');
$response = $request->send();
} catch (GuzzleException $e) {
throw new NotAuthenticatedException('Error while retrieving user info', $e->getCode(), $e);
}
if (200 !== $response->getStatusCode()) {
throw new NotAuthenticatedException('Error while retrieving user info');
}
$data = @json_decode($response->getBody(true), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Error while parsing json');
}
list($firstname, $lastname) = explode(' ', $data['name'], 2);
$identity->set(Identity::PROPERTY_EMAIL, $data['email']);
$identity->set(Identity::PROPERTY_FIRSTNAME, $firstname);
$identity->set(Identity::PROPERTY_ID, $data['id']);
$identity->set(Identity::PROPERTY_IMAGEURL, $data['avatar_url']);
$identity->set(Identity::PROPERTY_LASTNAME, $lastname);
return $identity;
}
/**
* {@inheritdoc}
*/
public function getIconURI()
{
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAAAwCAYAAAC4w'
. 'JK5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MO'
. 'mNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ'
. '2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6b'
. 'WV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgM'
. 'jAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJod'
. 'HRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZ'
. 'XNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZ'
. 'S5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL'
. '3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZ'
. 'G9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZ'
. 'DowMjgwMTE3NDA3MjA2ODExOEMxNEY3NEJCM0UzNjU4QyIgeG1wTU06RG9jdW1lbnRJR'
. 'D0ieG1wLmRpZDowMUNGRURDNTgzRUUxMUUyQjNFMDk5RUI0NTk2RTdBMiIgeG1wTU06S'
. 'W5zdGFuY2VJRD0ieG1wLmlpZDowMUNGRURDNDgzRUUxMUUyQjNFMDk5RUI0NTk2RTdBM'
. 'iIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChNYWNpbnRvc2gpI'
. 'j4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODUwR'
. 'DRBRkIxQjIwNjgxMThDMTRGNzRCQjNFMzY1OEMiIHN0UmVmOmRvY3VtZW50SUQ9Inhtc'
. 'C5kaWQ6MDI4MDExNzQwNzIwNjgxMThDMTRGNzRCQjNFMzY1OEMiLz4gPC9yZGY6RGVzY'
. '3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiP'
. 'z4ThndjAAAG5ElEQVR42tRaaUxUVxT+GB+YIqjEiCwiVBoLGgSRRRHUxjSKVutSfzTGu'
. 'CXUWnFNbGpKXYgLKribaGLin1ZjiwUxbq1xqaICKqKyKJtSwAUdBpBtYKbn3HlDGRiYY'
. 'cRk5pLDzH3v3vPud89yzzlv7LRaLWy9SfzPzs5OfMikIOrT7rs1NU0HYglo7VgSdjoUi'
. 'sKnT8NcXV1P0LURGo3G6nZc3dyc/evJkwvXrlv3nLrNRC0MRg+Cd9xBpVQ+blGrfZsaG'
. '9DSQvetTdVor9+/f3/FP2D0EurVEjUwNkm+LUDQqgWAhvp6aFpbrVL/7SVpEn24yl1eZ'
. 'IseBNtAX1YhlkCrlQIQTauVZBANMjXpQbBN2LP2MBBr9ljy2gYSveE1sxYp2qlTHxvyq'
. 'o6sObJ3tZPa3VCwx2KkNnB2SPKmKzqCkL0urM8rGfFTnQ67/zHoUNjaKS51MhyZbBeEX'
. 'pUskAR7tbuZmfjryhVkP8xBeUUFamtr4ezsDE8PDwQFjsaXU6YgPDSU3IniY0rCMsO+f'
. 'uMfJO7fj6LiYtF3cHCA19ChGEbU2NSE4pIS5BcU4NTp3+E7fDjWr16NSROjPg4InRDMB'
. '6FWq7Fj126cTk4Wuzt92jTMmzMbwUFBsLe3Nxh378EDnElJxcXLl7GCQMyfOxcbf9xgM'
. 'M5iK5djJ/a7g6tevSpVvn2LxoZ6swCsWrceN9PT8ZmvL3bEx8Pv8xEm5+UXPMVPcXEoL'
. 'CpCZEQEDiQl9hhIwNiQ7+kjl4gDwTcKo2atNU3bExIEgNCxY3H00EF86j3MrHmf+njj2'
. 'OFDCAsJEfO37Uwwa54B9YY63bh5C3/8mQIfb2/s37Mbu5L24sKlS5gRPQ0/LF8u4q+ys'
. 'n/R0NgIR8dPMNTTE5Ik4cjRYzh3/jxmz5qFfbt3YcGSpUhOScHkiRMxKSqy91wsTLhY9'
. 'kJ7Dx4UidT2rVvQz8kJz8vK0NTcjDOpZ5GSdg7GchG2Gf315y9eiHnbaP6CRYuJ3wFET'
. 'oiw2Gt1VicToswgN8peiN3lKH9/cc118GADkF2B17dBgwaJeaP8/ASf4pJS3M3ItFidF'
. 'B3VSUP/uqO/r14VY+fN/lr0ldXVyMjK7NHO8UYoVSoxn/lwu3Ltqsln68kMSaDbXXiY8'
. 'wgO5E2CAgNFPzUtDUpldY9AvKmqwlmax/PHEB/ml/PoUS8atonYqbKyEh50AlOGJcY9z'
. 's2zSI9z8/LFfDZ45ldeUWlxzKYwlnR0R7V1dehPoYS+z+eFJa2Fskc9jwH9+6OO+Jp6d'
. 'lees0PsJFI7aLupdDiTV6mhmEg/xtPD3SIQ7kOGtPFQ1dTAyalft881WxKsSqaMys3ND'
. 'RUU3PEZwP3I8REWPThi3Dgxn/kwPw93j94x7DaRydIwRgGjRqKZVCg7J0f0g4MCEREe3'
. 'iMAk6OixDyez3yYX8DIkd0+tz2ZdLFaE7vApyu3FPIurAbX6fSO3/QLncIzhZF2W26xl'
. '/DNnDnYEvdzGz/mwy0qMtJiSXSyCa0Jm+AI1YfipKvXb+Db+fPx4GE2bt+5gw1r1yBm8'
. 'WJk3r+P/YeP4J1S2TbHe9gwLFu0CCHBYzBwwADdo+gZhXRoXqMwnvnxvV6xiY7xkzHi5'
. 'HZFTIw4gXfuScTShQtxLzub8okDyHn8hPz9YwMA3F5QWDKcAj/2Qno+bAtbt+8QNS7mZ'
. '2eGZzTLO+kGaUzuSERYGGZGRyPtwgVs3LwZqyjo25mUhOTU1C5rRYVFxfAhiXBrJAAbN'
. '28RkviKgkbmp/2A2q/UlXcy1dbErsTrqjeUkmahquotEuK3wsXFBXezspCQmGQ0dmK+B'
. 'c+eYWdiIsVfJSIcXxsba9bzepBji+DJrF2RKOLctmkT9h06jHMXLyImdhUmRU6Ay0AXo'
. '+Of5OXh5u10YQO86BlTpxKAlYKP9gMr8AaZXVlJSenLinLUkdfpSbt9NwNHjx8XIbmp5'
. 'u3lhe+WLcP48DCLF/1F9HSDzK6TOllSKBgXForw0BDcJwO/cSsdufl5qHz5CvX19ZQUO'
. 'cLdbQhG+vljIuUM7N04F+nN2lanko0pF9tdC6aIlMlERbjXi3OSsaTIpiuAbaVY2HIZs'
. 'y12smVJ9LB4ZqUFZfnE1mpsWxLQ2sLria5BaBobG8rIh3tZM4pqleoddG9N9S/k26JY7'
. 'rT+dvJUXJNaXSFR3M9hpdbK/pSq6nfHTpw4RWvlYnGzHow+7OCXeP2JhhD5cOrMNS7oX'
. 'vBZywvJVnnxb4nKiUqJXhHVSO0GNEH3lv61fK3OSkGo5DXWymtuNfhZhLxoZ5kc5WvW8'
. 'iMVjaxC9TKAWr1aGfxABbqX27zwvvL3PlYGgqWhliXQLH/X/CfAALHSg9r3u8gEAAAAA'
. 'ElFTkSuQmCC';
}
/**
* {@inheritdoc}
*/
public static function create(UrlGenerator $generator, SessionInterface $session, array $options)
{
if (!isset($options['client-id'])) {
throw new InvalidArgumentException('Missing GitHub client-id parameter');
}
if (!isset($options['client-secret'])) {
throw new InvalidArgumentException('Missing GitHub client-secret parameter');
}
return new Github($generator, $session, new Guzzle('https://github.com/login/oauth'), $options['client-id'], $options['client-secret']);
}
}