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