id4me-2.0.x-dev/src/Controller/RedirectController.php

src/Controller/RedirectController.php
<?php

namespace Drupal\id4me\Controller;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Messenger\Messenger;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Url;
use Drupal\id4me\AuthmapService;
use Drupal\id4me\Id4meService;
use Drupal\id4me\StateToken;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Returns responses for ID4me routes.
 */
final class RedirectController extends ControllerBase {

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

  /**
   * The ID4me service.
   *
   * @var \Drupal\id4me\Id4meService
   */
  protected $id4meService;

  /**
   * The Authmap service.
   *
   * @var \Drupal\id4me\AuthmapService
   */
  protected $authmapService;

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

  /**
   * The current user object.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * RedirectController constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\id4me\Id4meService $id4me_service
   *   The ID4me service object.
   */

  /**
   * RedirectController constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\id4me\Id4meService $id4me_service
   *   The ID4me service object.
   * @param \Drupal\id4me\AuthmapService $authmap_service
   *   The Authmap service object.
   * @param \Drupal\Core\Messenger\Messenger $messenger_service
   *   The messenger service object.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   The current user object.
   */
  public function __construct(
      RequestStack $request_stack,
      Id4meService $id4me_service,
      AuthmapService $authmap_service,
      Messenger $messenger_service,
      AccountProxyInterface $current_user
  ) {
    $this->requestStack = $request_stack;
    $this->id4meService = $id4me_service;
    $this->authmapService = $authmap_service;
    $this->messengerService = $messenger_service;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new self(
      $container->get('request_stack'),
      $container->get('id4me'),
      $container->get('id4me.authmap'),
      $container->get('messenger'),
      $container->get('current_user')
    );
  }

  /**
   * Access callback: Redirect page.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   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 && StateToken::confirm($state_token)) {
      return AccessResult::allowed();
    }
    return AccessResult::forbidden();
  }

  /**
   * Authenticate with the Id4me service.
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse
   *   A redirect response.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   * @throws \Id4me\RP\Exception\InvalidAuthorityIssuerException
   * @throws \Id4me\RP\Exception\InvalidIDTokenException
   */
  public function authenticate() {
    $query = $this->requestStack->getCurrentRequest()->query;

    // Delete the state token, since it's already been confirmed.
    StateToken::delete();

    if (!$query->get('error') && !$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();
    }

    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->messengerService->addWarning(t('Logging in with Id4me has been canceled.'));
      }
      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('id4me')->error($message, $variables);
        $this->messengerService->addWarning(t('Could not authenticate with Id4me.'));
      }
    }
    else {
      // Process the login or connect operations.
      $this->id4meService->setState($query->get('state'));
      $authorizationTokens = $this->id4meService->getAuthorizationTokens($query->get('code'));
      $userInfo = $this->id4meService->getUserInfo();

      $account = $this->authmapService->userLoadByIdentifier(
        $authorizationTokens->getIdTokenDecoded()->getIss(),
        $authorizationTokens->getIdTokenDecoded()->getSub()
      );
      if ($this->currentUser->isAuthenticated() || !$account) {
        $account = User::create([
          'name' => $userInfo->getPreferredUsername(),
          'mail' => $userInfo->getEmail(),
          'status' => 1,
        ]);
        $account->save();
        $this->authmapService->createAssociation(
          $account,
          $authorizationTokens->getIdTokenDecoded()->getIss(),
          $authorizationTokens->getIdTokenDecoded()->getSub()
        );
        user_login_finalize($account);
      }
      elseif ($account instanceof UserInterface) {
        user_login_finalize($account);
      }
    }

    return new RedirectResponse(Url::fromUserInput('/')->toString());
  }

}

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

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