View source
<?php
namespace Drupal\simple_oauth\Controller;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\simple_oauth\Entities\UserEntity;
use Drupal\simple_oauth\KnownClientsRepositoryInterface;
use Drupal\simple_oauth\Plugin\Oauth2GrantManagerInterface;
use GuzzleHttp\Psr7\Response;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
use League\OAuth2\Server\Exception\OAuthServerException;
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
class Oauth2AuthorizeController extends ControllerBase {
protected $messageFactory;
protected $grantManager;
protected $configFactory;
protected $knownClientRepository;
public function __construct(HttpMessageFactoryInterface $message_factory, Oauth2GrantManagerInterface $grant_manager, ConfigFactoryInterface $config_factory, KnownClientsRepositoryInterface $known_clients_repository) {
$this->messageFactory = $message_factory;
$this->grantManager = $grant_manager;
$this->configFactory = $config_factory;
$this->knownClientRepository = $known_clients_repository;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('psr7.http_message_factory'), $container
->get('plugin.manager.oauth2_grant.processor'), $container
->get('config.factory'), $container
->get('simple_oauth.known_clients'));
}
public function authorize(Request $request) {
$client_uuid = $request
->get('client_id');
if (empty($client_uuid)) {
return OAuthServerException::invalidClient()
->generateHttpResponse(new Response());
}
$consumer_storage = $this
->entityTypeManager()
->getStorage('consumer');
$client_drupal_entities = $consumer_storage
->loadByProperties([
'uuid' => $client_uuid,
]);
if (empty($client_drupal_entities)) {
return OAuthServerException::invalidClient()
->generateHttpResponse(new Response());
}
$client_drupal_entity = reset($client_drupal_entities);
$is_third_party = $client_drupal_entity
->get('third_party')->value;
$scopes = [];
if ($request->query
->get('scope')) {
$scopes = explode(' ', $request->query
->get('scope'));
}
if ($this
->currentUser()
->isAnonymous()) {
$message = $this
->t('An external client application is requesting access to your data in this site. Please log in first to authorize the operation.');
$this
->messenger()
->addStatus($message);
$destination = Url::fromRoute('oauth2_token.authorize', [], [
'query' => UrlHelper::parse('/?' . $request
->getQueryString())['query'],
]);
$url = Url::fromRoute('user.login', [], [
'query' => [
'destination' => $destination
->toString(),
],
]);
return RedirectResponse::create($url
->toString(), 302, $request->headers
->all());
}
elseif (!$is_third_party || $this
->isKnownClient($client_uuid, $scopes)) {
if ($request
->get('response_type') == 'code') {
$grant_type = 'code';
}
elseif ($request
->get('response_type') == 'token') {
$grant_type = 'implicit';
}
else {
$grant_type = NULL;
}
try {
$server = $this->grantManager
->getAuthorizationServer($grant_type, $client_drupal_entity);
$ps7_request = $this->messageFactory
->createRequest($request);
$auth_request = $server
->validateAuthorizationRequest($ps7_request);
} catch (OAuthServerException $exception) {
$this
->messenger()
->addError($this
->t('Fatal error. Unable to get the authorization server.'));
watchdog_exception('simple_oauth', $exception);
return RedirectResponse::create(Url::fromRoute('<front>')
->toString());
}
if ($auth_request) {
$can_grant_codes = $this
->currentUser()
->hasPermission('grant simple_oauth codes');
return static::redirectToCallback($auth_request, $server, $this->currentUser, $can_grant_codes);
}
}
return $this
->formBuilder()
->getForm(Oauth2AuthorizeForm::class);
}
public static function redirectToCallback(AuthorizationRequest $auth_request, AuthorizationServer $server, AccountInterface $current_user, $can_grant_codes, $remembers_clients = FALSE, KnownClientsRepositoryInterface $known_clients_repository = NULL) {
$user_entity = new UserEntity();
$user_entity
->setIdentifier($current_user
->id());
$auth_request
->setUser($user_entity);
$auth_request
->setAuthorizationApproved($can_grant_codes);
$response = $server
->completeAuthorizationRequest($auth_request, new Response());
if ($remembers_clients) {
$scopes = array_map(function (ScopeEntityInterface $scope) {
return $scope
->getIdentifier();
}, $auth_request
->getScopes());
$known_clients_repository = $known_clients_repository instanceof KnownClientsRepositoryInterface ? $known_clients_repository : \Drupal::service('simple_oauth.known_clients');
$known_clients_repository
->rememberClient($current_user
->id(), $auth_request
->getClient()
->getIdentifier(), $scopes);
}
return TrustedRedirectResponse::create($response
->getHeaderLine('location'), $response
->getStatusCode(), $response
->getHeaders());
}
protected function isKnownClient($client_uuid, array $scopes) {
if (!$this->configFactory
->get('simple_oauth.settings')
->get('remember_clients')) {
return FALSE;
}
return $this->knownClientRepository
->isAuthorized($this
->currentUser()
->id(), $client_uuid, $scopes);
}
}