Normalize exceptions

This commit is contained in:
Romain Neutron
2013-05-13 19:37:01 +02:00
parent d515da0b88
commit 5b189276ef
9 changed files with 299 additions and 148 deletions

View File

@@ -63,6 +63,9 @@ class Facebook extends AbstractProvider
))); )));
} }
/**
* {@inheritdoc}
*/
public function logout() public function logout()
{ {
$this->facebook->destroySession(); $this->facebook->destroySession();
@@ -108,7 +111,7 @@ class Facebook extends AbstractProvider
$identity->set(Identity::PROPERTY_USERNAME, $data['username']); $identity->set(Identity::PROPERTY_USERNAME, $data['username']);
} catch (\FacebookApiException $e) { } catch (\FacebookApiException $e) {
throw new RuntimeException('Unable to get profile informations', $e->getCode(), $e); throw new NotAuthenticatedException('Unable to get profile informations', $e->getCode(), $e);
} }
return $identity; return $identity;
@@ -130,7 +133,7 @@ class Facebook extends AbstractProvider
public function getToken() public function getToken()
{ {
if (0 >= $this->facebook->getUser()) { if (0 >= $this->facebook->getUser()) {
throw new RuntimeException('Provider has not authenticated'); throw new NotAuthenticatedException('Provider has not authenticated');
} }
return new Token($this, $this->facebook->getUser()); return new Token($this, $this->facebook->getUser());

View File

@@ -18,6 +18,7 @@ use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Guzzle\Http\Client as Guzzle; use Guzzle\Http\Client as Guzzle;
use Guzzle\Http\ClientInterface; use Guzzle\Http\ClientInterface;
use Guzzle\Common\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGenerator;
@@ -97,6 +98,9 @@ class Github extends AbstractProvider
), '', '&')); ), '', '&'));
} }
/**
* {@inheritdoc}
*/
public function logout() public function logout()
{ {
// GitHub does not support tokens revocation // GitHub does not support tokens revocation
@@ -108,13 +112,14 @@ class Github extends AbstractProvider
public function onCallback(Request $request) public function onCallback(Request $request)
{ {
if (!$this->session->has('github.provider.state')) { if (!$this->session->has('github.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('No state value in session ; CSRF try ?');
} }
if ($request->query->get('state') !== $this->session->remove('github.provider.state')) { if ($request->query->get('state') !== $this->session->remove('github.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('Invalid state value ; CSRF try ?');
} }
try {
$guzzleRequest = $this->client->post('access_token'); $guzzleRequest = $this->client->post('access_token');
$guzzleRequest->addPostFields(array( $guzzleRequest->addPostFields(array(
@@ -129,27 +134,42 @@ class Github extends AbstractProvider
)); ));
$guzzleRequest->setHeader('Accept', 'application/json'); $guzzleRequest->setHeader('Accept', 'application/json');
$response = $guzzleRequest->send(); $response = $guzzleRequest->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Guzzle error while authentication', $e->getCode(), $e);
throw new RuntimeException('Error while getting access_token');
} }
$data = json_decode($response->getBody(true), true); 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->remove('github.provider.state');
$this->session->set('github.provider.access_token', $data['access_token']); $this->session->set('github.provider.access_token', $data['access_token']);
try {
$request = $this->client->get('https://api.github.com/user'); $request = $this->client->get('https://api.github.com/user');
$request->getQuery()->add('access_token', $data['access_token']); $request->getQuery()->add('access_token', $data['access_token']);
$request->setHeader('Accept', 'application/json'); $request->setHeader('Accept', 'application/json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Guzzle error while authentication', $e->getCode(), $e);
throw new RuntimeException('Error while retrieving user info');
} }
$data = json_decode($response->getBody(true), true); $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']); $this->session->set('github.provider.id', $data['id']);
} }
@@ -160,7 +180,7 @@ class Github extends AbstractProvider
public function getToken() public function getToken()
{ {
if ('' === trim($this->session->get('github.provider.id'))) { if ('' === trim($this->session->get('github.provider.id'))) {
throw new RuntimeException('Github has not authenticated'); throw new NotAuthenticatedException('Github has not authenticated');
} }
return new Token($this, $this->session->get('github.provider.id')); return new Token($this, $this->session->get('github.provider.id'));
@@ -173,17 +193,25 @@ class Github extends AbstractProvider
{ {
$identity = new Identity(); $identity = new Identity();
try {
$request = $this->client->get('https://api.github.com/user'); $request = $this->client->get('https://api.github.com/user');
$request->getQuery()->add('access_token', $this->session->get('github.provider.access_token')); $request->getQuery()->add('access_token', $this->session->get('github.provider.access_token'));
$request->setHeader('Accept', 'application/json'); $request->setHeader('Accept', 'application/json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Error while retrieving user info', $e->getCode(), $e);
throw new RuntimeException('Error while retrieving user info');
} }
$data = json_decode($response->getBody(true), true); 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); list($firstname, $lastname) = explode(' ', $data['name'], 2);

View File

@@ -18,6 +18,7 @@ use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Guzzle\Http\Client as Guzzle; use Guzzle\Http\Client as Guzzle;
use Guzzle\Http\ClientInterface; use Guzzle\Http\ClientInterface;
use Guzzle\Common\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGenerator;
@@ -147,9 +148,16 @@ class GooglePlus extends AbstractProvider
return new RedirectResponse($this->client->createAuthUrl()); return new RedirectResponse($this->client->createAuthUrl());
} }
/**
* {@inheritdoc}
*/
public function logout() public function logout()
{ {
try {
$this->client->revokeToken(); $this->client->revokeToken();
} catch (\Google_Exception $e) {
throw new RuntimeException('Unable to logout from Google+', $e->getCode(), $e);
}
} }
/** /**
@@ -158,17 +166,26 @@ class GooglePlus extends AbstractProvider
public function onCallback(Request $request) public function onCallback(Request $request)
{ {
if (!$this->session->has('google-plus.provider.state')) { if (!$this->session->has('google-plus.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('No state value in session ; CSRF try ?');
} }
if ($request->query->get('state') !== $this->session->remove('google-plus.provider.state')) { if ($request->query->get('state') !== $this->session->remove('google-plus.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('Invalid state value ; CSRF try ?');
} }
try {
$this->client->authenticate($request->query->get('code')); $this->client->authenticate($request->query->get('code'));
$token = json_decode($this->client->getAccessToken(), true); $token = @json_decode($this->client->getAccessToken(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Unable to parse Google+ JSON', $e->getCode(), $e);
}
$ticket = $this->client->verifyIdToken($token['id_token']); $ticket = $this->client->verifyIdToken($token['id_token']);
} catch (\Google_Exception $e) {
throw new NotAuthenticatedException('Unable to authenticate through Google+', $e->getCode(), $e);
}
$this->session->set('google-plus.provider.token', json_encode($token)); $this->session->set('google-plus.provider.token', json_encode($token));
$this->session->set('google-plus.provider.id', $ticket->getUserId()); $this->session->set('google-plus.provider.id', $ticket->getUserId());
@@ -180,7 +197,7 @@ class GooglePlus extends AbstractProvider
public function getToken() public function getToken()
{ {
if (!ctype_digit($this->session->get('google-plus.provider.id'))) { if (!ctype_digit($this->session->get('google-plus.provider.id'))) {
throw new RuntimeException('Google + has not authenticated'); throw new NotAuthenticatedException('Google + has not authenticated');
} }
return new Token($this, $this->session->get('google-plus.provider.id')); return new Token($this, $this->session->get('google-plus.provider.id'));
@@ -193,24 +210,37 @@ class GooglePlus extends AbstractProvider
{ {
$identity = new Identity(); $identity = new Identity();
$token = json_decode($this->session->get('google-plus.provider.token'), true); $token = @json_decode($this->session->get('google-plus.provider.token'), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Unable to parse Google+ JSON');
}
try {
$request = $this->guzzle->get(sprintf( $request = $this->guzzle->get(sprintf(
'https://www.googleapis.com/oauth2/v1/tokeninfo?%s', 'https://www.googleapis.com/oauth2/v1/tokeninfo?%s',
http_build_query(array('access_token' => $token['access_token']), '', '&') http_build_query(array('access_token' => $token['access_token']), '', '&')
)); ));
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
throw new NotAuthenticatedException('Unable to retrieve Google+ tokeninfo', $e->getCode(), $e);
}
if (200 !== $response->getStatusCode()) { if (200 !== $response->getStatusCode()) {
throw new RuntimeException('Error while retrieving user info'); throw new NotAuthenticatedException('Error while retrieving user info');
} }
try{ try{
$plusData = $this->plus->people->get('me'); $plusData = $this->plus->people->get('me');
} catch (\Google_Exception $e) { } catch (\Google_Exception $e) {
throw new RuntimeException('Error while retrieving user info', $e->getCode(), $e); throw new NotAuthenticatedException('Error while retrieving user info', $e->getCode(), $e);
} }
$data = json_decode($response->getBody(true), true); $data = @json_decode($response->getBody(true), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Unable to parse Google+ JSON');
}
$identity->set(Identity::PROPERTY_EMAIL, $data['email']); $identity->set(Identity::PROPERTY_EMAIL, $data['email']);

View File

@@ -18,6 +18,7 @@ use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Guzzle\Http\Client as Guzzle; use Guzzle\Http\Client as Guzzle;
use Guzzle\Http\ClientInterface; use Guzzle\Http\ClientInterface;
use Guzzle\Common\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGenerator;
@@ -98,6 +99,9 @@ class Linkedin extends AbstractProvider
), '', '&')); ), '', '&'));
} }
/**
* {@inheritdoc}
*/
public function logout() public function logout()
{ {
// LinkedIn does not provide Oauth2 token revocation // LinkedIn does not provide Oauth2 token revocation
@@ -109,13 +113,14 @@ class Linkedin extends AbstractProvider
public function onCallback(Request $request) public function onCallback(Request $request)
{ {
if (!$this->session->has('linkedin.provider.state')) { if (!$this->session->has('linkedin.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('No state value ; CSRF try ?');
} }
if ($request->query->get('state') !== $this->session->remove('linkedin.provider.state')) { if ($request->query->get('state') !== $this->session->remove('linkedin.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('Invalid state value ; CSRF try ?');
} }
try {
$guzzleRequest = $this->client->post('https://www.linkedin.com/uas/oauth2/accessToken?' . http_build_query(array( $guzzleRequest = $this->client->post('https://www.linkedin.com/uas/oauth2/accessToken?' . http_build_query(array(
'grant_type' => 'authorization_code', 'grant_type' => 'authorization_code',
'code' => $request->query->get('code'), 'code' => $request->query->get('code'),
@@ -128,27 +133,43 @@ class Linkedin extends AbstractProvider
'client_secret' => $this->secret, 'client_secret' => $this->secret,
), '', '&')); ), '', '&'));
$response = $guzzleRequest->send(); $response = $guzzleRequest->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Unable to query LinkedIn access token', $e->getCode(), $e);
throw new RuntimeException('Error while getting access_token'); }
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('Unable to parse LinkedIn JSON');
} }
$data = json_decode($response->getBody(true), true);
$this->session->remove('linkedin.provider.state'); $this->session->remove('linkedin.provider.state');
$this->session->set('linkedin.provider.access_token', $data['access_token']); $this->session->set('linkedin.provider.access_token', $data['access_token']);
try {
$request = $this->client->get('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,positions,industry,picture-url,email-address)'); $request = $this->client->get('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,positions,industry,picture-url,email-address)');
$request->getQuery() $request->getQuery()
->add('oauth2_access_token', $data['access_token']) ->add('oauth2_access_token', $data['access_token'])
->add('format', 'json'); ->add('format', 'json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Error while retrieving linkedin user informations.');
throw new RuntimeException('Error while retrieving user info');
} }
$data = json_decode($response->getBody(true), true); 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('Unable to parse LinkedIn JSON');
}
$this->session->set('linkedin.provider.id', $data['id']); $this->session->set('linkedin.provider.id', $data['id']);
} }
@@ -159,7 +180,7 @@ class Linkedin extends AbstractProvider
public function getToken() public function getToken()
{ {
if ('' === trim($this->session->get('linkedin.provider.id'))) { if ('' === trim($this->session->get('linkedin.provider.id'))) {
throw new RuntimeException('Linkedin has not authenticated'); throw new NotAuthenticatedException('Linkedin has not authenticated');
} }
return new Token($this, $this->session->get('linkedin.provider.id')); return new Token($this, $this->session->get('linkedin.provider.id'));
@@ -172,18 +193,26 @@ class Linkedin extends AbstractProvider
{ {
$identity = new Identity(); $identity = new Identity();
try {
$request = $this->client->get('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,positions,industry,picture-url;secure=true,email-address)'); $request = $this->client->get('https://api.linkedin.com/v1/people/~:(id,first-name,last-name,positions,industry,picture-url;secure=true,email-address)');
$request->getQuery() $request->getQuery()
->add('oauth2_access_token', $this->session->get('linkedin.provider.access_token')) ->add('oauth2_access_token', $this->session->get('linkedin.provider.access_token'))
->add('format', 'json'); ->add('format', 'json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Unable to fetch LinkedIn identity', $e->getCode(), $e);
throw new RuntimeException('Error while retrieving user info');
} }
$data = json_decode($response->getBody(true), true); 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('Unable to parse Linkedin JSON identity');
}
if (0 < $data['positions']['_total']) { if (0 < $data['positions']['_total']) {
$position = array_pop($data['positions']['values']); $position = array_pop($data['positions']['values']);

View File

@@ -13,11 +13,13 @@ namespace Alchemy\Phrasea\Authentication\Provider;
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Authentication\Provider\Token\Identity; use Alchemy\Phrasea\Authentication\Provider\Token\Identity;
use Alchemy\Phrasea\Authentication\Provider\Token\Token;
use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Alchemy\Phrasea\Exception\RuntimeException;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Alchemy\Phrasea\Authentication\Provider\Token\Token;
interface ProviderInterface interface ProviderInterface
{ {
@@ -48,6 +50,8 @@ interface ProviderInterface
/** /**
* Logout from the provider, removes the token if possible * Logout from the provider, removes the token if possible
*
* @throws RuntimeException In case logout fails.
*/ */
public function logout(); public function logout();
@@ -57,6 +61,8 @@ interface ProviderInterface
* *
* @param Application $app * @param Application $app
* @param Request $request * @param Request $request
*
* @throws NotAuthenticatedException In case the authentication failed.
*/ */
public function onCallback(Request $request); public function onCallback(Request $request);
@@ -64,6 +70,8 @@ interface ProviderInterface
* Returns the identity * Returns the identity
* *
* @return Identity * @return Identity
*
* @throws NotAuthenticatedException In case the provider is not connected
*/ */
public function getIdentity(); public function getIdentity();
@@ -71,6 +79,8 @@ interface ProviderInterface
* Returns a Token * Returns a Token
* *
* @return Token * @return Token
*
* @throws NotAuthenticatedException In case the provider is not connected
*/ */
public function getToken(); public function getToken();

View File

@@ -84,7 +84,7 @@ class Twitter extends AbstractProvider
); );
if ($code != 200) { if ($code != 200) {
throw new RuntimeException('Unable to request twitter token'); throw new NotAuthenticatedException('Unable to request twitter token');
} }
$oauth = $this->twitter->extract_params($this->twitter->response['response']); $oauth = $this->twitter->extract_params($this->twitter->response['response']);
@@ -98,6 +98,9 @@ class Twitter extends AbstractProvider
)); ));
} }
/**
* {@inheritdoc}
*/
public function logout() public function logout()
{ {
// Twitter does no timplement token revocation // Twitter does no timplement token revocation
@@ -120,7 +123,7 @@ class Twitter extends AbstractProvider
); );
if ($code != 200) { if ($code != 200) {
throw new RuntimeException('Unable to get twitter access token'); throw new NotAuthenticatedException('Unable to get twitter access token');
} }
$access_token = $this->twitter->extract_params($this->twitter->response['response']); $access_token = $this->twitter->extract_params($this->twitter->response['response']);
@@ -135,10 +138,14 @@ class Twitter extends AbstractProvider
); );
if ($code != 200) { if ($code != 200) {
throw new RuntimeException('Unable to get twitter credentials'); throw new NotAuthenticatedException('Unable to get twitter credentials');
} }
$resp = json_decode($this->twitter->response['response'], true); $resp = @json_decode($this->twitter->response['response'], true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Unable to parse Twitter JSON response.');
}
$this->session->set('twitter.provider.id', $resp['id']); $this->session->set('twitter.provider.id', $resp['id']);
} }
@@ -149,7 +156,7 @@ class Twitter extends AbstractProvider
public function getToken() public function getToken()
{ {
if (0 >= $this->session->get('twitter.provider.id')) { if (0 >= $this->session->get('twitter.provider.id')) {
throw new RuntimeException('Provider has not authenticated'); throw new NotAuthenticatedException('Provider has not authenticated');
} }
return new Token($this, $this->session->get('twitter.provider.id')); return new Token($this, $this->session->get('twitter.provider.id'));
@@ -170,10 +177,14 @@ class Twitter extends AbstractProvider
); );
if ($code != 200) { if ($code != 200) {
throw new RuntimeException('Unable to retrieve twitter identity'); throw new NotAuthenticatedException('Unable to retrieve twitter identity');
} }
$resp = json_decode($this->twitter->response['response'], true); $resp = @json_decode($this->twitter->response['response'], true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Unable to parse Twitter Identity JSON response.');
}
$identity = new Identity(); $identity = new Identity();

