You are here

class KeycloakService in Keycloak OpenID Connect 8

Keycloak service.

Hierarchy

Expanded class hierarchy of KeycloakService

1 string reference to 'KeycloakService'
keycloak.services.yml in ./keycloak.services.yml
keycloak.services.yml
1 service uses KeycloakService
keycloak.keycloak in ./keycloak.services.yml
Drupal\keycloak\Service\KeycloakService

File

src/Service/KeycloakService.php, line 17

Namespace

Drupal\keycloak\Service
View source
class KeycloakService implements KeycloakServiceInterface {

  /**
   * Machine name for the Keycloak openid_connect plugin.
   */
  protected const OPENID_CONNECT_CONFIG_NAME = 'openid_connect.settings.keycloak';

  /**
   * A configuration object containing Keycloak client settings.
   *
   * @var \Drupal\Core\Config\ImmutableConfig
   */
  protected $config;

  /**
   * Client plugin manager of the OpenID Connect module.
   *
   * @var \Drupal\openid_connect\Plugin\OpenIDConnectClientManager
   */
  protected $oidcClientManager;

  /**
   * A language manager instance.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

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

  /**
   * The users' private tempstore instance.
   *
   * @var \Drupal\Core\TempStore\PrivateTempStoreFactory
   */
  protected $privateTempstore;

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

  /**
   * Default keys to be stored to / retrieved from a Keycloak user session.
   *
   * @var array
   */
  private static $sessionInfoKeys;

  /**
   * {@inheritdoc}
   */
  public function __construct(ConfigFactoryInterface $config_factory, OpenIDConnectClientManager $oidc_client_manager, LanguageManagerInterface $language_manager, AccountProxyInterface $current_user, PrivateTempStoreFactory $private_tempstore, LoggerChannelFactoryInterface $logger) {
    $this->config = $config_factory
      ->get(static::OPENID_CONNECT_CONFIG_NAME);
    $this->oidcClientManager = $oidc_client_manager;
    $this->languageManager = $language_manager;
    $this->currentUser = $current_user;
    $this->privateTempstore = $private_tempstore;
    $this->loggerFactory = $logger;
  }

  /**
   * {@inheritdoc}
   */
  public function isEnabled() {
    return $this->config
      ->get('enabled');
  }

  /**
   * {@inheritdoc}
   */
  public function getBaseUrl() {
    return $this->config
      ->get('settings.keycloak_base');
  }

  /**
   * {@inheritdoc}
   */
  public function getRealm() {
    return $this->config
      ->get('settings.keycloak_realm');
  }

