1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/time/time.h"
9 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
10 #include "net/base/auth.h"
13 // The minimum interval allowed, in milliseconds, between data reduction proxy
15 const int64 kMinAuthRequestIntervalMs = 500;
17 // The minimum interval allowed, in milliseconds, between data reduction proxy
18 // auth token invalidation.
19 const int64 kMinTokenInvalidationIntervalMs = 60 * 60 * 1000;
21 // The maximum number of data reduction proxy authentication failures to
22 // accept before giving up.
23 const int kMaxBackToBackFailures = 5;
26 namespace data_reduction_proxy {
28 int64 DataReductionProxyAuthRequestHandler::auth_request_timestamp_ = 0;
30 int DataReductionProxyAuthRequestHandler::back_to_back_failure_count_ = 0;
33 DataReductionProxyAuthRequestHandler::auth_token_invalidation_timestamp_ = 0;
36 DataReductionProxyAuthRequestHandler::DataReductionProxyAuthRequestHandler(
37 DataReductionProxySettings* settings) : settings_(settings) {
40 DataReductionProxyAuthRequestHandler::~DataReductionProxyAuthRequestHandler() {
43 DataReductionProxyAuthRequestHandler::TryHandleResult
44 DataReductionProxyAuthRequestHandler::TryHandleAuthentication(
45 net::AuthChallengeInfo* auth_info,
47 base::string16* password) {
49 return TRY_HANDLE_RESULT_IGNORE;
54 if (!IsAcceptableAuthChallenge(auth_info)) {
55 *user = base::string16();
56 *password = base::string16();
57 return TRY_HANDLE_RESULT_IGNORE;
60 base::TimeTicks auth_request =
61 base::TimeTicks::FromInternalValue(auth_request_timestamp_);
62 base::TimeTicks auth_token_invalidation =
63 base::TimeTicks::FromInternalValue(auth_token_invalidation_timestamp_);
66 base::TimeTicks now = Now();
67 if ((now - auth_request).InMilliseconds() < kMinAuthRequestIntervalMs) {
68 // We've received back-to-back failures. There are two possibilities:
69 // 1) Our auth token has expired and we should invalidate it, or
70 // 2) We're receiving spurious failures from the service.
72 // If we haven't recently invalidated our token, we do that here
73 // and make several attempts to authenticate. Otherwise, we fail.
74 back_to_back_failure_count_++;
75 if ((now - auth_token_invalidation).InMilliseconds() <
76 kMinTokenInvalidationIntervalMs) {
77 auth_token_invalidation_timestamp_ = now.ToInternalValue();
78 back_to_back_failure_count_ = 0;
80 if (back_to_back_failure_count_ > kMaxBackToBackFailures) {
81 DLOG(WARNING) << "Interpreting frequent data reduction proxy auth "
82 << "requests as an authorization failure.";
83 back_to_back_failure_count_ = 0;
84 *user = base::string16();
85 *password = base::string16();
86 return TRY_HANDLE_RESULT_CANCEL;
90 back_to_back_failure_count_ = 0;
92 auth_request_timestamp_ = now.ToInternalValue();
94 *password = GetTokenForAuthChallenge(auth_info);
96 if (*password == base::string16()) {
97 *user = base::string16();
98 DLOG(WARNING) << "Data reduction proxy auth produced null token.";
99 return TRY_HANDLE_RESULT_CANCEL;
101 *user = base::UTF8ToUTF16("fw-cookie");
102 return TRY_HANDLE_RESULT_PROCEED;
105 bool DataReductionProxyAuthRequestHandler::IsAcceptableAuthChallenge(
106 net::AuthChallengeInfo* auth_info) {
107 return DataReductionProxySettings::IsAcceptableAuthChallenge(auth_info);
110 base::string16 DataReductionProxyAuthRequestHandler::GetTokenForAuthChallenge(
111 net::AuthChallengeInfo* auth_info) {
113 return settings_->GetTokenForAuthChallenge(auth_info);
116 base::TimeTicks DataReductionProxyAuthRequestHandler::Now() {
117 return base::TimeTicks::Now();
120 } // namespace data_reduction_proxy