device_oauth2_token_service.h revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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)#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_ 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_ 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string> 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <vector> 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/callback.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/gtest_prod_util.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/memory/weak_ptr.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/stl_util.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "google_apis/gaia/gaia_oauth_client.h" 19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "google_apis/gaia/oauth2_token_service.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace gaia { 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class GaiaOAuthClient; 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net { 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class URLRequestContextGetter; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class PrefRegistrySimple; 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class PrefService; 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// DeviceOAuth2TokenService retrieves OAuth2 access tokens for a given 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// set of scopes using the device-level OAuth2 any-api refresh token 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// obtained during enterprise device enrollment. 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// See |OAuth2TokenService| for usage details. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// When using DeviceOAuth2TokenSerivce, a value of |GetRobotAccountId| should 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// be used in places where API expects |account_id|. 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note that requests must be made from the UI thread. 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class DeviceOAuth2TokenService : public OAuth2TokenService, 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public gaia::GaiaOAuthClient::Delegate { 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef base::Callback<void(bool)> StatusCallback; 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Persist the given refresh token on the device. Overwrites any previous 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // value. Should only be called during initial device setup. Signals 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // completion via the given callback, passing true if the operation succeeded. 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void SetAndSaveRefreshToken(const std::string& refresh_token, 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const StatusCallback& callback); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) static void RegisterPrefs(PrefRegistrySimple* registry); 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Implementation of OAuth2TokenService. 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual bool RefreshTokenIsAvailable(const std::string& account_id) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const OVERRIDE; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Pull the robot account ID from device policy. 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual std::string GetRobotAccountId() const; 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // gaia::GaiaOAuthClient::Delegate implementation. 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnRefreshTokenResponse(const std::string& access_token, 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int expires_in_seconds) OVERRIDE; 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnGetTokenInfoResponse( 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<base::DictionaryValue> token_info) OVERRIDE; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnOAuthError() OVERRIDE; 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void OnNetworkError(int response_code) OVERRIDE; 72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) protected: 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Implementation of OAuth2TokenService. 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE; 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void FetchOAuth2Token(RequestImpl* request, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& account_id, 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::URLRequestContextGetter* getter, 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& client_id, 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& client_secret, 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ScopeSet& scopes) OVERRIDE; 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher( 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& account_id, 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) net::URLRequestContextGetter* getter, 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OAuth2AccessTokenConsumer* consumer) OVERRIDE; 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) struct PendingRequest; 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) friend class DeviceOAuth2TokenServiceFactory; 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch friend class DeviceOAuth2TokenServiceTest; 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Describes the operational state of this object. 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) enum State { 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Pending system salt / refresh token load. 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STATE_LOADING, 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No token available. 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STATE_NO_TOKEN, 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // System salt loaded, validation not started yet. 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STATE_VALIDATION_PENDING, 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Refresh token validation underway. 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STATE_VALIDATION_STARTED, 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Token validation failed. 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STATE_TOKEN_INVALID, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Refresh token is valid. 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STATE_TOKEN_VALID, 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Use DeviceOAuth2TokenServiceFactory to get an instance of this class. 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Ownership of |token_encryptor| will be taken. 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) explicit DeviceOAuth2TokenService(net::URLRequestContextGetter* getter, 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PrefService* local_state); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~DeviceOAuth2TokenService(); 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Returns the refresh token for account_id. 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string GetRefreshToken(const std::string& account_id) const; 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Handles completion of the system salt input. 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void DidGetSystemSalt(const std::string& system_salt); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Checks whether |gaia_robot_id| matches the expected account ID indicated in 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // device settings. 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void CheckRobotAccountId(const std::string& gaia_robot_id); 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Encrypts and saves the refresh token. Should only be called when the system 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // salt is available. 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void EncryptAndSaveToken(); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Starts the token validation flow, i.e. token info fetch. 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StartValidation(); 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Flushes |pending_requests_|, indicating the specified result. 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void FlushPendingRequests(bool token_is_valid, 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GoogleServiceAuthError::State error); 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Flushes |token_save_callbacks_|, indicating the specified result. 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void FlushTokenSaveCallbacks(bool result); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Signals failure on the specified request, passing |error| as the reason. 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void FailRequest(RequestImpl* request, GoogleServiceAuthError::State error); 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Dependencies. 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PrefService* local_state_; 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Current operational state. 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) State state_; 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Token save callbacks waiting to be completed. 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<StatusCallback> token_save_callbacks_; 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Currently open requests that are waiting while loading the system salt or 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // validating the token. 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::vector<PendingRequest*> pending_requests_; 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The system salt for encrypting and decrypting the refresh token. 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::string system_salt_; 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) int max_refresh_token_validation_retries_; 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Cache the decrypted refresh token, so we only decrypt once. 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string refresh_token_; 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_; 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::WeakPtrFactory<DeviceOAuth2TokenService> weak_ptr_factory_; 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DeviceOAuth2TokenService); 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace chromeos 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_ 173