1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_auth_fetcher.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_constants.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h" 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace policy { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Max retry count for token fetching requests. 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaxRequestAttemptCount = 5; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// OAuth token request retry delay in milliseconds. 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kRequestRestartDelay = 3000; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PolicyOAuth2TokenFetcher::PolicyOAuth2TokenFetcher( 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::URLRequestContextGetter* auth_context_getter, 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::URLRequestContextGetter* system_context_getter, 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const TokenCallback& callback) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : auth_context_getter_(auth_context_getter), 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) system_context_getter_(system_context_getter), 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_count_(0), 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) failed_(false), 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback_(callback) {} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PolicyOAuth2TokenFetcher::~PolicyOAuth2TokenFetcher() {} 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::Start() { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_count_ = 0; 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) StartFetchingRefreshToken(); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::StartFetchingRefreshToken() { 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) refresh_token_fetcher_.reset(new GaiaAuthFetcher( 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this, GaiaConstants::kChromeSource, auth_context_getter_.get())); 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) refresh_token_fetcher_->StartCookieForOAuthLoginTokenExchange(std::string()); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::StartFetchingAccessToken() { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<std::string> scopes; 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth); 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scopes.push_back(GaiaConstants::kOAuthWrapBridgeUserInfoScope); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) access_token_fetcher_.reset( 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new OAuth2AccessTokenFetcherImpl(this, 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) system_context_getter_.get(), 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) oauth2_refresh_token_)); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) access_token_fetcher_->Start( 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_id(), 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scopes); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::OnClientOAuthSuccess( 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) { 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(1) << "OAuth2 tokens for policy fetching succeeded."; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) oauth2_refresh_token_ = oauth2_tokens.refresh_token; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_count_ = 0; 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) StartFetchingAccessToken(); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::OnClientOAuthFailure( 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GoogleServiceAuthError& error) { 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(1) << "OAuth2 tokens fetch for policy fetch failed!"; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetryOnError(error, 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingRefreshToken, 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AsWeakPtr())); 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::OnGetTokenSuccess( 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& access_token, 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::Time& expiration_time) { 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(1) << "OAuth2 access token (device management) fetching succeeded."; 91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch oauth2_access_token_ = access_token; 92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ForwardPolicyToken(access_token, 93558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch GoogleServiceAuthError(GoogleServiceAuthError::NONE)); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::OnGetTokenFailure( 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GoogleServiceAuthError& error) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "OAuth2 access token (device management) fetching failed!"; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RetryOnError(error, 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&PolicyOAuth2TokenFetcher::StartFetchingAccessToken, 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AsWeakPtr())); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyOAuth2TokenFetcher::RetryOnError(const GoogleServiceAuthError& error, 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::Closure& task) { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((error.state() == GoogleServiceAuthError::CONNECTION_FAILED || 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE || 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error.state() == GoogleServiceAuthError::REQUEST_CANCELED) && 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_count_ < kMaxRequestAttemptCount) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) retry_count_++; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::PostDelayedTask( 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserThread::UI, FROM_HERE, task, 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kRequestRestartDelay)); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Unrecoverable error or retry count max reached."; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) failed_ = true; 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Invoking the |callback_| signals to the owner of this object that it has 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // completed, and the owner may delete this object on the callback method. 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // So don't rely on |this| still being valid after ForwardPolicyToken() 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // returns i.e. don't write to |failed_| or other fields. 123558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ForwardPolicyToken(std::string(), error); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 126558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid PolicyOAuth2TokenFetcher::ForwardPolicyToken( 127558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const std::string& token, 128558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const GoogleServiceAuthError& error) { 129558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!callback_.is_null()) 130558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch callback_.Run(token, error); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace policy 134