cilogon_auth-8.x-1.1/src/Controller/CILogonAuthRedirectController.php

src/Controller/CILogonAuthRedirectController.php
<?php

namespace Drupal\cilogon_auth\Controller;

use Drupal\cilogon_auth\CILogonAuth;
use Drupal\cilogon_auth\CILogonAuthStateToken;
use Drupal\cilogon_auth\Plugin\CILogonAuthClientManager;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Routing\Access\AccessInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\Core\Messenger\MessengerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;


/**
 * Class CILogonRedirectController.
 *
 * @package Drupal\cilogon_auth\Controller
 */
class CILogonAuthRedirectController extends ControllerBase implements AccessInterface {

    /**
     * Drupal\cilogon_auth\Plugin\CILogonAuthClientManager definition.
     *
     * @var \Drupal\cilogon_auth\Plugin\CILogonAuthClientManager
     */
    protected $pluginManager;

    /**
     * The request stack used to access request globals.
     *
     * @var \Symfony\Component\HttpFoundation\RequestStack
     */
    protected $requestStack;

    /**
     * The logger factory.
     *
     * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
     */
    protected $loggerFactory;

    /**
     * Drupal\Core\Session\AccountProxy definition.
     *
     * @var \Drupal\Core\Session\AccountProxy
     */
    protected $currentUser;

    /**
     * The CILogon Auth service.
     *
     * @var \Drupal\cilogon_auth\CILogonAuth
     */
    protected $ciLogonAuth;

    /**
     * The Messenger service.
     *
     * @var \Drupal\Core\Messenger\MessengerInterface
     */
    protected $messenger;

    /**
     * {@inheritdoc}
     */
    public function __construct(
        CILogonAuthClientManager $plugin_manager,
        CILogonAuth $cilogon_auth,
        RequestStack $request_stack,
        LoggerChannelFactoryInterface $logger_factory,
        AccountInterface $current_user,
        MessengerInterface $messenger
    ) {
        $this->pluginManager = $plugin_manager;
        $this->ciLogonAuth = $cilogon_auth;
        $this->requestStack = $request_stack;
        $this->loggerFactory = $logger_factory;
        $this->currentUser = $current_user;
        $this->messenger = $messenger;
    }

    /**
     * {@inheritdoc}
     */
    public static function create(ContainerInterface $container) {
        return new static(
            $container->get('plugin.manager.cilogon_auth_client.processor'),
            $container->get('cilogon_auth.cilogon_auth'),
            $container->get('request_stack'),
            $container->get('logger.factory'),
            $container->get('current_user'),
            $container->get('messenger')
        );
    }

    /**
     * Access callback: Redirect page.
     *
     * @return bool
     *   Whether the state token matches the previously created one that is stored
     *   in the session.
     */
    public function access() {
        // Confirm anti-forgery state token. This round-trip verification helps to
        // ensure that the user, not a malicious script, is making the request.
        $query = $this->requestStack->getCurrentRequest()->query;
        $state_token = $query->get('state');
        if ($state_token && CILogonAuthStateToken::confirm($state_token)) {
            return AccessResult::allowed();
        }
        return AccessResult::forbidden();
    }

    /**
     * Redirect.
     *
     * @param string $client_name
     *   The client name.
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
     *   The redirect response starting the authentication request.
     */
    public function authenticate($client_name) {
        $query = $this->requestStack->getCurrentRequest()->query;

        // Delete the state token, since it's already been confirmed.
        unset($_SESSION['cilogon_auth_state']);

        // Get parameters from the session, and then clean up.
        $parameters = [
            'destination' => 'user',
            'op' => 'login',
            'connect_uid' => NULL,
        ];
        foreach ($parameters as $key => $default) {
            if (isset($_SESSION['cilogon_auth_' . $key])) {
                $parameters[$key] = $_SESSION['cilogon_auth_' . $key];
                unset($_SESSION['cilogon_auth_' . $key]);
            }
        }
        $destination = $parameters['destination'];

        $configuration = $this->config('cilogon_auth.settings.' . $client_name)
            ->get('settings');
        $client = $this->pluginManager->createInstance(
            $client_name,
            $configuration
        );
        if (!$query->get('error') && (!$client || !$query->get('code'))) {
            // In case we don't have an error, but the client could not be loaded or
            // there is no state token specified, the URI is probably being visited
            // outside of the login flow.
            throw new NotFoundHttpException();
        }

        $provider_param = ['@provider' => $client->getPluginDefinition()['label']];

        if ($query->get('error')) {
            if (in_array($query->get('error'), [
                'interaction_required',
                'login_required',
                'account_selection_required',
                'consent_required',
            ])) {
                // If we have an one of the above errors, that means the user hasn't
                // granted the authorization for the claims.
                $this->messenger->addWarning($this->t('Logging in with @provider has been canceled.', $provider_param));
            }
            else {
                // Any other error should be logged. E.g. invalid scope.
                $variables = [
                    '@error' => $query->get('error'),
                    '@details' => $query->get('error_description') ? $query->get('error_description') : $this->t('Unknown error.'),
                ];
                $message = 'Authorization failed: @error. Details: @details';
                $this->loggerFactory->get('cilogon_auth_' . $client_name)->error($message, $variables);
                $this->messenger->addError($this->t('Could not authenticate with @provider.', $provider_param));
            }
        }
        else {
            // Process the login or connect operations.
            $tokens = $client->retrieveTokens($query->get('code'));
            if ($tokens) {
                if ($parameters['op'] === 'login') {
                    $success = $this->ciLogonAuth->completeAuthorization($client, $tokens, $destination);

                    if (!$success) {
                        // Check Drupal user register settings before saving.
                        $register = $this->config('user.settings')->get('register');
                        // Respect possible override from CILogono-Auth settings.
                        $register_override = $this->config('cilogon_auth.settings')
                            ->get('override_registration_settings');
                        if ($register === USER_REGISTER_ADMINISTRATORS_ONLY && $register_override) {
                            $register = USER_REGISTER_VISITORS;
                        }

                        switch ($register) {
                            case USER_REGISTER_ADMINISTRATORS_ONLY:
                            case USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL:
                                // Skip creating an error message, as completeAuthorization
                                // already added according messages.
                                break;

                            default:
                                $this->messenger->addError($this->t('Logging in with @provider could not be completed due to an error.', $provider_param));
                                break;
                        }
                    }
                }
                elseif ($parameters['op'] === 'connect' && $parameters['connect_uid'] === $this->currentUser->id()) {
                    $success = $this->ciLogonAuth->connectCurrentUser($client, $tokens);
                    if ($success) {
                        $this->messenger->addMessage($this->t('Account successfully connected with @provider.', $provider_param));
                    }
                    else {
                        $this->messenger->addError($this->t('Connecting with @provider could not be completed due to an error.', $provider_param));
                    }
                }
            }
        }

        // It's possible to set 'options' in the redirect destination.
        if (is_array($destination)) {
            $query = !empty($destination[1]['query']) ? '?' . $destination[1]['query'] : '';
            $redirect = Url::fromUri('internal:/' . ltrim($destination[0], '/') . $query)->toString();
        }
        else {
            $redirect = Url::fromUri('internal:/' . ltrim($destination, '/'))->toString();
        }
        return new RedirectResponse($redirect);
    }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc