File: device_oauth2_token_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (205 lines) | stat: -rw-r--r-- 8,361 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_DEVICE_IDENTITY_DEVICE_OAUTH2_TOKEN_SERVICE_H_
#define CHROME_BROWSER_DEVICE_IDENTITY_DEVICE_OAUTH2_TOKEN_SERVICE_H_

#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/device_identity/device_oauth2_token_store.h"
#include "google_apis/gaia/core_account_id.h"
#include "google_apis/gaia/gaia_oauth_client.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_manager.h"

namespace network {
class SharedURLLoaderFactory;
}

class OAuth2AccessTokenFetcher;
class OAuth2AccessTokenConsumer;

// DeviceOAuth2TokenService retrieves OAuth2 access tokens for a given
// set of scopes using the device-level OAuth2 any-api refresh token
// obtained during enterprise device enrollment.
//
// Note that requests must be made from the UI thread.
class DeviceOAuth2TokenService : public OAuth2AccessTokenManager::Delegate,
                                 public gaia::GaiaOAuthClient::Delegate,
                                 public DeviceOAuth2TokenStore::Observer {
 public:
  using RefreshTokenAvailableCallback = base::RepeatingClosure;
  using StatusCallback = base::OnceCallback<void(bool)>;

  DeviceOAuth2TokenService(const DeviceOAuth2TokenService&) = delete;
  DeviceOAuth2TokenService& operator=(const DeviceOAuth2TokenService&) = delete;

  // Persist the given refresh token on the device. Overwrites any previous
  // value. Should only be called during initial device setup. Signals
  // completion via the given callback, passing true if the operation succeeded.
  void SetAndSaveRefreshToken(const std::string& refresh_token,
                              StatusCallback callback);

  // Pull the robot account ID from device policy.
  CoreAccountId GetRobotAccountId() const;

  // If set, this callback will be invoked when a new refresh token is
  // available.
  void SetRefreshTokenAvailableCallback(RefreshTokenAvailableCallback callback);

  // Returns true if the refresh token is available and if the clients of this
  // class may start fetching access tokens.
  bool RefreshTokenIsAvailable() const;

  // Checks in the cache for a valid access token for a specified |account_id|
  // and |scopes|, and if not found starts a request for an OAuth2 access token
  // using the OAuth2 refresh token maintained by this instance for that
  // |account_id|. The caller owns the returned Request.
  // |scopes| is the set of scopes to get an access token for, |consumer| is
  // the object that will be called back with results if the returned request
  // is not deleted.
  std::unique_ptr<OAuth2AccessTokenManager::Request> StartAccessTokenRequest(
      const OAuth2AccessTokenManager::ScopeSet& scopes,
      OAuth2AccessTokenManager::Consumer* consumer);

  // Mark an OAuth2 |access_token| issued for |account_id| and |scopes| as
  // invalid. This should be done if the token was received from this class,
  // but was not accepted by the server (e.g., the server returned
  // 401 Unauthorized). The token will be removed from the cache for the given
  // scopes.
  void InvalidateAccessToken(const OAuth2AccessTokenManager::ScopeSet& scopes,
                             const std::string& access_token);

  OAuth2AccessTokenManager* GetAccessTokenManager();

#if !BUILDFLAG(IS_CHROMEOS)
  // Used on non-ChromeOS platforms to set the email associated with the
  // current service account. On ChromeOS, this function isn't used because
  // the service account identity comes from CrosSettings.
  void SetServiceAccountEmail(const std::string& account_email);
#endif

  // Can be used to override the robot account ID for testing purposes. Most
  // common use case is to easily inject a non-empty account ID to make the
  // refresh token for the robot account visible via GetAccounts() and
  // RefreshTokenIsAvailable().
  void set_robot_account_id_for_testing(const CoreAccountId& account_id);

 private:
  friend class DeviceOAuth2TokenServiceFactory;
  friend class DeviceOAuth2TokenServiceTest;
  struct PendingRequest;

  // Describes the operational state of this object.
  enum State {
    // Pending system salt / refresh token load.
    STATE_LOADING,
    // No token available.
    STATE_NO_TOKEN,
    // System salt loaded, validation not started yet.
    STATE_VALIDATION_PENDING,
    // Refresh token validation underway.
    STATE_VALIDATION_STARTED,
    // Token validation failed.
    STATE_TOKEN_INVALID,
    // Refresh token is valid.
    STATE_TOKEN_VALID,
  };

  // gaia::GaiaOAuthClient::Delegate implementation.
  void OnRefreshTokenResponse(const std::string& access_token,
                              int expires_in_seconds) override;
  void OnGetTokenInfoResponse(const base::Value::Dict& token_info) override;
  void OnOAuthError() override;
  void OnNetworkError(int response_code) override;

  // DeviceOAuth2TokenStore callbacks:
  void OnInitComplete(bool init_result, bool validation_required);
  void OnPrepareTrustedAccountIdFinished(const CoreAccountId& gaia_robot_id,
                                         bool check_passed);

  // DeviceOAuth2TokenStore::Observer:
  void OnRefreshTokenAvailable() override;

  // OAuth2AccessTokenManager::Delegate:
  std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
      const CoreAccountId& account_id,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      OAuth2AccessTokenConsumer* consumer,
      const std::string& token_binding_challenge) override;
  bool HasRefreshToken(const CoreAccountId& account_id) const override;
  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
      const override;
  bool HandleAccessTokenFetch(
      OAuth2AccessTokenManager::RequestImpl* request,
      const CoreAccountId& account_id,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      const std::string& client_id,
      const std::string& client_secret,
      const OAuth2AccessTokenManager::ScopeSet& scopes) override;

  void FireRefreshTokenAvailable();

  // Use DeviceOAuth2TokenServiceFactory to get an instance of this class.
  explicit DeviceOAuth2TokenService(
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      std::unique_ptr<DeviceOAuth2TokenStore> store);
  ~DeviceOAuth2TokenService() override;

  // Flushes |pending_requests_|, indicating the specified result.
  void FlushPendingRequests(bool token_is_valid,
                            GoogleServiceAuthError::State error);

  // Signals failure on the specified request, passing |error| as the reason.
  void FailRequest(OAuth2AccessTokenManager::RequestImpl* request,
                   GoogleServiceAuthError::State error);

  // Starts the token validation flow, i.e. token info fetch.
  void StartValidation();

  void RequestValidation();

  // Returns the refresh token for the robot account id.
  std::string GetRefreshToken() const;

  void ReportServiceError(GoogleServiceAuthError::State error);

  // Returns true if this object has already received the validation result for
  // the token, false otherwise.
  bool HasValidationResult() const;

  std::unique_ptr<OAuth2AccessTokenManager> token_manager_;

  // Currently open requests that are waiting while loading the system salt or
  // validating the token.
  std::vector<raw_ptr<PendingRequest, VectorExperimental>> pending_requests_;

  // Callbacks to invoke, if set, for refresh token-related events.
  RefreshTokenAvailableCallback on_refresh_token_available_callback_;

  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;

  // Current operational state.
  State state_;

  int max_refresh_token_validation_retries_;

  // Flag to indicate whether there are pending requests.
  bool validation_requested_;

  std::unique_ptr<gaia::GaiaOAuthClient> gaia_oauth_client_;

  CoreAccountId robot_account_id_for_testing_;

  std::unique_ptr<DeviceOAuth2TokenStore> store_;

  base::WeakPtrFactory<DeviceOAuth2TokenService> weak_ptr_factory_{this};
};

#endif  // CHROME_BROWSER_DEVICE_IDENTITY_DEVICE_OAUTH2_TOKEN_SERVICE_H_