[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |