providerID = substr(get_called_class(), strlen('helper_plugin_')); $this->settings = new Settings($this->providerID, $user); } /** * The ID of this provider * * @return string */ public function getProviderID() { return $this->providerID; } /** * Pretty Label for this provider * * @return string */ public function getLabel() { return PhpString::ucfirst($this->providerID); } /** * Clear all settings */ public function reset() { $this->settings->purge(); } /** * Has this provider been fully configured by the user and thus can be used * for authentication? * * @return bool */ abstract public function isConfigured(); /** * Render the configuration form * * This method should add the needed form elements to (re)configure the provider. * The contents of the form may change depending on the current settings. * * No submit button should be added - this is handled by the main plugin. * * @param Form $form The initial form to add elements to * @return Form */ abstract public function renderProfileForm(Form $form); /** * Handle any input data * * @return void */ abstract public function handleProfileForm(); /** * Transmits the code to the user * * @param string $code The code to transmit * @return string Informational message for the user * @throw \Exception when the message can't be sent */ abstract public function transmitMessage($code); // region OTP methods /** * Create and store a new secret for this provider * * @return string the new secret * @throws \Exception when no suitable random source is available */ public function initSecret() { $ga = new GoogleAuthenticator(); $secret = $ga->createSecret(); $this->settings->set('secret', $secret); return $secret; } /** * Generate an auth code * * @return string * @throws \Exception when no code can be created */ public function generateCode() { $secret = $this->settings->get('secret'); if (!$secret) throw new \Exception('No secret for provider ' . $this->getProviderID()); $ga = new GoogleAuthenticator(); return $ga->getCode($secret); } /** * Check the given code * * @param string $code * @param int $tolerance * @return string * @throws \Exception when no code can be created */ public function checkCode($code, $tolerance = 2) { $secret = $this->settings->get('secret'); if (!$secret) throw new \Exception('No secret for provider ' . $this->getProviderID()); $ga = new GoogleAuthenticator(); return $ga->verifyCode($secret, $code, $tolerance); } // endregion // region old shit /** * This is called to see if the user can use it to login. * @return bool - True if this module has access to all needed information * to perform a login. */ abstract public function canUse($user = null); /** * This is called to see if the module provides login functionality on the * main login page. * @return bool - True if this module provides main login functionality. */ abstract public function canAuthLogin(); /** * This is called to process the user configurable portion of the module * inside the user's profile. * @return mixed - True if the user's settings were changed, false if * settings could not be changed, null if no settings were changed, * the string 'verified' if the module was successfully verified, * the string 'failed' if the module failed verification, * the string 'otp' if the module is requesting a one-time password * for verification, * the string 'deleted' if the module was unenrolled. */ public function processProfileForm() { return null; } /** * This is called to see if the module can send a message to the user. * @return bool - True if a message can be sent to the user. */ abstract public function canTransmitMessage(); /** * This is called to validate the code provided. The default is to see if * the code matches the one-time password. * @return bool - True if the user has successfully authenticated using * this mechanism. */ public function processLogin($code, $user = null) { $twofactor = plugin_load('action', 'twofactor'); $otpQuery = $twofactor->get_otp_code(); if (!$otpQuery) { return false; } list($otp, $modname) = $otpQuery; return ($code == $otp && $code != '' && (count($modname) == 0 || in_array(get_called_class(), $modname))); } /** * This is a helper function to get text strings from the twofactor class * calling this module. * @return string - Language string from the calling class. */ protected function _getSharedLang($key) { $twofactor = plugin_load('action', 'twofactor'); return $twofactor->getLang($key); } /** * This is a helper function to get shared configuration options from the * twofactor class. * @return string - Language string from the calling class. */ protected function _getSharedConfig($key) { $twofactor = plugin_load('action', 'twofactor'); return $twofactor->getConf($key); } /** * This is a helper function to check for the existence of shared * twofactor settings. * @return string - Language string from the calling class. */ protected function _sharedSettingExists($key) { return $this->attribute->exists("twofactor", $key); } /** * This is a helper function to get shared twofactor settings. * @return string - Language string from the calling class. */ protected function _sharedSettingGet($key, $default = null, $user = null) { return $this->_sharedSettingExists($key) ? $this->attribute->get("twofactor", $key, $success, $user) : $default; } /** * This is a helper function to set shared twofactor settings. * @return string - Language string from the calling class. */ protected function _sharedSettingSet($key, $value) { return $this->attribute->set("twofactor", $key, $value); } /** * This is a helper function that attempts to load the named modules. * @return array - An array of instanced objects from the loaded modules. */ static public function _loadModules($mods) { $objects = array(); foreach ($mods as $mod) { $obj = plugin_load('helper', $mod); if ($obj && is_a($obj, 'Twofactor_Auth_Module')) { $objects[$mod] = $obj; } } return $objects; } // endregion }