  /**
   * {@inheritdoc}
   */
  public function getEndpoints() {
    $base = $this
      ->getBaseUrl() . '/realms/' . $this
      ->getRealm();
    return [
      'authorization' => $base . self::KEYCLOAK_AUTH_ENDPOINT_URI,
      'token' => $base . self::KEYCLOAK_TOKEN_ENDPOINT_URI,
      'userinfo' => $base . self::KEYCLOAK_USERINFO_ENDPOINT_URI,
      'end_session' => $base . self::KEYCLOAK_END_SESSION_ENDPOINT_URI,
      'session_iframe' => $base . self::KEYCLOAK_CHECK_SESSION_IFRAME_URI,
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function isKeycloakUser() {

    // Whether the user is not authenticated or the Keycloak client disabled.
    if (!$this->currentUser
      ->isAuthenticated() || !$this
      ->isEnabled()) {
      return FALSE;
    }

    // If the user was logged in using Keycloak, we will find session
    // information in the users' private tempstore.
    $tempstore = $this->privateTempstore
      ->get('keycloak');
    return !empty($tempstore);
  }

  /**
   * {@inheritdoc}
   */
  public function getSessionInfoDefaultKeys() {
    if (!isset(self::$sessionInfoKeys)) {
      $default_keys = [
        self::KEYCLOAK_SESSION_ACCESS_TOKEN,
        self::KEYCLOAK_SESSION_REFRESH_TOKEN,
        self::KEYCLOAK_SESSION_ID_TOKEN,
        self::KEYCLOAK_SESSION_CLIENT_ID,
        self::KEYCLOAK_SESSION_SESSION_ID,
      ];
      self::$sessionInfoKeys = $default_keys;
    }
    return self::$sessionInfoKeys;
  }

  /**
   * {@inheritdoc}
   */
  public function getSessionInfo($keys = NULL) {
    $session_info = [];
    if (!$this
      ->isKeycloakUser()) {
      return $session_info;
    }
    $default_keys = $this
      ->getSessionInfoDefaultKeys();
    $keys = empty($keys) ? $default_keys : array_intersect($default_keys, $keys);
    $tempstore = $this->privateTempstore
      ->get('keycloak');
    foreach ($keys as $key) {
      $session_info[$key] = $tempstore
        ->get($key);
    }
    return $session_info;
  }

  /**
   * {@inheritdoc}
   */
  public function setSessionInfo(array $info) {

    // Whether the user is not authenticated or the Keycloak client disabled.
    if (!$this->currentUser
      ->isAuthenticated() || !$this
      ->isEnabled()) {
      return FALSE;
    }
    $default_keys = $this
      ->getSessionInfoDefaultKeys();
    $old_values = $this
      ->getSessionInfo();
    $new_values = array_merge($old_values, $info);
    $tempstore = $this->privateTempstore
      ->get('keycloak');
    foreach ($default_keys as $key) {
      $tempstore
        ->set($key, $new_values[$key]);
    }
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function isI18nEnabled() {
    return $this
      ->isEnabled() && $this->languageManager
      ->isMultilingual() && $this->config
      ->get('settings.keycloak_i18n.enabled');
  }

  /**
   * {@inheritdoc}
   */
  public function getI18nMapping($reverse = FALSE, $include_enabled = TRUE) {
    $mappings = [];
    $languages = $this->languageManager
      ->getLanguages();
    if (empty($languages)) {
      return $mappings;
    }
    $configured = $this->config
      ->get('settings.keycloak_i18n_mapping');

    // The stored mapping is an unkeyed list of associative arrays
    // with 'langcode' and 'target' as keys. Transform it to an assoc
    // array of 'langcode' => 'target'.
    $kc_mappings = [];
    if (!empty($configured)) {
      foreach ($configured as $mapping) {
        $kc_mappings[$mapping['langcode']] = $mapping['target'];
      }
    }

    // Create the i18n locale mapping information.
    foreach ($languages as $langcode => $language) {
      if (empty($kc_mappings[$langcode]) && !$include_enabled) {
        continue;
      }
      $mapping = [
        'language_id' => $langcode,
        'locale' => !empty($kc_mappings[$langcode]) ? $kc_mappings[$langcode] : $langcode,
        'label' => $language
          ->getName(),
      ];
      $mappings[$reverse ? $mapping['locale'] : $langcode] = $mapping;
    }
    return $mappings;
  }

  /**
   * {@inheritdoc}
   */
  public function isSsoEnabled() {
    return $this
      ->isEnabled() && $this->config
      ->get('settings.keycloak_sso');
  }

  /**
   * {@inheritdoc}
   */
  public function isKeycloakSignOutEnabled() {
    return $this->config
      ->get('enabled') && $this->config
      ->get('settings.keycloak_sign_out');
  }

  /**
   * {@inheritdoc}
   */
  public function getKeycloakSignOutEndpoint() {
    return $this
      ->getEndpoints()['end_session'];
  }

  /**
   * {@inheritdoc}
   */
  public function getKeycloakSignoutResponse(array $session_information) {
    $logout_redirect = Url::fromRoute('<front>', [], [
      'absolute' => TRUE,
    ])
      ->toString();
    if ($this
      ->isKeycloakSignOutEnabled() && !empty($session_information[self::KEYCLOAK_SESSION_ID_TOKEN])) {

      // We do an internal redirect here and modify it in
      // our KeycloakRequestSubscriber.
      return new RedirectResponse(Url::fromRoute('keycloak.logout', [], [
        'query' => [
          'id_token_hint' => $session_information[self::KEYCLOAK_SESSION_ID_TOKEN],
          'post_logout_redirect_uri' => $logout_redirect,
        ],
      ])
        ->toString());
    }
    return new RedirectResponse($logout_redirect);
  }

  /**
   * {@inheritdoc}
   */
  public function isCheckSessionEnabled() {
    return $this->config
      ->get('enabled') && $this->config
      ->get('settings.check_session.enabled');
  }

  /**
   * {@inheritdoc}
   */
  public function getCheckSessionInterval() {
    return $this->config
      ->get('settings.check_session.interval');
  }

  /**
   * {@inheritdoc}
   */
  public function getCheckSessionIframeUrl() {
    return $this
      ->getEndpoints()['session_iframe'];
  }

  /**
   * {@inheritdoc}
   */
  public function getClientInstance() {
    $config = $this->config
      ->get('settings');
    if (empty($config)) {
      $config = [];
    }
    return $this->oidcClientManager
      ->createInstance('keycloak', $config);
  }

  /**
   * {@inheritdoc}
   */
  public function getLogger() {
    return $this->loggerFactory
      ->get('openid_connect_keycloak');
  }

  /**
   * {@inheritdoc}
   */
  public function isDebugMode() {
    return $this->config
      ->get('settings.debug');
  }

}

Members

Namesort descending Modifiers Type Description Overrides
KeycloakService::$config protected property A configuration object containing Keycloak client settings.
KeycloakService::$currentUser protected property The current user.
KeycloakService::$languageManager protected property A language manager instance.
KeycloakService::$loggerFactory protected property The logger factory.
KeycloakService::$oidcClientManager protected property Client plugin manager of the OpenID Connect module.
KeycloakService::$privateTempstore protected property The users' private tempstore instance.
KeycloakService::$sessionInfoKeys private static property Default keys to be stored to / retrieved from a Keycloak user session.
KeycloakService::getBaseUrl public function Return the Keycloak base URL. Overrides KeycloakServiceInterface::getBaseUrl
KeycloakService::getCheckSessionIframeUrl public function Return the check session iframe URL. Overrides KeycloakServiceInterface::getCheckSessionIframeUrl
KeycloakService::getCheckSessionInterval public function Return the check session interval. Overrides KeycloakServiceInterface::getCheckSessionInterval
KeycloakService::getClientInstance public function Return a configured Keycloak client plugin for the openid_connect module. Overrides KeycloakServiceInterface::getClientInstance
KeycloakService::getEndpoints public function Return the available Keycloak endpoints. Overrides KeycloakServiceInterface::getEndpoints
KeycloakService::getI18nMapping public function Return the Keycloak i18n locale code mapping. Overrides KeycloakServiceInterface::getI18nMapping
KeycloakService::getKeycloakSignOutEndpoint public function Return the Keycloak Single Sing-Out endpoint. Overrides KeycloakServiceInterface::getKeycloakSignOutEndpoint
KeycloakService::getKeycloakSignoutResponse public function Return a RP (Drupal) initiated single sign-out response. Overrides KeycloakServiceInterface::getKeycloakSignoutResponse
KeycloakService::getLogger public function Return Keycloak logger. Overrides KeycloakServiceInterface::getLogger
KeycloakService::getRealm public function Return the Keycloak realm. Overrides KeycloakServiceInterface::getRealm
KeycloakService::getSessionInfo public function Return an associative array of Keycloak session information. Overrides KeycloakServiceInterface::getSessionInfo
KeycloakService::getSessionInfoDefaultKeys public function Return an array of available Keycloak session info keys. Overrides KeycloakServiceInterface::getSessionInfoDefaultKeys
KeycloakService::isCheckSessionEnabled public function Whether OP (Keycloak) initiated Single Sing-Out is enabled. Overrides KeycloakServiceInterface::isCheckSessionEnabled
KeycloakService::isDebugMode public function Whether the Keycloak client is in verbose debug mode. Overrides KeycloakServiceInterface::isDebugMode
KeycloakService::isEnabled public function Whether the Keycloak client is enabled. Overrides KeycloakServiceInterface::isEnabled
KeycloakService::isI18nEnabled public function Whether Keycloak multi-language support is enabled. Overrides KeycloakServiceInterface::isI18nEnabled
KeycloakService::isKeycloakSignOutEnabled public function Whether RP (Drupal) initiated Single Sing-Out is enabled. Overrides KeycloakServiceInterface::isKeycloakSignOutEnabled
KeycloakService::isKeycloakUser public function Whether the currently logged in user was logged in using Keycloak. Overrides KeycloakServiceInterface::isKeycloakUser
KeycloakService::isSsoEnabled public function Whether Keycloak single sign-on (SSO) is enabled. Overrides KeycloakServiceInterface::isSsoEnabled
KeycloakService::OPENID_CONNECT_CONFIG_NAME protected constant Machine name for the Keycloak openid_connect plugin.
KeycloakService::setSessionInfo public function Store the Keycloak session information to the user session. Overrides KeycloakServiceInterface::setSessionInfo
KeycloakService::__construct public function Constructor for Drupal\keycloak\Service\KeycloakService. Overrides KeycloakServiceInterface::__construct
KeycloakServiceInterface::KEYCLOAK_AUTH_ENDPOINT_URI constant Default Keycloak authorization endpoint URI.
KeycloakServiceInterface::KEYCLOAK_CHECK_SESSION_IFRAME_URI constant Default Keycloak check session iframe URI.
KeycloakServiceInterface::KEYCLOAK_CONFIG_ENDPOINT_URI constant Default Keycloak OpenID configuration endpoint URI.
KeycloakServiceInterface::KEYCLOAK_END_SESSION_ENDPOINT_URI constant Default Keycloak end session endpoint URI for single sign-out propagation.
KeycloakServiceInterface::KEYCLOAK_SESSION_ACCESS_TOKEN constant Keycloak access token.
KeycloakServiceInterface::KEYCLOAK_SESSION_CLIENT_ID constant Keycloak client ID.
KeycloakServiceInterface::KEYCLOAK_SESSION_ID_TOKEN constant Keycloak ID token.
KeycloakServiceInterface::KEYCLOAK_SESSION_REFRESH_TOKEN constant Keycloak refresh token.
KeycloakServiceInterface::KEYCLOAK_SESSION_SESSION_ID constant Keycloak session ID.
KeycloakServiceInterface::KEYCLOAK_TOKEN_ENDPOINT_URI constant Default Keycloak token endpoint URI.
KeycloakServiceInterface::KEYCLOAK_USERINFO_ENDPOINT_URI constant Default Keycloak userinfo endpoint URI.