[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/plugins/system/webauthn/src/PluginTraits/ -> AdditionalLoginButtons.php (source)

   1  <?php
   2  
   3  /**
   4   * @package         Joomla.Plugin
   5   * @subpackage      System.Webauthn
   6   *
   7   * @copyright   (C) 2020 Open Source Matters, Inc. <https://www.joomla.org>
   8   * @license         GNU General Public License version 2 or later; see LICENSE.txt
   9   */
  10  
  11  namespace Joomla\Plugin\System\Webauthn\PluginTraits;
  12  
  13  use Exception;
  14  use Joomla\CMS\Application\CMSApplication;
  15  use Joomla\CMS\Document\HtmlDocument;
  16  use Joomla\CMS\Helper\AuthenticationHelper;
  17  use Joomla\CMS\HTML\HTMLHelper;
  18  use Joomla\CMS\Language\Text;
  19  use Joomla\CMS\Uri\Uri;
  20  use Joomla\CMS\User\UserHelper;
  21  use Joomla\Event\Event;
  22  
  23  // phpcs:disable PSR1.Files.SideEffects
  24  \defined('_JEXEC') or die;
  25  // phpcs:enable PSR1.Files.SideEffects
  26  
  27  /**
  28   * Inserts Webauthn buttons into login modules
  29   *
  30   * @since   4.0.0
  31   */
  32  trait AdditionalLoginButtons
  33  {
  34      /**
  35       * Do I need to inject buttons? Automatically detected (i.e. disabled if I'm already logged
  36       * in).
  37       *
  38       * @var     boolean|null
  39       * @since   4.0.0
  40       */
  41      protected $allowButtonDisplay = null;
  42  
  43      /**
  44       * Have I already injected CSS and JavaScript? Prevents double inclusion of the same files.
  45       *
  46       * @var     boolean
  47       * @since   4.0.0
  48       */
  49      private $injectedCSSandJS = false;
  50  
  51      /**
  52       * Creates additional login buttons
  53       *
  54       * @param   Event  $event  The event we are handling
  55       *
  56       * @return  void
  57       *
  58       * @see     AuthenticationHelper::getLoginButtons()
  59       *
  60       * @since   4.0.0
  61       */
  62      public function onUserLoginButtons(Event $event): void
  63      {
  64          /** @var string $form The HTML ID of the form we are enclosed in */
  65          [$form] = $event->getArguments();
  66  
  67          // If we determined we should not inject a button return early
  68          if (!$this->mustDisplayButton()) {
  69              return;
  70          }
  71  
  72          // Load necessary CSS and Javascript files
  73          $this->addLoginCSSAndJavascript();
  74  
  75          // Unique ID for this button (allows display of multiple modules on the page)
  76          $randomId = 'plg_system_webauthn-' .
  77              UserHelper::genRandomPassword(12) . '-' . UserHelper::genRandomPassword(8);
  78  
  79          // Get local path to image
  80          $image = HTMLHelper::_('image', 'plg_system_webauthn/webauthn.svg', '', '', true, true);
  81  
  82          // If you can't find the image then skip it
  83          $image = $image ? JPATH_ROOT . substr($image, \strlen(Uri::root(true))) : '';
  84  
  85          // Extract image if it exists
  86          $image = file_exists($image) ? file_get_contents($image) : '';
  87  
  88          $this->returnFromEvent($event, [
  89              [
  90                  'label'              => 'PLG_SYSTEM_WEBAUTHN_LOGIN_LABEL',
  91                  'tooltip'            => 'PLG_SYSTEM_WEBAUTHN_LOGIN_DESC',
  92                  'id'                 => $randomId,
  93                  'data-webauthn-form' => $form,
  94                  'svg'                => $image,
  95                  'class'              => 'plg_system_webauthn_login_button',
  96              ],
  97              ]);
  98      }
  99  
 100      /**
 101       * Should I allow this plugin to add a WebAuthn login button?
 102       *
 103       * @return  boolean
 104       *
 105       * @since   4.0.0
 106       */
 107      private function mustDisplayButton(): bool
 108      {
 109          // We must have a valid application
 110          if (!($this->getApplication() instanceof CMSApplication)) {
 111              return false;
 112          }
 113  
 114          // This plugin only applies to the frontend and administrator applications
 115          if (!$this->getApplication()->isClient('site') && !$this->getApplication()->isClient('administrator')) {
 116              return false;
 117          }
 118  
 119          // We must have a valid user
 120          if (empty($this->getApplication()->getIdentity())) {
 121              return false;
 122          }
 123  
 124          if (\is_null($this->allowButtonDisplay)) {
 125              $this->allowButtonDisplay = false;
 126  
 127              /**
 128               * Do not add a WebAuthn login button if we are already logged in
 129               */
 130              if (!$this->getApplication()->getIdentity()->guest) {
 131                  return false;
 132              }
 133  
 134              /**
 135               * Only display a button on HTML output
 136               */
 137              try {
 138                  $document = $this->getApplication()->getDocument();
 139              } catch (Exception $e) {
 140                  $document = null;
 141              }
 142  
 143              if (!($document instanceof HtmlDocument)) {
 144                  return false;
 145              }
 146  
 147              /**
 148               * WebAuthn only works on HTTPS. This is a security-related limitation of the W3C Web Authentication
 149               * specification, not an issue with this plugin :)
 150               */
 151              if (!Uri::getInstance()->isSsl()) {
 152                  return false;
 153              }
 154  
 155              // All checks passed; we should allow displaying a WebAuthn login button
 156              $this->allowButtonDisplay = true;
 157          }
 158  
 159          return $this->allowButtonDisplay;
 160      }
 161  
 162      /**
 163       * Injects the WebAuthn CSS and Javascript for frontend logins, but only once per page load.
 164       *
 165       * @return  void
 166       *
 167       * @since   4.0.0
 168       */
 169      private function addLoginCSSAndJavascript(): void
 170      {
 171          if ($this->injectedCSSandJS) {
 172              return;
 173          }
 174  
 175          // Set the "don't load again" flag
 176          $this->injectedCSSandJS = true;
 177  
 178          /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
 179          $wa = $this->getApplication()->getDocument()->getWebAssetManager();
 180  
 181          if (!$wa->assetExists('style', 'plg_system_webauthn.button')) {
 182              $wa->registerStyle('plg_system_webauthn.button', 'plg_system_webauthn/button.css');
 183          }
 184  
 185          if (!$wa->assetExists('script', 'plg_system_webauthn.login')) {
 186              $wa->registerScript('plg_system_webauthn.login', 'plg_system_webauthn/login.js', [], ['defer' => true], ['core']);
 187          }
 188  
 189          $wa->useStyle('plg_system_webauthn.button')
 190              ->useScript('plg_system_webauthn.login');
 191  
 192          // Load language strings client-side
 193          Text::script('PLG_SYSTEM_WEBAUTHN_ERR_CANNOT_FIND_USERNAME');
 194          Text::script('PLG_SYSTEM_WEBAUTHN_ERR_EMPTY_USERNAME');
 195          Text::script('PLG_SYSTEM_WEBAUTHN_ERR_INVALID_USERNAME');
 196  
 197          // Store the current URL as the default return URL after login (or failure)
 198          $this->getApplication()->getSession()->set('plg_system_webauthn.returnUrl', Uri::current());
 199      }
 200  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer