supervised_user_refresh_token_fetcher_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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 25namespace { 26 27const char kAccountId[] = "account_id"; 28const char kDeviceName[] = "Compy"; 29const char kSupervisedUserId[] = "abcdef"; 30 31const char kAccessToken[] = "accesstoken"; 32const char kAuthorizationCode[] = "authorizationcode"; 33const char kSupervisedUserToken[] = "supervisedusertoken"; 34const char kOAuth2RefreshToken[] = "refreshtoken"; 35 36const char kIssueTokenResponseFormat[] = 37 "{" 38 " \"code\": \"%s\"" 39 "}"; 40 41const 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. 51bool 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 58void 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 67void 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 73void 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 79void 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 88class 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 124SupervisedUserRefreshTokenFetcherTest::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 132void 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 142net::TestURLFetcher* 143SupervisedUserRefreshTokenFetcherTest::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 165net::TestURLFetcher* 166SupervisedUserRefreshTokenFetcherTest::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 180void 181SupervisedUserRefreshTokenFetcherTest::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 192void 193SupervisedUserRefreshTokenFetcherTest::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 202void SupervisedUserRefreshTokenFetcherTest::MakeIssueTokenRequestSucceed() { 203 SendResponse(GetIssueTokenRequest(), 204 base::StringPrintf(kIssueTokenResponseFormat, 205 kAuthorizationCode)); 206} 207 208void SupervisedUserRefreshTokenFetcherTest::MakeRefreshTokenFetchSucceed() { 209 SendResponse(GetRefreshTokenRequest(), 210 base::StringPrintf(kGetRefreshTokenResponseFormat, 211 kSupervisedUserToken)); 212} 213 214void SupervisedUserRefreshTokenFetcherTest::Reset() { 215 token_fetcher_.reset(); 216} 217 218void SupervisedUserRefreshTokenFetcherTest::OnTokenFetched( 219 const GoogleServiceAuthError& error, 220 const std::string& token) { 221 error_ = error; 222 token_ = token; 223} 224 225// Tests -------------------------------------------------------- 226 227TEST_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 237TEST_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 249TEST_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 263TEST_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 273TEST_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 282TEST_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 292TEST_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 305TEST_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 319TEST_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 330TEST_F(SupervisedUserRefreshTokenFetcherTest, CancelWhileFetchingAccessToken) { 331 StartFetching(); 332 Reset(); 333 334 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 335 EXPECT_EQ(std::string(), token()); 336} 337 338TEST_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 347TEST_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