mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 09:53:15 +00:00
Merge pull request #2620 from aynsix/PHRAS-2062-port-2061
PHRAS-2062 port 2061 authorize with providers
This commit is contained in:
@@ -50,13 +50,15 @@ class Facebook extends AbstractProvider
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate()
|
||||
public function authenticate(array $params = array())
|
||||
{
|
||||
$params = array_merge(['providerId' => $this->getId()], $params);
|
||||
|
||||
return new RedirectResponse(
|
||||
$this->facebook->getRedirectLoginHelper()->getLoginUrl(
|
||||
$this->generator->generate(
|
||||
'login_authentication_provider_callback',
|
||||
['providerId' => $this->getId()],
|
||||
$params,
|
||||
UrlGenerator::ABSOLUTE_URL
|
||||
),
|
||||
['email']
|
||||
|
@@ -78,8 +78,10 @@ class Github extends AbstractProvider
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate()
|
||||
public function authenticate(array $params = array())
|
||||
{
|
||||
$params = array_merge(['providerId' => $this->getId()], $params);
|
||||
|
||||
$state = $this->createState();
|
||||
|
||||
$this->session->set('github.provider.state', $state);
|
||||
@@ -90,7 +92,7 @@ class Github extends AbstractProvider
|
||||
'state' => $state,
|
||||
'redirect_uri' => $this->generator->generate(
|
||||
'login_authentication_provider_callback',
|
||||
['providerId' => $this->getId()],
|
||||
$params,
|
||||
UrlGenerator::ABSOLUTE_URL
|
||||
),
|
||||
], '', '&'));
|
||||
|
@@ -41,14 +41,6 @@ class GooglePlus extends AbstractProvider
|
||||
'https://www.googleapis.com/auth/userinfo.profile',
|
||||
]);
|
||||
|
||||
$this->client->setRedirectUri(
|
||||
$this->generator->generate(
|
||||
'login_authentication_provider_callback', [
|
||||
'providerId' => $this->getId(),
|
||||
], UrlGenerator::ABSOLUTE_URL
|
||||
)
|
||||
);
|
||||
|
||||
$this->client->setApprovalPrompt("auto");
|
||||
|
||||
if ($this->session->has('google-plus.provider.token')) {
|
||||
@@ -115,8 +107,18 @@ class GooglePlus extends AbstractProvider
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate()
|
||||
public function authenticate(array $params = array())
|
||||
{
|
||||
$params = array_merge(['providerId' => $this->getId()], $params);
|
||||
|
||||
$this->client->setRedirectUri(
|
||||
$this->generator->generate(
|
||||
'login_authentication_provider_callback',
|
||||
$params,
|
||||
UrlGenerator::ABSOLUTE_URL
|
||||
)
|
||||
);
|
||||
|
||||
$state = $this->createState();
|
||||
|
||||
$this->session->set('google-plus.provider.state', $state);
|
||||
|
@@ -78,8 +78,10 @@ class Linkedin extends AbstractProvider
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate()
|
||||
public function authenticate(array $params = array())
|
||||
{
|
||||
$params = array_merge(['providerId' => $this->getId()], $params);
|
||||
|
||||
$state = $this->createState();
|
||||
|
||||
$this->session->set('linkedin.provider.state', $state);
|
||||
@@ -91,7 +93,7 @@ class Linkedin extends AbstractProvider
|
||||
'state' => $state,
|
||||
'redirect_uri' => $this->generator->generate(
|
||||
'login_authentication_provider_callback',
|
||||
['providerId' => $this->getId()],
|
||||
$params,
|
||||
UrlGenerator::ABSOLUTE_URL
|
||||
),
|
||||
], '', '&'));
|
||||
|
@@ -43,9 +43,11 @@ interface ProviderInterface
|
||||
/**
|
||||
* Redirects to the actual authentication provider
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function authenticate();
|
||||
public function authenticate(array $params);
|
||||
|
||||
/**
|
||||
* Logout from the provider, removes the token if possible
|
||||
|
@@ -69,14 +69,16 @@ class Twitter extends AbstractProvider
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate()
|
||||
public function authenticate(array $params = array())
|
||||
{
|
||||
$params = array_merge(['providerId' => $this->getId()], $params);
|
||||
|
||||
$code = $this->twitter->request(
|
||||
'POST',
|
||||
$this->twitter->url('oauth/request_token', ''),
|
||||
['oauth_callback' => $this->generator->generate(
|
||||
'login_authentication_provider_callback',
|
||||
['providerId' => $this->getId()],
|
||||
$params,
|
||||
UrlGenerator::ABSOLUTE_URL
|
||||
)]
|
||||
);
|
||||
|
@@ -79,8 +79,10 @@ class Viadeo extends AbstractProvider
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function authenticate()
|
||||
public function authenticate(array $params = array())
|
||||
{
|
||||
$params = array_merge(['providerId' => $this->getId()], $params);
|
||||
|
||||
$state = $this->createState();
|
||||
|
||||
$this->session->set('viadeo.provider.state', $state);
|
||||
@@ -91,7 +93,7 @@ class Viadeo extends AbstractProvider
|
||||
'response_type' => 'code',
|
||||
'redirect_uri' => $this->generator->generate(
|
||||
'login_authentication_provider_callback',
|
||||
['providerId' => $this->getId()],
|
||||
$params,
|
||||
UrlGenerator::ABSOLUTE_URL
|
||||
),
|
||||
]));
|
||||
|
@@ -167,6 +167,103 @@ class OAuth2Controller extends Controller
|
||||
return '';
|
||||
}
|
||||
|
||||
public function authorizeWithProviderAction(Request $request, $providerId)
|
||||
{
|
||||
$context = new Context(Context::CONTEXT_OAUTH2_NATIVE);
|
||||
$this->dispatch(PhraseaEvents::PRE_AUTHENTICATE, new PreAuthenticate($request, $context));
|
||||
|
||||
//Check for auth params, send error or redirect if not valid
|
||||
$params = $this->oAuth2Adapter->getAuthorizationRequestParameters($request);
|
||||
|
||||
/** @var ApiApplicationRepository $appRepository */
|
||||
$appRepository = $this->app['repo.api-applications'];
|
||||
if (null === $client = $appRepository->findByClientId($params['client_id'])) {
|
||||
throw new NotFoundHttpException(sprintf('Application with client id %s could not be found', $params['client_id']));
|
||||
}
|
||||
|
||||
$provider = $this->findProvider($providerId);
|
||||
|
||||
return $provider->authenticate($request->query->all());
|
||||
}
|
||||
|
||||
public function authorizeCallbackAction(Request $request, $providerId)
|
||||
{
|
||||
$context = new Context(Context::CONTEXT_OAUTH2_NATIVE);
|
||||
$provider = $this->findProvider($providerId);
|
||||
$params = $this->oAuth2Adapter->getAuthorizationRequestParameters($request);
|
||||
|
||||
// triggers what's necessary
|
||||
try {
|
||||
$provider->onCallback($request);
|
||||
$token = $provider->getToken();
|
||||
} catch (NotAuthenticatedException $e) {
|
||||
$this->getSession()->getFlashBag()->add('error', $this->app->trans('Unable to authenticate with %provider_name%', ['%provider_name%' => $provider->getName()]));
|
||||
|
||||
return $this->app->redirectPath('oauth2_authorize', array_merge(array('error' => 'login'), $params));
|
||||
}
|
||||
|
||||
$userAuthProvider = $this->getUserAuthProviderRepository()
|
||||
->findWithProviderAndId($token->getProvider()->getId(), $token->getId());
|
||||
|
||||
if($userAuthProvider == null){
|
||||
unset($params['state']);
|
||||
|
||||
return $this->app->redirectPath('oauth2_authorize', array_merge(array('error' => 'login'), $params));
|
||||
}
|
||||
|
||||
try {
|
||||
$user = $this->getAuthenticationSuggestionFinder()->find($token);
|
||||
} catch (NotAuthenticatedException $e) {
|
||||
$this->app->addFlash('error', $this->app->trans('Unable to retrieve provider identity'));
|
||||
|
||||
return $this->app->redirectPath('oauth2_authorize', array_merge(array('error' => 'login'), $params));
|
||||
}
|
||||
|
||||
$this->getAuthenticator()->openAccount($userAuthProvider->getUser());
|
||||
$event = new PostAuthenticate($request, new Response(), $user, $context);
|
||||
$this->dispatch(PhraseaEvents::POST_AUTHENTICATE, $event);
|
||||
|
||||
/** @var ApiApplicationRepository $appRepository */
|
||||
$appRepository = $this->app['repo.api-applications'];
|
||||
if (null === $client = $appRepository->findByClientId($params['client_id'])) {
|
||||
throw new NotFoundHttpException(sprintf('Application with client id %s could not be found', $params['client_id']));
|
||||
}
|
||||
|
||||
$this->oAuth2Adapter->setClient($client);
|
||||
|
||||
//check if current client is already authorized by current user
|
||||
$clients = $appRepository->findAuthorizedAppsByUser($this->getAuthenticatedUser());
|
||||
$appAuthorized = false;
|
||||
|
||||
foreach ($clients as $authClient) {
|
||||
if ($client->getClientId() == $authClient->getClientId()) {
|
||||
$appAuthorized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$account = $this->oAuth2Adapter->updateAccount($this->getAuthenticatedUser());
|
||||
|
||||
$params['account_id'] = $account->getId();
|
||||
|
||||
//if native app show template
|
||||
if ($this->oAuth2Adapter->isNativeApp($params['redirect_uri'])) {
|
||||
$params = $this->oAuth2Adapter->finishNativeClientAuthorization($appAuthorized, $params);
|
||||
|
||||
$r = new Response($this->render("api/auth/native_app_access_token.html.twig", $params));
|
||||
$r->headers->set('Content-Type', 'text/html');
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
$this->oAuth2Adapter->finishClientAuthorization($appAuthorized, $params);
|
||||
|
||||
// As OAuth2 library already outputs response content, we need to send an empty
|
||||
// response to avoid breaking silex controller
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* TOKEN ENDPOINT
|
||||
* Token endpoint - used to exchange an authorization grant for an access token.
|
||||
@@ -206,4 +303,41 @@ class OAuth2Controller extends Controller
|
||||
{
|
||||
return $this->app['manipulator.api-account'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $providerId
|
||||
* @return ProviderInterface
|
||||
*/
|
||||
private function findProvider($providerId)
|
||||
{
|
||||
try {
|
||||
return $this->getAuthenticationProviders()->get($providerId);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new NotFoundHttpException('The requested provider does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ProvidersCollection
|
||||
*/
|
||||
private function getAuthenticationProviders()
|
||||
{
|
||||
return $this->app['authentication.providers'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UsrAuthProviderRepository
|
||||
*/
|
||||
private function getUserAuthProviderRepository()
|
||||
{
|
||||
return $this->app['repo.usr-auth-providers'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SuggestionFinder
|
||||
*/
|
||||
private function getAuthenticationSuggestionFinder()
|
||||
{
|
||||
return $this->app['authentication.suggestion-finder'];
|
||||
}
|
||||
}
|
||||
|
@@ -18,9 +18,12 @@ use Silex\Application;
|
||||
use Silex\ControllerCollection;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Silex\ServiceProviderInterface;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
|
||||
class OAuth2 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.oauth2'] = $app->share(function (PhraseaApplication $app) {
|
||||
@@ -35,6 +38,16 @@ class OAuth2 extends Api implements ControllerProviderInterface, ServiceProvider
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$firewall = $this->getFirewall($app);
|
||||
|
||||
$requireUnauthenticated = function () use ($firewall) {
|
||||
if (null !== $response = $firewall->requireNotAuthenticated()) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
if (! $this->isApiEnabled($app)) {
|
||||
return $app['controllers_factory'];
|
||||
}
|
||||
@@ -48,6 +61,15 @@ class OAuth2 extends Api implements ControllerProviderInterface, ServiceProvider
|
||||
|
||||
$controllers->post('/token', 'controller.oauth2:tokenAction');
|
||||
|
||||
$controllers->get('/provider/{providerId}/authorize/', 'controller.oauth2:authorizeWithProviderAction')
|
||||
->before($requireUnauthenticated)
|
||||
->bind('oauth2_provider_authorize');
|
||||
|
||||
// AuthProviders callbacks
|
||||
$controllers->get('/provider/{providerId}/callback/', 'controller.oauth2:authorizeCallbackAction')
|
||||
->before($requireUnauthenticated)
|
||||
->bind('login_authentication_provider_callback');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user