scopeConfig = $scopeConfig; } /** * Get API hostname * @return string */ public function getApiHostname() { return $this->scopeConfig->getValue(static::XML_PATH_API_HOSTNAME); } /** * Get application key * @return string */ private function getApplicationKey() { return $this->scopeConfig->getValue(static::XML_PATH_APPLICATION_KEY); } /** * Get secret key * @return string */ private function getSecretKey() { return $this->scopeConfig->getValue(static::XML_PATH_SECRET_KEY); } /** * Get integration key * @return string */ private function getIntegrationKey() { return $this->scopeConfig->getValue(static::XML_PATH_INTEGRATION_KEY); } /** * Sign values * @param string $key * @param string $values * @param string $prefix * @param int $expire * @param int $time * @return string */ private function signValues($key, $values, $prefix, $expire, $time) { $exp = $time + $expire; $cookie = $prefix . '|' . base64_encode($values . '|' . $exp); $sig = hash_hmac("sha1", $cookie, $key); return $cookie . '|' . $sig; } /** * Parse signed values and return username * @param string $key * @param string $val * @param string $prefix * @param int $time * @return string|false */ private function parseValues($key, $val, $prefix, $time) { $integrationKey = $this->getIntegrationKey(); $timestamp = ($time ? $time : time()); $parts = explode('|', $val); if (count($parts) !== 3) { return false; } list($uPrefix, $uB64, $uSig) = $parts; $sig = hash_hmac("sha1", $uPrefix . '|' . $uB64, $key); if (hash_hmac("sha1", $sig, $key) !== hash_hmac("sha1", $uSig, $key)) { return false; } if ($uPrefix !== $prefix) { return false; } // @codingStandardsIgnoreStart $cookieParts = explode('|', base64_decode($uB64)); // @codingStandardsIgnoreEnd if (count($cookieParts) !== 3) { return false; } list($user, $uIkey, $exp) = $cookieParts; if ($uIkey !== $integrationKey) { return false; } if ($timestamp >= (int) $exp) { return false; } return $user; } /** * Get request signature * @param UserInterface $user * @return string */ public function getRequestSignature(UserInterface $user) { $time = time(); $values = $user->getUserName() . '|' . $this->getIntegrationKey(); $duoSignature = $this->signValues( $this->getSecretKey(), $values, static::DUO_PREFIX, static::DUO_EXPIRE, $time ); $appSignature = $this->signValues( $this->getApplicationKey(), $values, static::APP_PREFIX, static::APP_EXPIRE, $time ); return $duoSignature . ':' . $appSignature; } /** * Return true on token validation * @param UserInterface $user * @param DataObject $request * @return bool */ public function verify(UserInterface $user, DataObject $request) { $time = time(); list($authSig, $appSig) = explode(':', $request->getData('sig_response')); $authUser = $this->parseValues($this->getSecretKey(), $authSig, static::AUTH_PREFIX, $time); $appUser = $this->parseValues($this->getApplicationKey(), $appSig, static::APP_PREFIX, $time); return (($authUser === $appUser) && ($appUser === $user->getUserName())); } /** * Return true if this provider has been enabled by admin * @return boolean */ public function isEnabled() { return !!$this->scopeConfig->getValue(static::XML_PATH_ENABLED) && !!$this->getApiHostname() && !!$this->getIntegrationKey() && !!$this->getApiHostname() && !!$this->getSecretKey(); } /** * Return true if this provider allows trusted devices * @return boolean */ public function isTrustedDevicesAllowed() { return false; } }