View File

@@ -11,12 +11,13 @@
namespace Alchemy\Phrasea\Authentication\Provider; namespace Alchemy\Phrasea\Authentication\Provider;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Authentication\Provider\Token\Token; use Alchemy\Phrasea\Authentication\Provider\Token\Token;
use Alchemy\Phrasea\Authentication\Provider\Token\Identity; use Alchemy\Phrasea\Authentication\Provider\Token\Identity;
use Alchemy\Phrasea\Exception\RuntimeException; use Alchemy\Phrasea\Exception\RuntimeException;
use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
use Guzzle\Http\Client as Guzzle; use Guzzle\Http\Client as Guzzle;
use Guzzle\Http\ClientInterface; use Guzzle\Http\ClientInterface;
use Guzzle\Common\Exception\GuzzleException;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGenerator;
@@ -96,8 +97,12 @@ class Viadeo extends AbstractProvider
))); )));
} }
/**
* {@inheritdoc}
*/
public function logout() public function logout()
{ {
try {
$request = $this->client->get('https://secure.viadeo.com/oauth-provider/revoke_access_token2'); $request = $this->client->get('https://secure.viadeo.com/oauth-provider/revoke_access_token2');
$request $request
->getQuery() ->getQuery()
@@ -108,6 +113,9 @@ class Viadeo extends AbstractProvider
$request->setHeader('Accept', 'application/json'); $request->setHeader('Accept', 'application/json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
throw new RuntimeException('Unable to revoke token from Viadeo', $e->getCode(), $e);
}
if (302 !== $response->getStatusCode()) { if (302 !== $response->getStatusCode()) {
throw new RuntimeException('Error while revoking access token'); throw new RuntimeException('Error while revoking access token');
@@ -120,13 +128,14 @@ class Viadeo extends AbstractProvider
public function onCallback(Request $request) public function onCallback(Request $request)
{ {
if (!$this->session->has('viadeo.provider.state')) { if (!$this->session->has('viadeo.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('No state value ; CSRF try ?');
} }
if ($request->query->get('state') !== $this->session->remove('viadeo.provider.state')) { if ($request->query->get('state') !== $this->session->remove('viadeo.provider.state')) {
throw new RuntimeException('Invalid state value ; CSRF try ?'); throw new NotAuthenticatedException('Invalid state value ; CSRF try ?');
} }
try {
$guzzleRequest = $this->client->post('https://secure.viadeo.com/oauth-provider/access_token2'); $guzzleRequest = $this->client->post('https://secure.viadeo.com/oauth-provider/access_token2');
$guzzleRequest->addPostFields(array( $guzzleRequest->addPostFields(array(
@@ -138,27 +147,42 @@ class Viadeo extends AbstractProvider
)); ));
$guzzleRequest->setHeader('Accept', 'application/json'); $guzzleRequest->setHeader('Accept', 'application/json');
$response = $guzzleRequest->send(); $response = $guzzleRequest->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Unable to retrieve viadeo access token', $e->getCode(), $e);
throw new RuntimeException('Error while getting access_token');
} }
$data = json_decode($response->getBody(true), true); 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('Unable to parse Viadeo access_token response.');
}
$this->session->remove('viadeo.provider.state'); $this->session->remove('viadeo.provider.state');
$this->session->set('viadeo.provider.access_token', $data['access_token']); $this->session->set('viadeo.provider.access_token', $data['access_token']);
try {
$request = $this->client->get('https://api.viadeo.com/me?secure=true'); $request = $this->client->get('https://api.viadeo.com/me?secure=true');
$request->getQuery()->add('access_token', $data['access_token']); $request->getQuery()->add('access_token', $data['access_token']);
$request->setHeader('Accept', 'application/json'); $request->setHeader('Accept', 'application/json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Unable to retrieve viadeo user informations', $e->getCode(), $e);
throw new RuntimeException('Error while retrieving user info');
} }
$data = json_decode($response->getBody(true), true); 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('Unable to parse Viadeo user informations response.');
}
$this->session->set('viadeo.provider.id', $data['id']); $this->session->set('viadeo.provider.id', $data['id']);
} }
@@ -169,7 +193,7 @@ class Viadeo extends AbstractProvider
public function getToken() public function getToken()
{ {
if ('' === trim($this->session->get('viadeo.provider.id'))) { if ('' === trim($this->session->get('viadeo.provider.id'))) {
throw new RuntimeException('Viadeo has not authenticated'); throw new NotAuthenticatedException('Viadeo has not authenticated');
} }
return new Token($this, $this->session->get('viadeo.provider.id')); return new Token($this, $this->session->get('viadeo.provider.id'));
@@ -182,18 +206,26 @@ class Viadeo extends AbstractProvider
{ {
$identity = new Identity(); $identity = new Identity();
try {
$request = $this->client->get('https://api.viadeo.com/me?secure=true'); $request = $this->client->get('https://api.viadeo.com/me?secure=true');
$request->getQuery() $request->getQuery()
->add('access_token', $this->session->get('viadeo.provider.access_token')); ->add('access_token', $this->session->get('viadeo.provider.access_token'));
$request->setHeader('Accept', 'application/json'); $request->setHeader('Accept', 'application/json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Unable to retrieve Viadeo identity');
throw new RuntimeException('Error while retrieving user info');
} }
$data = json_decode($response->getBody(true), true); 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('Unable to parse Viadeo identity.');
}
$identity->set(Identity::PROPERTY_FIRSTNAME, $data['first_name']); $identity->set(Identity::PROPERTY_FIRSTNAME, $data['first_name']);
$identity->set(Identity::PROPERTY_ID, $data['id']); $identity->set(Identity::PROPERTY_ID, $data['id']);
@@ -201,17 +233,25 @@ class Viadeo extends AbstractProvider
$identity->set(Identity::PROPERTY_LASTNAME, $data['last_name']); $identity->set(Identity::PROPERTY_LASTNAME, $data['last_name']);
$identity->set(Identity::PROPERTY_USERNAME, $data['nickname']); $identity->set(Identity::PROPERTY_USERNAME, $data['nickname']);
try {
$request = $this->client->get('https://api.viadeo.com/me/career?secure=true'); $request = $this->client->get('https://api.viadeo.com/me/career?secure=true');
$request->getQuery()->add('access_token', $this->session->get('viadeo.provider.access_token')); $request->getQuery()->add('access_token', $this->session->get('viadeo.provider.access_token'));
$request->setHeader('Accept', 'application/json'); $request->setHeader('Accept', 'application/json');
$response = $request->send(); $response = $request->send();
} catch (GuzzleException $e) {
if (200 !== $response->getStatusCode()) { throw new NotAuthenticatedException('Unable to retrieve Viadeo career information.');
throw new RuntimeException('Error while retrieving company info');
} }
$data = json_decode($response->getBody(true), true); if (200 !== $response->getStatusCode()) {
throw new NotAuthenticatedException('Error while retrieving company info');
}
$data = @json_decode($response->getBody(true), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new NotAuthenticatedException('Unable to parse Viadeo career informations.');
}
if (0 < count($data['data'])) { if (0 < count($data['data'])) {
$job = array_shift($data['data']); $job = array_shift($data['data']);

View File

@@ -90,7 +90,7 @@ abstract class ProviderTestCase extends \PHPUnit_Framework_TestCase
/** /**
* @dataProvider provideDataForFailingCallback * @dataProvider provideDataForFailingCallback
* @expectedException Alchemy\Phrasea\Exception\RuntimeException * @expectedException Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException
*/ */
public function testOnCallbackWithFailure($provider, $request) public function testOnCallbackWithFailure($provider, $request)
{ {
@@ -109,7 +109,7 @@ abstract class ProviderTestCase extends \PHPUnit_Framework_TestCase
} }
/** /**
* @expectedException Alchemy\Phrasea\Exception\RuntimeException * @expectedException Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException
*/ */
public function testGetTokenWhenNotAuthenticated() public function testGetTokenWhenNotAuthenticated()
{ {
@@ -129,7 +129,7 @@ abstract class ProviderTestCase extends \PHPUnit_Framework_TestCase
} }
/** /**
* @expectedException Alchemy\Phrasea\Exception\RuntimeException * @expectedException Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException
*/ */
public function testGetIdentityWhenNotAuthenticated() public function testGetIdentityWhenNotAuthenticated()
{ {

View File

@@ -31,7 +31,7 @@ class TwitterTest extends ProviderTestCase
} }
/** /**
* @expectedException Alchemy\Phrasea\Exception\RuntimeException * @expectedException Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException
*/ */
public function testAuthenticateWithFailure() public function testAuthenticateWithFailure()
{ {