device_oauth2_token_service.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <string> 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <vector> 9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/prefs/pref_service.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/browser_process.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/policy/browser_policy_connector.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/cryptohome/cryptohome_library.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/gaia_urls.h" 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/google_service_auth_error.h" 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst char kServiceScopeGetUserInfo[] = 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "https://www.googleapis.com/auth/userinfo.email"; 2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos { 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// A wrapper for the consumer passed to StartRequest, which doesn't call 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// through to the target Consumer unless the refresh token validation is 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// complete. Additionally derives from the RequestImpl, so that it 33558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// can be passed back to the caller and directly deleted when cancelling 34558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// the request. 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass DeviceOAuth2TokenService::ValidatingConsumer 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : public OAuth2TokenService::Consumer, 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public OAuth2TokenService::RequestImpl, 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public gaia::GaiaOAuthClient::Delegate { 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit ValidatingConsumer(DeviceOAuth2TokenService* token_service, 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Consumer* consumer); 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~ValidatingConsumer(); 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void StartValidation(); 45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // OAuth2TokenService::Consumer 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnGetTokenSuccess( 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& access_token, 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Time& expiration_time) OVERRIDE; 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnGetTokenFailure( 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GoogleServiceAuthError& error) OVERRIDE; 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // gaia::GaiaOAuthClient::Delegate implementation. 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnRefreshTokenResponse(const std::string& access_token, 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int expires_in_seconds) OVERRIDE; 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnGetTokenInfoResponse(scoped_ptr<DictionaryValue> token_info) 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OVERRIDE; 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnOAuthError() OVERRIDE; 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnNetworkError(int response_code) OVERRIDE; 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void RefreshTokenIsValid(bool is_valid); 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void InformConsumer(); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeviceOAuth2TokenService* token_service_; 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Consumer* consumer_; 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We don't know which will complete first: the validation or the token 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // minting. So, we need to cache the results so the final callback can 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // take action. 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // RefreshTokenValidationConsumer results 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool token_validation_done_; 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool token_is_valid_; 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // OAuth2TokenService::Consumer results 80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool token_fetch_done_; 81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string access_token_; 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Time expiration_time_; 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<GoogleServiceAuthError> error_; 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDeviceOAuth2TokenService::ValidatingConsumer::ValidatingConsumer( 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeviceOAuth2TokenService* token_service, 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Consumer* consumer) 8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) : OAuth2TokenService::RequestImpl(this), 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_service_(token_service), 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch consumer_(consumer), 92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_validation_done_(false), 93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_is_valid_(false), 94558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch token_fetch_done_(false) { 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDeviceOAuth2TokenService::ValidatingConsumer::~ValidatingConsumer() { 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 10068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DeviceOAuth2TokenService::ValidatingConsumer::StartValidation() { 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!gaia_oauth_client_); 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch g_browser_process->system_request_context())); 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia::OAuthClientInfo client_info; 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch client_info.client_id = gaia_urls->oauth2_chrome_client_id(); 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch client_info.client_secret = gaia_urls->oauth2_chrome_client_secret(); 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_->RefreshToken( 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch client_info, 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_service_->GetRefreshToken(token_service_->GetRobotAccountId()), 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string>(1, kServiceScopeGetUserInfo), 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_service_->max_refresh_token_validation_retries_, 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this); 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnRefreshTokenResponse( 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& access_token, 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int expires_in_seconds) { 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_->GetTokenInfo( 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch access_token, 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_service_->max_refresh_token_validation_retries_, 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this); 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenInfoResponse( 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<DictionaryValue> token_info) { 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string gaia_robot_id; 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_info->GetString("email", &gaia_robot_id); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string policy_robot_id = token_service_->GetRobotAccountId(); 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (policy_robot_id == gaia_robot_id) { 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(true); 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (gaia_robot_id.empty()) { 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "Device service account owner in policy is empty."; 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(INFO) << "Device service account owner in policy does not match " 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << "refresh token owner \"" << gaia_robot_id << "\"."; 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(false); 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnOAuthError() { 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(false); 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnNetworkError( 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int response_code) { 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(false); 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenSuccess( 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& access_token, 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Time& expiration_time) { 16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_EQ(request, this); 161558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch token_fetch_done_ = true; 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch access_token_ = access_token; 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expiration_time_ = expiration_time; 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (token_validation_done_) 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InformConsumer(); 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenFailure( 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GoogleServiceAuthError& error) { 17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_EQ(request, this); 172558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch token_fetch_done_ = true; 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_.reset(new GoogleServiceAuthError(error.state())); 174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (token_validation_done_) 175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InformConsumer(); 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::RefreshTokenIsValid( 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool is_valid) { 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_validation_done_ = true; 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_is_valid_ = is_valid; 18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_service_->OnValidationComplete(is_valid); 183558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (token_fetch_done_) 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InformConsumer(); 185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::InformConsumer() { 188558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK(token_fetch_done_); 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(token_validation_done_); 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Note: this object (which is also the Request instance) may be deleted in 192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // these consumer callbacks, so the callbacks must be the last line executed. 193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Also, make copies of the parameters passed to the consumer to avoid invalid 194ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // memory accesses when the consumer deletes |this| immediately. 195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!token_is_valid_) { 196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) consumer_->OnGetTokenFailure(this, GoogleServiceAuthError( 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (error_) { 199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch GoogleServiceAuthError error_copy = *error_; 200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch consumer_->OnGetTokenFailure(this, error_copy); 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string access_token_copy = access_token_; 203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Time expiration_time_copy = expiration_time_; 204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch consumer_->OnGetTokenSuccess(this, access_token_copy, expiration_time_copy); 205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeviceOAuth2TokenService::DeviceOAuth2TokenService( 209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::URLRequestContextGetter* getter, 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PrefService* local_state) 211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch : refresh_token_is_valid_(false), 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch max_refresh_token_validation_retries_(3), 213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch url_request_context_getter_(getter), 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) local_state_(local_state) { 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeviceOAuth2TokenService::~DeviceOAuth2TokenService() { 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::OnValidationComplete( 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool refresh_token_is_valid) { 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch refresh_token_is_valid_ = refresh_token_is_valid; 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeviceOAuth2TokenService::RegisterPrefs(PrefRegistrySimple* registry) { 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterStringPref(prefs::kDeviceRobotAnyApiRefreshToken, 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string()); 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeviceOAuth2TokenService::SetAndSaveRefreshToken( 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& refresh_token) { 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string encrypted_refresh_token = 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CryptohomeLibrary::Get()->EncryptWithSystemSalt(refresh_token); 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) local_state_->SetString(prefs::kDeviceRobotAnyApiRefreshToken, 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) encrypted_refresh_token); 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string DeviceOAuth2TokenService::GetRefreshToken( 24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id) { 24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_EQ(account_id, GetRobotAccountId()); 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (refresh_token_.empty()) { 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string encrypted_refresh_token = 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) local_state_->GetString(prefs::kDeviceRobotAnyApiRefreshToken); 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) refresh_token_ = CryptohomeLibrary::Get()->DecryptWithSystemSalt( 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) encrypted_refresh_token); 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return refresh_token_; 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string DeviceOAuth2TokenService::GetRobotAccountId() { 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch policy::BrowserPolicyConnector* connector = 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch g_browser_process->browser_policy_connector(); 258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (connector) 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return connector->GetDeviceCloudPolicyManager()->GetRobotAccountId(); 260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return std::string(); 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)net::URLRequestContextGetter* DeviceOAuth2TokenService::GetRequestContext() { 2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return url_request_context_getter_.get(); 2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 26768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)scoped_ptr<OAuth2TokenService::RequestImpl> 26868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DeviceOAuth2TokenService::CreateRequest( 26968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OAuth2TokenService::Consumer* consumer) { 27068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (refresh_token_is_valid_) 27168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return OAuth2TokenService::CreateRequest(consumer); 27268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 27368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Substitute our own consumer to wait for refresh token validation. 27468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<ValidatingConsumer> validating_consumer( 27568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) new ValidatingConsumer(this, consumer)); 27668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) validating_consumer->StartValidation(); 27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return validating_consumer.PassAs<RequestImpl>(); 27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace chromeos 281