private function AuthenticateRESTv3($request) { if (empty($request['Signature'])) { throw new Exception("Signature is missing"); } if (empty($request['KeyID'])) { throw new Exception("KeyID is missing"); } if (empty($request['Timestamp']) && empty($request['TimeStamp'])) { throw new Exception("Timestamp is missing"); } if (!empty($request['Timestamp'])) { $request['TimeStamp'] = $request['Timestamp']; } //You mustn't do urldecode here in the next API version! $string_to_sign = "{$request['Action']}:{$request['KeyID']}:" . urldecode($request['TimeStamp']); $this->debug['stringToSign'] = $string_to_sign; try { $this->user = Scalr_Account_User::init()->loadByApiAccessKey($request['KeyID']); } catch (Exception $e) { } if (!$this->user) { throw new Exception("The specified KeyID does not exist"); } $auth_key = $this->user->getSetting(Scalr_Account_User::SETTING_API_SECRET_KEY); if ($this->user->getAccountId()) { if (\Scalr::config('scalr.auth_mode') == 'ldap') { $this->Environment = Scalr_Environment::init()->loadById($request['EnvID']); try { $ldap = \Scalr::getContainer()->ldap($this->user->getLdapUsername(), null); if (!$ldap->isValidUsername()) { throw new Exception('Incorrect login or password (1)'); } $this->user->applyLdapGroups($ldap->getUserGroups()); } catch (Exception $e) { throw new Exception("Incorrect login or password (1)" . "\n" . $ldap->getLog()); } } else { if (empty($request['EnvID'])) { $envs = $this->user->getEnvironments(); if (empty($envs[0]['id'])) { throw new Exception("User has no access to any environments"); } $this->Environment = Scalr_Environment::init()->loadById($envs[0]['id']); } else { $this->Environment = Scalr_Environment::init()->loadById($request['EnvID']); } } $this->user->getPermissions()->setEnvironmentId($this->Environment->id)->validate($this->Environment); //We must set environment to DI Container. $this->setDiContainer(); } $valid_sign = base64_encode(hash_hmac(self::HASH_ALGO, trim($string_to_sign), $auth_key, 1)); //You mustn't do this in the next API version! $request['Signature'] = str_replace(" ", "+", urldecode($request['Signature'])); //You mustn't do urldecode here in the next API version! $this->debug['reqSignature'] = urldecode($request['Signature']); $this->debug['validSignature'] = $valid_sign; $this->debug['usedAuthVersion'] = 3; $this->debug['sha256AccessKey'] = hash(self::HASH_ALGO, $auth_key); if ($valid_sign != $request['Signature']) { //This is workaround to bugfix SCALRCORE-400. //It needn't have made unnecessary urldecode operation with request parameters. $sts2 = "{$request['Action']}:{$request['KeyID']}:{$request['TimeStamp']}"; $vs2 = base64_encode(hash_hmac(self::HASH_ALGO, trim($sts2), $auth_key, 1)); if ($vs2 != $request['Signature']) { throw new Exception("Signature doesn't match"); } } }