blob: ade5f6d76ed7e140f38a19f1125fbc762322160b [file] [log] [blame]
joedowea77cec2015-02-25 23:12:511// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "remoting/test/access_token_fetcher.h"
6
joedowdd5660bd2015-03-06 02:41:027#include <string>
Daniel Chengce48c3c42019-04-26 15:06:088#include <utility>
joedowdd5660bd2015-03-06 02:41:029#include <vector>
10
joedowea77cec2015-02-25 23:12:5111#include "base/bind.h"
12#include "base/logging.h"
gabbac02f52016-05-11 17:55:5113#include "base/threading/thread_task_runner_handle.h"
joedowea77cec2015-02-25 23:12:5114#include "google_apis/gaia/gaia_constants.h"
15#include "google_apis/google_api_keys.h"
16#include "net/url_request/url_fetcher.h"
17#include "remoting/base/url_request_context_getter.h"
Maks Orlovich8db7d0d62018-08-16 19:22:2718#include "services/network/public/cpp/shared_url_loader_factory.h"
19#include "services/network/transitional_url_loader_factory_owner.h"
joedowea77cec2015-02-25 23:12:5120
21namespace {
22const int kMaxGetTokensRetries = 3;
23const char kOauthRedirectUrl[] =
24 "https://chromoting-oauth.talkgadget."
25 "google.com/talkgadget/oauth/chrome-remote-desktop/dev";
joedowdd5660bd2015-03-06 02:41:0226} // namespace
joedowea77cec2015-02-25 23:12:5127
28namespace remoting {
29namespace test {
30
31AccessTokenFetcher::AccessTokenFetcher() {
32 oauth_client_info_ = {
33 google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING),
34 google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING),
35 kOauthRedirectUrl};
36}
37
Chris Watkins6fe52aa2017-11-28 03:24:0538AccessTokenFetcher::~AccessTokenFetcher() = default;
joedowea77cec2015-02-25 23:12:5139
40void AccessTokenFetcher::GetAccessTokenFromAuthCode(
41 const std::string& auth_code,
Sylvain Defresne77274cc2019-06-28 17:17:4842 AccessTokenCallback callback) {
joedowea77cec2015-02-25 23:12:5143 DCHECK(!auth_code.empty());
44 DCHECK(!callback.is_null());
45 DCHECK(access_token_callback_.is_null());
46
joedow9cfae7c2015-07-06 18:44:1847 VLOG(2) << "Calling GetTokensFromAuthCode to exchange auth_code for token";
joedowea77cec2015-02-25 23:12:5148
49 access_token_.clear();
50 refresh_token_.clear();
Sylvain Defresne77274cc2019-06-28 17:17:4851 access_token_callback_ = std::move(callback);
joedowea77cec2015-02-25 23:12:5152
53 // Create a new GaiaOAuthClient for each request to GAIA.
54 CreateNewGaiaOAuthClientInstance();
joedow910989d2016-12-02 21:15:3255 auth_client_->GetTokensFromAuthCode(oauth_client_info_, auth_code,
56 kMaxGetTokensRetries,
57 /*delegate=*/this);
joedowea77cec2015-02-25 23:12:5158}
59
60void AccessTokenFetcher::GetAccessTokenFromRefreshToken(
61 const std::string& refresh_token,
Sylvain Defresne77274cc2019-06-28 17:17:4862 AccessTokenCallback callback) {
joedowea77cec2015-02-25 23:12:5163 DCHECK(!refresh_token.empty());
64 DCHECK(!callback.is_null());
65 DCHECK(access_token_callback_.is_null());
66
joedow9cfae7c2015-07-06 18:44:1867 VLOG(2) << "Calling RefreshToken to generate a new access token";
joedowea77cec2015-02-25 23:12:5168
69 access_token_.clear();
70 refresh_token_ = refresh_token;
Sylvain Defresne77274cc2019-06-28 17:17:4871 access_token_callback_ = std::move(callback);
joedowea77cec2015-02-25 23:12:5172
73 // Create a new GaiaOAuthClient for each request to GAIA.
74 CreateNewGaiaOAuthClientInstance();
joedow13648c62015-03-26 03:47:5575 auth_client_->RefreshToken(oauth_client_info_, refresh_token_,
joedow910989d2016-12-02 21:15:3276 /*scopes=*/std::vector<std::string>(),
joedow13648c62015-03-26 03:47:5577 kMaxGetTokensRetries,
joedow910989d2016-12-02 21:15:3278 /*delegate=*/this);
joedowea77cec2015-02-25 23:12:5179}
80
Maks Orlovich8db7d0d62018-08-16 19:22:2781void AccessTokenFetcher::SetURLLoaderFactoryForTesting(
82 scoped_refptr<network::SharedURLLoaderFactory>
83 url_loader_factory_for_testing) {
84 url_loader_factory_for_testing_ = url_loader_factory_for_testing;
85}
joedowea77cec2015-02-25 23:12:5186
Maks Orlovich8db7d0d62018-08-16 19:22:2787void AccessTokenFetcher::CreateNewGaiaOAuthClientInstance() {
88 scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
89 if (url_loader_factory_for_testing_) {
90 url_loader_factory = url_loader_factory_for_testing_;
91 } else {
92 scoped_refptr<remoting::URLRequestContextGetter> request_context_getter;
93 request_context_getter = new remoting::URLRequestContextGetter(
94 base::ThreadTaskRunnerHandle::Get());
95
96 url_loader_factory_owner_.reset(
97 new network::TransitionalURLLoaderFactoryOwner(request_context_getter));
98 url_loader_factory = url_loader_factory_owner_->GetURLLoaderFactory();
99 }
100
101 auth_client_.reset(new gaia::GaiaOAuthClient(url_loader_factory));
joedowea77cec2015-02-25 23:12:51102}
103
104void AccessTokenFetcher::OnGetTokensResponse(const std::string& refresh_token,
105 const std::string& access_token,
106 int expires_in_seconds) {
joedow9cfae7c2015-07-06 18:44:18107 VLOG(1) << "AccessTokenFetcher::OnGetTokensResponse() Called";
108 VLOG(1) << "--refresh_token: " << refresh_token;
109 VLOG(1) << "--access_token: " << access_token;
110 VLOG(1) << "--expires_in_seconds: " << expires_in_seconds;
joedowea77cec2015-02-25 23:12:51111
112 refresh_token_ = refresh_token;
113 access_token_ = access_token;
114
115 ValidateAccessToken();
116}
117
118void AccessTokenFetcher::OnRefreshTokenResponse(const std::string& access_token,
119 int expires_in_seconds) {
joedow9cfae7c2015-07-06 18:44:18120 VLOG(1) << "AccessTokenFetcher::OnRefreshTokenResponse() Called";
121 VLOG(1) << "--access_token: " << access_token;
122 VLOG(1) << "--expires_in_seconds: " << expires_in_seconds;
joedowea77cec2015-02-25 23:12:51123
124 access_token_ = access_token;
125
126 ValidateAccessToken();
127}
128
129void AccessTokenFetcher::OnGetUserEmailResponse(const std::string& user_email) {
130 // This callback should not be called as we do not request the user's email.
131 NOTREACHED();
132}
133
134void AccessTokenFetcher::OnGetUserIdResponse(const std::string& user_id) {
135 // This callback should not be called as we do not request the user's id.
136 NOTREACHED();
137}
138
139void AccessTokenFetcher::OnGetUserInfoResponse(
dcheng0765c492016-04-06 22:41:53140 std::unique_ptr<base::DictionaryValue> user_info) {
joedowea77cec2015-02-25 23:12:51141 // This callback should not be called as we do not request user info.
142 NOTREACHED();
143}
144
145void AccessTokenFetcher::OnGetTokenInfoResponse(
dcheng0765c492016-04-06 22:41:53146 std::unique_ptr<base::DictionaryValue> token_info) {
joedow9cfae7c2015-07-06 18:44:18147 VLOG(1) << "AccessTokenFetcher::OnGetTokenInfoResponse() Called";
joedowea77cec2015-02-25 23:12:51148
149 std::string error_string;
150 std::string error_description;
151
152 // Check to see if the token_info we received had any errors,
153 // otherwise we will assume that it is valid for our purposes.
154 if (token_info->HasKey("error")) {
155 token_info->GetString("error", &error_string);
156 token_info->GetString("error_description", &error_description);
157
158 LOG(ERROR) << "OnGetTokenInfoResponse returned an error. "
joedowea77cec2015-02-25 23:12:51159 << "error: " << error_string << ", "
160 << "description: " << error_description;
161 access_token_.clear();
162 refresh_token_.clear();
163 } else {
joedow9cfae7c2015-07-06 18:44:18164 VLOG(1) << "Access Token has been validated";
joedowea77cec2015-02-25 23:12:51165 }
166
Daniel Chengce48c3c42019-04-26 15:06:08167 std::move(access_token_callback_).Run(access_token_, refresh_token_);
joedowea77cec2015-02-25 23:12:51168}
169
170void AccessTokenFetcher::OnOAuthError() {
171 LOG(ERROR) << "AccessTokenFetcher::OnOAuthError() Called";
172
173 access_token_.clear();
174 refresh_token_.clear();
175
Daniel Chengce48c3c42019-04-26 15:06:08176 std::move(access_token_callback_).Run(access_token_, refresh_token_);
joedowea77cec2015-02-25 23:12:51177}
178
179void AccessTokenFetcher::OnNetworkError(int response_code) {
180 LOG(ERROR) << "AccessTokenFetcher::OnNetworkError() Called";
181 LOG(ERROR) << "response code: " << response_code;
182
183 access_token_.clear();
184 refresh_token_.clear();
185
Daniel Chengce48c3c42019-04-26 15:06:08186 std::move(access_token_callback_).Run(access_token_, refresh_token_);
joedowea77cec2015-02-25 23:12:51187}
188
189void AccessTokenFetcher::ValidateAccessToken() {
joedow9cfae7c2015-07-06 18:44:18190 VLOG(2) << "Calling GetTokenInfo to validate access token";
joedowea77cec2015-02-25 23:12:51191
192 // Create a new GaiaOAuthClient for each request to GAIA.
193 CreateNewGaiaOAuthClientInstance();
joedow13648c62015-03-26 03:47:55194 auth_client_->GetTokenInfo(access_token_, kMaxGetTokensRetries,
joedow910989d2016-12-02 21:15:32195 /*delegate=*/this);
joedowea77cec2015-02-25 23:12:51196}
197
198} // namespace test
199} // namespace remoting