policy_oauth2_token_fetcher.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <vector>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "base/bind.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/string_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_auth_fetcher.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_constants.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_fetcher.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace policy {
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Max retry count for token fetching requests.
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kMaxRequestAttemptCount = 5;
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// OAuth token request retry delay in milliseconds.
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kRequestRestartDelay = 3000;
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PolicyOAuth2TokenFetcher::PolicyOAuth2TokenFetcher(
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    net::URLRequestContextGetter* auth_context_getter,
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    net::URLRequestContextGetter* system_context_getter,
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TokenCallback& callback)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : auth_context_getter_(auth_context_getter),
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      system_context_getter_(system_context_getter),
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      retry_count_(0),
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      failed_(false),
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      callback_(callback) {}
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PolicyOAuth2TokenFetcher::PolicyOAuth2TokenFetcher(
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    net::URLRequestContextGetter* system_context_getter,
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& oauth2_refresh_token,
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const TokenCallback& callback)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : system_context_getter_(system_context_getter),
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      oauth2_refresh_token_(oauth2_refresh_token),
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      retry_count_(0),
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      failed_(false),
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      callback_(callback) {}
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PolicyOAuth2TokenFetcher::~PolicyOAuth2TokenFetcher() {}
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PolicyOAuth2TokenFetcher::Start() {
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  retry_count_ = 0;
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (oauth2_refresh_token_.empty()) {
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    StartFetchingRefreshToken();
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    StartFetchingAccessToken();
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PolicyOAuth2TokenFetcher::StartFetchingRefreshToken() {
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!refresh_token_fetcher_.get());
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  refresh_token_fetcher_.reset(
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new GaiaAuthFetcher(this,
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          GaiaConstants::kChromeSource,
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          auth_context_getter_));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  refresh_token_fetcher_->StartCookieForOAuthLoginTokenExchange(EmptyString());
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyOAuth2TokenFetcher::StartFetchingAccessToken() {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> scopes;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  access_token_fetcher_.reset(
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      new OAuth2AccessTokenFetcher(this, system_context_getter_));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  access_token_fetcher_->Start(
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      oauth2_refresh_token_,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scopes);
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PolicyOAuth2TokenFetcher::OnClientOAuthSuccess(
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) {
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "OAuth2 tokens for policy fetching succeeded.";
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  oauth2_tokens_ = oauth2_tokens;
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  oauth2_refresh_token_ = oauth2_tokens.refresh_token;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  retry_count_ = 0;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StartFetchingAccessToken();
93b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyOAuth2TokenFetcher::OnClientOAuthFailure(
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GoogleServiceAuthError& error) {
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  LOG(ERROR) << "OAuth2 tokens fetch for policy fetch failed!";
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RetryOnError(error,
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)               base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingRefreshToken,
100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                          AsWeakPtr()));
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyOAuth2TokenFetcher::OnGetTokenSuccess(
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& access_token,
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::Time& expiration_time) {
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LOG(INFO) << "OAuth2 access token (device management) fetching succeeded.";
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ForwardPolicyToken(access_token);
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PolicyOAuth2TokenFetcher::OnGetTokenFailure(
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const GoogleServiceAuthError& error) {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  LOG(ERROR) << "OAuth2 access token (device management) fetching failed!";
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RetryOnError(error,
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingAccessToken,
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                          AsWeakPtr()));
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PolicyOAuth2TokenFetcher::RetryOnError(const GoogleServiceAuthError& error,
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            const base::Closure& task) {
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if ((error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE ||
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       error.state() == GoogleServiceAuthError::REQUEST_CANCELED) &&
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      retry_count_ < kMaxRequestAttemptCount) {
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    retry_count_++;
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BrowserThread::PostDelayedTask(
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        BrowserThread::UI, FROM_HERE, task,
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "Unrecoverable error or retry count max reached.";
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  failed_ = true;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invoking the |callback_| signals to the owner of this object that it has
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completed, and the owner may delete this object on the callback method.
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // So don't rely on |this| still being valid after ForwardPolicyToken()
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // returns i.e. don't write to |failed_| or other fields.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ForwardPolicyToken(EmptyString());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PolicyOAuth2TokenFetcher::ForwardPolicyToken(const std::string& token) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_.Run(token);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)