1 // Copyright 2014 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 "base/bind.h" 6 #include "base/memory/scoped_ptr.h" 7 #include "base/strings/stringprintf.h" 8 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" 9 #include "chrome/browser/supervised_user/supervised_user_refresh_token_fetcher.h" 10 #include "chrome/test/base/testing_profile.h" 11 #include "content/public/test/test_browser_thread_bundle.h" 12 #include "google_apis/gaia/gaia_constants.h" 13 #include "google_apis/gaia/gaia_oauth_client.h" 14 #include "google_apis/gaia/gaia_urls.h" 15 #include "google_apis/gaia/google_service_auth_error.h" 16 #include "google_apis/gaia/oauth2_token_service.h" 17 #include "net/base/net_errors.h" 18 #include "net/base/url_util.h" 19 #include "net/http/http_request_headers.h" 20 #include "net/http/http_status_code.h" 21 #include "net/url_request/test_url_fetcher_factory.h" 22 #include "net/url_request/url_fetcher_delegate.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 namespace { 26 27 const char kAccountId[] = "account_id"; 28 const char kDeviceName[] = "Compy"; 29 const char kSupervisedUserId[] = "abcdef"; 30 31 const char kAccessToken[] = "accesstoken"; 32 const char kAuthorizationCode[] = "authorizationcode"; 33 const char kSupervisedUserToken[] = "supervisedusertoken"; 34 const char kOAuth2RefreshToken[] = "refreshtoken"; 35 36 const char kIssueTokenResponseFormat[] = 37 "{" 38 " \"code\": \"%s\"" 39 "}"; 40 41 const char kGetRefreshTokenResponseFormat[] = 42 "{" 43 " \"access_token\": \"<ignored>\"," 44 " \"expires_in\": 12345," 45 " \"refresh_token\": \"%s\"" 46 "}"; 47 48 // Utility methods -------------------------------------------------- 49 50 // Slightly hacky way to extract a value from a URL-encoded POST request body. 51 bool GetValueForKey(const std::string& encoded_string, 52 const std::string& key, 53 std::string* value) { 54 GURL url("http://example.com/?" + encoded_string); 55 return net::GetValueForKeyInQuery(url, key, value); 56 } 57 58 void SendResponse(net::TestURLFetcher* url_fetcher, 59 const std::string& response) { 60 url_fetcher->set_status( 61 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0)); 62 url_fetcher->set_response_code(net::HTTP_OK); 63 url_fetcher->SetResponseString(response); 64 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 65 } 66 67 void SetNetworkError(net::TestURLFetcher* url_fetcher, int error) { 68 url_fetcher->set_status( 69 net::URLRequestStatus(net::URLRequestStatus::FAILED, error)); 70 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 71 } 72 73 void SetHttpError(net::TestURLFetcher* url_fetcher, int error) { 74 url_fetcher->set_status(net::URLRequestStatus()); 75 url_fetcher->set_response_code(error); 76 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 77 } 78 79 void VerifyTokenRequest( 80 std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests) { 81 ASSERT_EQ(1u, requests.size()); 82 EXPECT_EQ(1u, requests[0].scopes.size()); 83 EXPECT_EQ(1u, requests[0].scopes.count(GaiaConstants::kOAuth1LoginScope)); 84 } 85 86 } // namespace 87 88 class SupervisedUserRefreshTokenFetcherTest : public testing::Test { 89 public: 90 SupervisedUserRefreshTokenFetcherTest(); 91 virtual ~SupervisedUserRefreshTokenFetcherTest() {} 92 93 protected: 94 void StartFetching(); 95 96 net::TestURLFetcher* GetIssueTokenRequest(); 97 net::TestURLFetcher* GetRefreshTokenRequest(); 98 99 void MakeOAuth2TokenServiceRequestSucceed(); 100 void MakeOAuth2TokenServiceRequestFail(GoogleServiceAuthError::State error); 101 void MakeIssueTokenRequestSucceed(); 102 void MakeRefreshTokenFetchSucceed(); 103 104 void Reset(); 105 106 const GoogleServiceAuthError& error() const { return error_; } 107 const std::string& token() const { return token_; } 108 109 private: 110 void OnTokenFetched(const GoogleServiceAuthError& error, 111 const std::string& token); 112 113 content::TestBrowserThreadBundle thread_bundle_; 114 TestingProfile profile_; 115 FakeProfileOAuth2TokenService oauth2_token_service_; 116 net::TestURLFetcherFactory url_fetcher_factory_; 117 scoped_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher_; 118 119 GoogleServiceAuthError error_; 120 std::string token_; 121 base::WeakPtrFactory<SupervisedUserRefreshTokenFetcherTest> weak_ptr_factory_; 122 }; 123 124 SupervisedUserRefreshTokenFetcherTest::SupervisedUserRefreshTokenFetcherTest() 125 : token_fetcher_(SupervisedUserRefreshTokenFetcher::Create( 126 &oauth2_token_service_, 127 kAccountId, 128 profile_.GetRequestContext())), 129 error_(GoogleServiceAuthError::NONE), 130 weak_ptr_factory_(this) {} 131 132 void SupervisedUserRefreshTokenFetcherTest::StartFetching() { 133 oauth2_token_service_.IssueRefreshToken(kOAuth2RefreshToken); 134 token_fetcher_->Start( 135 kSupervisedUserId, 136 kDeviceName, 137 base::Bind( 138 &SupervisedUserRefreshTokenFetcherTest::OnTokenFetched, 139 weak_ptr_factory_.GetWeakPtr())); 140 } 141 142 net::TestURLFetcher* 143 SupervisedUserRefreshTokenFetcherTest::GetIssueTokenRequest() { 144 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); 145 if (!url_fetcher) 146 return NULL; 147 148 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_issue_token_url(), 149 url_fetcher->GetOriginalURL()); 150 std::string access_token; 151 net::HttpRequestHeaders headers; 152 url_fetcher->GetExtraRequestHeaders(&headers); 153 EXPECT_TRUE(headers.GetHeader("Authorization", &access_token)); 154 EXPECT_EQ(std::string("Bearer ") + kAccessToken, access_token); 155 const std::string upload_data = url_fetcher->upload_data(); 156 std::string supervised_user_id; 157 EXPECT_TRUE(GetValueForKey(upload_data, "profile_id", &supervised_user_id)); 158 EXPECT_EQ(kSupervisedUserId, supervised_user_id); 159 std::string device_name; 160 EXPECT_TRUE(GetValueForKey(upload_data, "device_name", &device_name)); 161 EXPECT_EQ(kDeviceName, device_name); 162 return url_fetcher; 163 } 164 165 net::TestURLFetcher* 166 SupervisedUserRefreshTokenFetcherTest::GetRefreshTokenRequest() { 167 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID( 168 gaia::GaiaOAuthClient::kUrlFetcherId); 169 if (!url_fetcher) 170 return NULL; 171 172 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_token_url(), 173 url_fetcher->GetOriginalURL()); 174 std::string auth_code; 175 EXPECT_TRUE(GetValueForKey(url_fetcher->upload_data(), "code", &auth_code)); 176 EXPECT_EQ(kAuthorizationCode, auth_code); 177 return url_fetcher; 178 } 179 180 void 181 SupervisedUserRefreshTokenFetcherTest::MakeOAuth2TokenServiceRequestSucceed() { 182 std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests = 183 oauth2_token_service_.GetPendingRequests(); 184 VerifyTokenRequest(requests); 185 base::Time expiration_date = base::Time::Now() + 186 base::TimeDelta::FromHours(1); 187 oauth2_token_service_.IssueTokenForScope(requests[0].scopes, 188 kAccessToken, 189 expiration_date); 190 } 191 192 void 193 SupervisedUserRefreshTokenFetcherTest::MakeOAuth2TokenServiceRequestFail( 194 GoogleServiceAuthError::State error) { 195 std::vector<FakeProfileOAuth2TokenService::PendingRequest> requests = 196 oauth2_token_service_.GetPendingRequests(); 197 VerifyTokenRequest(requests); 198 oauth2_token_service_.IssueErrorForScope(requests[0].scopes, 199 GoogleServiceAuthError(error)); 200 } 201 202 void SupervisedUserRefreshTokenFetcherTest::MakeIssueTokenRequestSucceed() { 203 SendResponse(GetIssueTokenRequest(), 204 base::StringPrintf(kIssueTokenResponseFormat, 205 kAuthorizationCode)); 206 } 207 208 void SupervisedUserRefreshTokenFetcherTest::MakeRefreshTokenFetchSucceed() { 209 SendResponse(GetRefreshTokenRequest(), 210 base::StringPrintf(kGetRefreshTokenResponseFormat, 211 kSupervisedUserToken)); 212 } 213 214 void SupervisedUserRefreshTokenFetcherTest::Reset() { 215 token_fetcher_.reset(); 216 } 217 218 void SupervisedUserRefreshTokenFetcherTest::OnTokenFetched( 219 const GoogleServiceAuthError& error, 220 const std::string& token) { 221 error_ = error; 222 token_ = token; 223 } 224 225 // Tests -------------------------------------------------------- 226 227 TEST_F(SupervisedUserRefreshTokenFetcherTest, Success) { 228 StartFetching(); 229 MakeOAuth2TokenServiceRequestSucceed(); 230 MakeIssueTokenRequestSucceed(); 231 MakeRefreshTokenFetchSucceed(); 232 233 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 234 EXPECT_EQ(kSupervisedUserToken, token()); 235 } 236 237 TEST_F(SupervisedUserRefreshTokenFetcherTest, ExpiredAccessToken) { 238 StartFetching(); 239 MakeOAuth2TokenServiceRequestSucceed(); 240 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); 241 MakeOAuth2TokenServiceRequestSucceed(); 242 MakeIssueTokenRequestSucceed(); 243 MakeRefreshTokenFetchSucceed(); 244 245 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 246 EXPECT_EQ(kSupervisedUserToken, token()); 247 } 248 249 TEST_F(SupervisedUserRefreshTokenFetcherTest, ExpiredAccessTokenRetry) { 250 // If we get a 401 error for the second time, we should give up instead of 251 // retrying again. 252 StartFetching(); 253 MakeOAuth2TokenServiceRequestSucceed(); 254 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); 255 MakeOAuth2TokenServiceRequestSucceed(); 256 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); 257 258 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 259 EXPECT_EQ(net::ERR_FAILED, error().network_error()); 260 EXPECT_EQ(std::string(), token()); 261 } 262 263 TEST_F(SupervisedUserRefreshTokenFetcherTest, MalformedIssueTokenResponse) { 264 StartFetching(); 265 MakeOAuth2TokenServiceRequestSucceed(); 266 SendResponse(GetIssueTokenRequest(), "choke"); 267 268 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 269 EXPECT_EQ(net::ERR_INVALID_RESPONSE, error().network_error()); 270 EXPECT_EQ(std::string(), token()); 271 } 272 273 TEST_F(SupervisedUserRefreshTokenFetcherTest, FetchAccessTokenFailure) { 274 StartFetching(); 275 MakeOAuth2TokenServiceRequestFail( 276 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 277 278 EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error().state()); 279 EXPECT_EQ(std::string(), token()); 280 } 281 282 TEST_F(SupervisedUserRefreshTokenFetcherTest, IssueTokenNetworkError) { 283 StartFetching(); 284 MakeOAuth2TokenServiceRequestSucceed(); 285 SetNetworkError(GetIssueTokenRequest(), net::ERR_SSL_PROTOCOL_ERROR); 286 287 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 288 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, error().network_error()); 289 EXPECT_EQ(std::string(), token()); 290 } 291 292 TEST_F(SupervisedUserRefreshTokenFetcherTest, FetchRefreshTokenNetworkError) { 293 StartFetching(); 294 MakeOAuth2TokenServiceRequestSucceed(); 295 MakeIssueTokenRequestSucceed(); 296 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); 297 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 298 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); 299 300 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 301 EXPECT_EQ(net::ERR_FAILED, error().network_error()); 302 EXPECT_EQ(std::string(), token()); 303 } 304 305 TEST_F(SupervisedUserRefreshTokenFetcherTest, 306 FetchRefreshTokenTransientNetworkError) { 307 StartFetching(); 308 MakeOAuth2TokenServiceRequestSucceed(); 309 MakeIssueTokenRequestSucceed(); 310 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); 311 312 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 313 MakeRefreshTokenFetchSucceed(); 314 315 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 316 EXPECT_EQ(kSupervisedUserToken, token()); 317 } 318 319 TEST_F(SupervisedUserRefreshTokenFetcherTest, FetchRefreshTokenBadRequest) { 320 StartFetching(); 321 MakeOAuth2TokenServiceRequestSucceed(); 322 MakeIssueTokenRequestSucceed(); 323 SetHttpError(GetRefreshTokenRequest(), net::HTTP_BAD_REQUEST); 324 325 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 326 EXPECT_EQ(net::ERR_FAILED, error().network_error()); 327 EXPECT_EQ(std::string(), token()); 328 } 329 330 TEST_F(SupervisedUserRefreshTokenFetcherTest, CancelWhileFetchingAccessToken) { 331 StartFetching(); 332 Reset(); 333 334 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 335 EXPECT_EQ(std::string(), token()); 336 } 337 338 TEST_F(SupervisedUserRefreshTokenFetcherTest, CancelWhileCallingIssueToken) { 339 StartFetching(); 340 MakeOAuth2TokenServiceRequestSucceed(); 341 Reset(); 342 343 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 344 EXPECT_EQ(std::string(), token()); 345 } 346 347 TEST_F(SupervisedUserRefreshTokenFetcherTest, CancelWhileFetchingRefreshToken) { 348 StartFetching(); 349 MakeOAuth2TokenServiceRequestSucceed(); 350 MakeIssueTokenRequestSucceed(); 351 Reset(); 352 353 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 354 EXPECT_EQ(std::string(), token()); 355 } 356