device_oauth2_token_service.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/chromeos/settings/token_encryptor.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/gaia_urls.h" 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/google_service_auth_error.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "policy/proto/device_management_backend.pb.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, 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& account_id, 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Consumer* consumer); 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~ValidatingConsumer(); 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void StartValidation(); 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // OAuth2TokenService::Consumer 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnGetTokenSuccess( 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& access_token, 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Time& expiration_time) OVERRIDE; 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnGetTokenFailure( 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GoogleServiceAuthError& error) OVERRIDE; 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // gaia::GaiaOAuthClient::Delegate implementation. 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnRefreshTokenResponse(const std::string& access_token, 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int expires_in_seconds) OVERRIDE; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void OnGetTokenInfoResponse( 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> token_info) OVERRIDE; 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnOAuthError() OVERRIDE; 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void OnNetworkError(int response_code) OVERRIDE; 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void RefreshTokenIsValid(bool is_valid); 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch void InformConsumer(); 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeviceOAuth2TokenService* token_service_; 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Consumer* consumer_; 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; 71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // We don't know which will complete first: the validation or the token 73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // minting. So, we need to cache the results so the final callback can 74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // take action. 75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // RefreshTokenValidationConsumer results 77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool token_validation_done_; 78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool token_is_valid_; 79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // OAuth2TokenService::Consumer results 81558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool token_fetch_done_; 82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string access_token_; 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Time expiration_time_; 84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<GoogleServiceAuthError> error_; 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDeviceOAuth2TokenService::ValidatingConsumer::ValidatingConsumer( 88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DeviceOAuth2TokenService* token_service, 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& account_id, 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Consumer* consumer) 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : OAuth2TokenService::Consumer("device_token_service"), 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OAuth2TokenService::RequestImpl(account_id, this), 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_service_(token_service), 94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch consumer_(consumer), 95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_validation_done_(false), 96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_is_valid_(false), 97558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch token_fetch_done_(false) { 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochDeviceOAuth2TokenService::ValidatingConsumer::~ValidatingConsumer() { 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void DeviceOAuth2TokenService::ValidatingConsumer::StartValidation() { 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(!gaia_oauth_client_); 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_.reset(new gaia::GaiaOAuthClient( 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch g_browser_process->system_request_context())); 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GaiaUrls* gaia_urls = GaiaUrls::GetInstance(); 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia::OAuthClientInfo client_info; 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch client_info.client_id = gaia_urls->oauth2_chrome_client_id(); 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch client_info.client_secret = gaia_urls->oauth2_chrome_client_secret(); 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_->RefreshToken( 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch client_info, 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_service_->GetRefreshToken(token_service_->GetRobotAccountId()), 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::vector<std::string>(1, kServiceScopeGetUserInfo), 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_service_->max_refresh_token_validation_retries_, 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this); 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnRefreshTokenResponse( 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& access_token, 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int expires_in_seconds) { 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gaia_oauth_client_->GetTokenInfo( 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch access_token, 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_service_->max_refresh_token_validation_retries_, 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this); 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenInfoResponse( 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::DictionaryValue> token_info) { 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string gaia_robot_id; 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_info->GetString("email", &gaia_robot_id); 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string policy_robot_id = token_service_->GetRobotAccountId(); 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (policy_robot_id == gaia_robot_id) { 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(true); 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (gaia_robot_id.empty()) { 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(WARNING) << "Device service account owner in policy is empty."; 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(WARNING) << "Device service account owner in policy does not match " 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "refresh token owner \"" << gaia_robot_id << "\"."; 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(false); 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnOAuthError() { 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(false); 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnNetworkError( 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int response_code) { 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RefreshTokenIsValid(false); 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenSuccess( 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const std::string& access_token, 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::Time& expiration_time) { 16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_EQ(request, this); 164558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch token_fetch_done_ = true; 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch access_token_ = access_token; 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch expiration_time_ = expiration_time; 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (token_validation_done_) 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InformConsumer(); 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::OnGetTokenFailure( 172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const Request* request, 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GoogleServiceAuthError& error) { 17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_EQ(request, this); 175558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch token_fetch_done_ = true; 176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch error_.reset(new GoogleServiceAuthError(error.state())); 177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (token_validation_done_) 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InformConsumer(); 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::RefreshTokenIsValid( 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool is_valid) { 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_validation_done_ = true; 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch token_is_valid_ = is_valid; 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) token_service_->OnValidationComplete(is_valid); 186558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (token_fetch_done_) 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch InformConsumer(); 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::ValidatingConsumer::InformConsumer() { 191558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DCHECK(token_fetch_done_); 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(token_validation_done_); 19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Note: this object (which is also the Request instance) may be deleted in 195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // these consumer callbacks, so the callbacks must be the last line executed. 196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Also, make copies of the parameters passed to the consumer to avoid invalid 197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // memory accesses when the consumer deletes |this| immediately. 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!token_is_valid_) { 199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) consumer_->OnGetTokenFailure(this, GoogleServiceAuthError( 200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); 201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else if (error_) { 202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch GoogleServiceAuthError error_copy = *error_; 203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch consumer_->OnGetTokenFailure(this, error_copy); 204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string access_token_copy = access_token_; 206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Time expiration_time_copy = expiration_time_; 207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch consumer_->OnGetTokenSuccess(this, access_token_copy, expiration_time_copy); 208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeviceOAuth2TokenService::DeviceOAuth2TokenService( 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) net::URLRequestContextGetter* getter, 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) PrefService* local_state, 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) TokenEncryptor* token_encryptor) 215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch : refresh_token_is_valid_(false), 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch max_refresh_token_validation_retries_(3), 217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch url_request_context_getter_(getter), 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) local_state_(local_state), 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) token_encryptor_(token_encryptor), 2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) weak_ptr_factory_(this) { 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)DeviceOAuth2TokenService::~DeviceOAuth2TokenService() { 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid DeviceOAuth2TokenService::OnValidationComplete( 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch bool refresh_token_is_valid) { 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch refresh_token_is_valid_ = refresh_token_is_valid; 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeviceOAuth2TokenService::RegisterPrefs(PrefRegistrySimple* registry) { 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterStringPref(prefs::kDeviceRobotAnyApiRefreshToken, 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string()); 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool DeviceOAuth2TokenService::SetAndSaveRefreshToken( 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& refresh_token) { 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string encrypted_refresh_token = 2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) token_encryptor_->EncryptWithSystemSalt(refresh_token); 2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (encrypted_refresh_token.empty()) { 2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) LOG(ERROR) << "Failed to encrypt refresh token; save aborted."; 2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) local_state_->SetString(prefs::kDeviceRobotAnyApiRefreshToken, 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) encrypted_refresh_token); 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)std::string DeviceOAuth2TokenService::GetRefreshToken( 25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& account_id) { 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (refresh_token_.empty()) { 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string encrypted_refresh_token = 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) local_state_->GetString(prefs::kDeviceRobotAnyApiRefreshToken); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) refresh_token_ = token_encryptor_->DecryptWithSystemSalt( 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) encrypted_refresh_token); 2621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!encrypted_refresh_token.empty() && refresh_token_.empty()) 2631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) LOG(ERROR) << "Failed to decrypt refresh token."; 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return refresh_token_; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string DeviceOAuth2TokenService::GetRobotAccountId() { 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) policy::BrowserPolicyConnectorChromeOS* connector = 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_browser_process->platform_part()->browser_policy_connector_chromeos(); 271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (connector) 272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return connector->GetDeviceCloudPolicyManager()->GetRobotAccountId(); 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return std::string(); 274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)net::URLRequestContextGetter* DeviceOAuth2TokenService::GetRequestContext() { 2773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return url_request_context_getter_.get(); 2783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)scoped_ptr<OAuth2TokenService::RequestImpl> 28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)DeviceOAuth2TokenService::CreateRequest( 282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& account_id, 28368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) OAuth2TokenService::Consumer* consumer) { 28468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (refresh_token_is_valid_) 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return OAuth2TokenService::CreateRequest(account_id, consumer); 28668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 28768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Substitute our own consumer to wait for refresh token validation. 28868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<ValidatingConsumer> validating_consumer( 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ValidatingConsumer(this, account_id, consumer)); 29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) validating_consumer->StartValidation(); 29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) return validating_consumer.PassAs<RequestImpl>(); 29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 29368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace chromeos 295