blob: 1158748b17cae2b1559e2ce55a224a40c7593bb7 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
#include "net/base/auth.h"
namespace {
// The minimum interval allowed, in milliseconds, between data reduction proxy
// auth requests.
const int64 kMinAuthRequestIntervalMs = 500;
// The minimum interval allowed, in milliseconds, between data reduction proxy
// auth token invalidation.
const int64 kMinTokenInvalidationIntervalMs = 60 * 60 * 1000;
// The maximum number of data reduction proxy authentication failures to
// accept before giving up.
const int kMaxBackToBackFailures = 5;
}
namespace data_reduction_proxy {
int64 DataReductionProxyAuthRequestHandler::auth_request_timestamp_ = 0;
int DataReductionProxyAuthRequestHandler::back_to_back_failure_count_ = 0;
int64
DataReductionProxyAuthRequestHandler::auth_token_invalidation_timestamp_ = 0;
DataReductionProxyAuthRequestHandler::DataReductionProxyAuthRequestHandler(
DataReductionProxySettings* settings) : settings_(settings) {
}
DataReductionProxyAuthRequestHandler::~DataReductionProxyAuthRequestHandler() {
}
DataReductionProxyAuthRequestHandler::TryHandleResult
DataReductionProxyAuthRequestHandler::TryHandleAuthentication(
net::AuthChallengeInfo* auth_info,
base::string16* user,
base::string16* password) {
if (!auth_info) {
return TRY_HANDLE_RESULT_IGNORE;
}
DCHECK(user);
DCHECK(password);
if (!IsAcceptableAuthChallenge(auth_info)) {
*user = base::string16();
*password = base::string16();
return TRY_HANDLE_RESULT_IGNORE;
}
base::TimeTicks auth_request =
base::TimeTicks::FromInternalValue(auth_request_timestamp_);
base::TimeTicks auth_token_invalidation =
base::TimeTicks::FromInternalValue(auth_token_invalidation_timestamp_);
base::TimeTicks now = Now();
if ((now - auth_request).InMilliseconds() < kMinAuthRequestIntervalMs) {
// We've received back-to-back failures. There are two possibilities:
// 1) Our auth token has expired and we should invalidate it, or
// 2) We're receiving spurious failures from the service.
//
// If we haven't recently invalidated our token, we do that here
// and make several attempts to authenticate. Otherwise, we fail.
back_to_back_failure_count_++;
if ((now - auth_token_invalidation).InMilliseconds() <
kMinTokenInvalidationIntervalMs) {
auth_token_invalidation_timestamp_ = now.ToInternalValue();
back_to_back_failure_count_ = 0;
} else {
if (back_to_back_failure_count_ > kMaxBackToBackFailures) {
DLOG(WARNING) << "Interpreting frequent data reduction proxy auth "
<< "requests as an authorization failure.";
back_to_back_failure_count_ = 0;
*user = base::string16();
*password = base::string16();
return TRY_HANDLE_RESULT_CANCEL;
}
}
} else {
back_to_back_failure_count_ = 0;
}
auth_request_timestamp_ = now.ToInternalValue();
*password = GetTokenForAuthChallenge(auth_info);
if (*password == base::string16()) {
*user = base::string16();
DLOG(WARNING) << "Data reduction proxy auth produced null token.";
return TRY_HANDLE_RESULT_CANCEL;
}
*user = base::UTF8ToUTF16("fw-cookie");
return TRY_HANDLE_RESULT_PROCEED;
}
bool DataReductionProxyAuthRequestHandler::IsAcceptableAuthChallenge(
net::AuthChallengeInfo* auth_info) {
return DataReductionProxySettings::IsAcceptableAuthChallenge(auth_info);
}
base::string16 DataReductionProxyAuthRequestHandler::GetTokenForAuthChallenge(
net::AuthChallengeInfo* auth_info) {
DCHECK(settings_);
return settings_->GetTokenForAuthChallenge(auth_info);
}
base::TimeTicks DataReductionProxyAuthRequestHandler::Now() {
return base::TimeTicks::Now();
}
} // namespace data_reduction_proxy