Scalr\Api\Rest\ApiApplication::authenticationMiddleware PHP Method

authenticationMiddleware() public method

Authentication middleware
    public function authenticationMiddleware()
    {
        $bDebug = $this->request->headers('x-scalr-debug', 0) == 1;
        //If API is not enabled
        if (!$this->getContainer()->config('scalr.system.api.enabled')) {
            $this->halt(403, 'API is not enabled. See scalr.system.api.enabled');
        }
        //Authentication
        $keyId = $this->request->headers('x-scalr-key-id');
        $signature = $this->request->headers('x-scalr-signature');
        //ISO-8601 formatted date
        $date = trim(preg_replace('/\\s+/', '', $this->request->headers('x-scalr-date')));
        if (empty($keyId) || empty($signature)) {
            throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Unsigned request');
        } elseif (empty($date) || ($time = strtotime($date)) === false) {
            throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, 'Missing or invalid X-Scalr-Date header');
        }
        $sigparts = explode(' ', $signature, 2);
        if (empty($sigparts) || !in_array($sigparts[0], ['V1-HMAC-SHA256'])) {
            throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Invalid signature');
        }
        $this->apiKey = ApiKeyEntity::findPk($keyId);
        if (!$this->apiKey instanceof ApiKeyEntity || !$this->apiKey->active) {
            throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Invalid API Key');
        }
        if (abs(time() - $time) > 300) {
            throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Request is expired.' . ($bDebug ? ' Now is ' . gmdate('Y-m-d\\TH:i:s\\Z') : ''));
        }
        $now = new \DateTime('now');
        if (empty($this->apiKey->lastUsed) || $now->getTimestamp() - $this->apiKey->lastUsed->getTimestamp() > 10) {
            $this->apiKey->lastUsed = $now;
            $this->apiKey->save();
        }
        $qstr = $this->request->get();
        $canonicalStr = '';
        if (!empty($qstr)) {
            ksort($qstr);
            $canonicalStr = http_build_query($qstr, null, '&', PHP_QUERY_RFC3986);
        }
        $reqBody = $this->request->getBody();
        $stringToSign = $this->request->getMethod() . "\n" . $date . "\n" . $this->request->getPath() . "\n" . $canonicalStr . "\n" . (empty($reqBody) ? '' : $reqBody);
        if ($bDebug) {
            $this->meta->stringToSign = $stringToSign;
        }
        switch ($sigparts[0]) {
            default:
                throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Invalid signature method. Please use "V1-HMAC-SHA256 [SIGNATURE]"');
                break;
            case 'V1-HMAC-SHA256':
                $algo = strtolower(substr($sigparts[0], 8));
        }
        $sig = base64_encode(hash_hmac($algo, $stringToSign, $this->apiKey->secretKey, 1));
        if ($sig !== $sigparts[1]) {
            throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'Signature does not match');
        }
        $user = Entity\Account\User::findPk($this->apiKey->userId);
        /* @var $user Entity\Account\User */
        if (!$user instanceof Entity\Account\User) {
            throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'User does not exist');
        }
        if ($user->status != Entity\Account\User::STATUS_ACTIVE) {
            throw new ApiErrorException(403, ErrorMessage::ERR_PERMISSION_VIOLATION, 'Inactive user status');
        }
        if (\Scalr::config('scalr.auth_mode') == 'ldap') {
            try {
                $ldap = \Scalr::getContainer()->ldap($user->getLdapUsername(), null);
                if (!$ldap->isValidUsername()) {
                    if ($bDebug && $ldap->getConfig()->debug) {
                        $this->meta->ldapDebug = $ldap->getLog();
                    }
                    throw new ApiErrorException(401, ErrorMessage::ERR_BAD_AUTHENTICATION, 'User does not exist');
                }
                $user->applyLdapGroups($ldap->getUserGroups());
            } catch (LdapException $e) {
                if ($bDebug && $ldap instanceof LdapClient && $ldap->getConfig()->debug) {
                    $this->meta->ldapDebug = $ldap->getLog();
                }
                throw new RuntimeException($e->getMessage(), $e->getCode(), $e);
            }
        }
        $this->limiter->checkAccountRateLimit($this->apiKey->keyId);
        //Validates API version
        if ($this->settings[ApiApplication::SETTING_API_VERSION] != 1) {
            throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, 'Invalid API version');
        }
        if ($this->request->getBody() !== '' && strtolower($this->request->getMediaType()) !== 'application/json') {
            throw new ApiErrorException(400, ErrorMessage::ERR_BAD_REQUEST, 'Invalid Content-Type');
        }
        $this->setUser($user);
        $container = $this->getContainer();
        //Releases auditloger to ensure it will be updated
        $container->release('auditlogger');
        $container->set('auditlogger.request', function () {
            return $this;
        });
    }