1 // Copyright 2013 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/managed_mode/managed_user_refresh_token_fetcher.h" 9 #include "chrome/browser/signin/oauth2_token_service.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_oauth_client.h" 13 #include "google_apis/gaia/gaia_urls.h" 14 #include "google_apis/gaia/google_service_auth_error.h" 15 #include "net/base/net_errors.h" 16 #include "net/base/url_util.h" 17 #include "net/http/http_request_headers.h" 18 #include "net/http/http_status_code.h" 19 #include "net/url_request/test_url_fetcher_factory.h" 20 #include "net/url_request/url_fetcher_delegate.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace { 24 25 const char kManagedUserId[] = "abcdef"; 26 const char kDeviceName[] = "Compy"; 27 28 const char kAccessToken[] = "accesstoken"; 29 const char kAuthorizationCode[] = "authorizationcode"; 30 const char kManagedUserToken[] = "managedusertoken"; 31 32 const char kIssueTokenResponseFormat[] = 33 "{" 34 " \"code\": \"%s\"" 35 "}"; 36 37 const char kGetRefreshTokenResponseFormat[] = 38 "{" 39 " \"access_token\": \"<ignored>\"," 40 " \"expires_in\": 12345," 41 " \"refresh_token\": \"%s\"" 42 "}"; 43 44 // MockOAuth2TokenService --------------------------------------------- 45 46 class MockOAuth2TokenService : public OAuth2TokenService { 47 public: 48 class Request : public OAuth2TokenService::Request { 49 public: 50 Request(const OAuth2TokenService::ScopeSet& scopes, 51 OAuth2TokenService::Consumer* consumer, 52 MockOAuth2TokenService* owner); 53 virtual ~Request(); 54 55 void Succeed(); 56 void Fail(GoogleServiceAuthError::State error); 57 58 const OAuth2TokenService::ScopeSet& scopes() const { return scopes_; } 59 60 private: 61 OAuth2TokenService::ScopeSet scopes_; 62 63 OAuth2TokenService::Consumer* consumer_; 64 65 MockOAuth2TokenService* owner_; 66 }; 67 68 MockOAuth2TokenService(); 69 virtual ~MockOAuth2TokenService(); 70 71 Request* request() const { return request_; } 72 73 void ClearRequest(Request* request); 74 75 private: 76 // OAuth2TokenService overrides: 77 virtual scoped_ptr<OAuth2TokenService::Request> StartRequest( 78 const OAuth2TokenService::ScopeSet& scopes, 79 OAuth2TokenService::Consumer* consumer) OVERRIDE; 80 virtual std::string GetRefreshToken() OVERRIDE; 81 virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE { 82 return NULL; 83 } 84 85 Request* request_; 86 87 DISALLOW_COPY_AND_ASSIGN(MockOAuth2TokenService); 88 }; 89 90 MockOAuth2TokenService::Request::Request( 91 const OAuth2TokenService::ScopeSet& scopes, 92 OAuth2TokenService::Consumer* consumer, 93 MockOAuth2TokenService* owner) 94 : scopes_(scopes), 95 consumer_(consumer), 96 owner_(owner) {} 97 98 MockOAuth2TokenService::Request::~Request() { 99 owner_->ClearRequest(this); 100 } 101 102 void MockOAuth2TokenService::Request::Succeed() { 103 base::Time expiration_date = base::Time::Now() + 104 base::TimeDelta::FromHours(1); 105 consumer_->OnGetTokenSuccess(this, kAccessToken, expiration_date); 106 } 107 108 void MockOAuth2TokenService::Request::Fail( 109 GoogleServiceAuthError::State error) { 110 consumer_->OnGetTokenFailure(this, GoogleServiceAuthError(error)); 111 } 112 113 MockOAuth2TokenService::MockOAuth2TokenService() : request_(NULL) {} 114 115 MockOAuth2TokenService::~MockOAuth2TokenService() { 116 EXPECT_FALSE(request_); 117 } 118 119 void MockOAuth2TokenService::ClearRequest( 120 MockOAuth2TokenService::Request* request) { 121 if (request_ == request) 122 request_ = NULL; 123 } 124 125 scoped_ptr<OAuth2TokenService::Request> MockOAuth2TokenService::StartRequest( 126 const OAuth2TokenService::ScopeSet& scopes, 127 OAuth2TokenService::Consumer* consumer) { 128 scoped_ptr<Request> request(new Request(scopes, consumer, this)); 129 request_ = request.get(); 130 return request.PassAs<OAuth2TokenService::Request>(); 131 } 132 133 std::string MockOAuth2TokenService::GetRefreshToken() { 134 NOTREACHED(); 135 return std::string(); 136 } 137 138 // Utility methods -------------------------------------------------- 139 140 // Slightly hacky way to extract a value from a URL-encoded POST request body. 141 bool GetValueForKey(const std::string& encoded_string, 142 const std::string& key, 143 std::string* value) { 144 GURL url("http://example.com/?" + encoded_string); 145 return net::GetValueForKeyInQuery(url, key, value); 146 } 147 148 void SendResponse(net::TestURLFetcher* url_fetcher, 149 const std::string& response) { 150 url_fetcher->set_status( 151 net::URLRequestStatus(net::URLRequestStatus::SUCCESS, 0)); 152 url_fetcher->set_response_code(net::HTTP_OK); 153 url_fetcher->SetResponseString(response); 154 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 155 } 156 157 void SetNetworkError(net::TestURLFetcher* url_fetcher, int error) { 158 url_fetcher->set_status( 159 net::URLRequestStatus(net::URLRequestStatus::FAILED, error)); 160 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 161 } 162 163 void SetHttpError(net::TestURLFetcher* url_fetcher, int error) { 164 url_fetcher->set_status(net::URLRequestStatus()); 165 url_fetcher->set_response_code(error); 166 url_fetcher->delegate()->OnURLFetchComplete(url_fetcher); 167 } 168 169 } // namespace 170 171 class ManagedUserRefreshTokenFetcherTest : public testing::Test { 172 public: 173 ManagedUserRefreshTokenFetcherTest(); 174 virtual ~ManagedUserRefreshTokenFetcherTest() {} 175 176 protected: 177 void StartFetching(); 178 179 MockOAuth2TokenService::Request* GetOAuth2TokenServiceRequest(); 180 net::TestURLFetcher* GetIssueTokenRequest(); 181 net::TestURLFetcher* GetRefreshTokenRequest(); 182 183 void MakeIssueTokenRequestSucceed(); 184 void MakeRefreshTokenFetchSucceed(); 185 186 void Reset(); 187 188 const GoogleServiceAuthError& error() const { return error_; } 189 const std::string& token() const { return token_; } 190 191 private: 192 void OnTokenFetched(const GoogleServiceAuthError& error, 193 const std::string& token); 194 195 content::TestBrowserThreadBundle thread_bundle_; 196 TestingProfile profile_; 197 MockOAuth2TokenService oauth2_token_service_; 198 net::TestURLFetcherFactory url_fetcher_factory_; 199 scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher_; 200 201 GoogleServiceAuthError error_; 202 std::string token_; 203 base::WeakPtrFactory<ManagedUserRefreshTokenFetcherTest> weak_ptr_factory_; 204 }; 205 206 ManagedUserRefreshTokenFetcherTest::ManagedUserRefreshTokenFetcherTest() 207 : token_fetcher_( 208 ManagedUserRefreshTokenFetcher::Create(&oauth2_token_service_, 209 profile_.GetRequestContext())), 210 error_(GoogleServiceAuthError::NONE), 211 weak_ptr_factory_(this) {} 212 213 void ManagedUserRefreshTokenFetcherTest::StartFetching() { 214 token_fetcher_->Start(kManagedUserId, kDeviceName, 215 base::Bind( 216 &ManagedUserRefreshTokenFetcherTest::OnTokenFetched, 217 weak_ptr_factory_.GetWeakPtr())); 218 } 219 220 MockOAuth2TokenService::Request* 221 ManagedUserRefreshTokenFetcherTest::GetOAuth2TokenServiceRequest() { 222 MockOAuth2TokenService::Request* request = oauth2_token_service_.request(); 223 224 OAuth2TokenService::ScopeSet scopes = request->scopes(); 225 EXPECT_EQ(1u, scopes.size()); 226 EXPECT_EQ(1u, scopes.count(GaiaUrls::GetInstance()->oauth1_login_scope())); 227 return request; 228 } 229 230 net::TestURLFetcher* 231 ManagedUserRefreshTokenFetcherTest::GetIssueTokenRequest() { 232 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID(1); 233 if (!url_fetcher) 234 return NULL; 235 236 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_issue_token_url(), 237 url_fetcher->GetOriginalURL().spec()); 238 std::string access_token; 239 net::HttpRequestHeaders headers; 240 url_fetcher->GetExtraRequestHeaders(&headers); 241 EXPECT_TRUE(headers.GetHeader("Authorization", &access_token)); 242 EXPECT_EQ(std::string("Bearer ") + kAccessToken, access_token); 243 const std::string upload_data = url_fetcher->upload_data(); 244 std::string managed_user_id; 245 EXPECT_TRUE(GetValueForKey(upload_data, "profile_id", &managed_user_id)); 246 EXPECT_EQ(kManagedUserId, managed_user_id); 247 std::string device_name; 248 EXPECT_TRUE(GetValueForKey(upload_data, "device_name", &device_name)); 249 EXPECT_EQ(kDeviceName, device_name); 250 return url_fetcher; 251 } 252 253 net::TestURLFetcher* 254 ManagedUserRefreshTokenFetcherTest::GetRefreshTokenRequest() { 255 net::TestURLFetcher* url_fetcher = url_fetcher_factory_.GetFetcherByID( 256 gaia::GaiaOAuthClient::kUrlFetcherId); 257 if (!url_fetcher) 258 return NULL; 259 260 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_token_url(), 261 url_fetcher->GetOriginalURL().spec()); 262 std::string auth_code; 263 EXPECT_TRUE(GetValueForKey(url_fetcher->upload_data(), "code", &auth_code)); 264 EXPECT_EQ(kAuthorizationCode, auth_code); 265 return url_fetcher; 266 } 267 268 void ManagedUserRefreshTokenFetcherTest::MakeIssueTokenRequestSucceed() { 269 SendResponse(GetIssueTokenRequest(), 270 base::StringPrintf(kIssueTokenResponseFormat, 271 kAuthorizationCode)); 272 } 273 274 void ManagedUserRefreshTokenFetcherTest::MakeRefreshTokenFetchSucceed() { 275 SendResponse(GetRefreshTokenRequest(), 276 base::StringPrintf(kGetRefreshTokenResponseFormat, 277 kManagedUserToken)); 278 } 279 280 void ManagedUserRefreshTokenFetcherTest::Reset() { 281 token_fetcher_.reset(); 282 } 283 284 void ManagedUserRefreshTokenFetcherTest::OnTokenFetched( 285 const GoogleServiceAuthError& error, 286 const std::string& token) { 287 error_ = error; 288 token_ = token; 289 } 290 291 // Tests -------------------------------------------------------- 292 293 TEST_F(ManagedUserRefreshTokenFetcherTest, Success) { 294 StartFetching(); 295 GetOAuth2TokenServiceRequest()->Succeed(); 296 MakeIssueTokenRequestSucceed(); 297 MakeRefreshTokenFetchSucceed(); 298 299 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 300 EXPECT_EQ(kManagedUserToken, token()); 301 } 302 303 TEST_F(ManagedUserRefreshTokenFetcherTest, ExpiredAccessToken) { 304 StartFetching(); 305 GetOAuth2TokenServiceRequest()->Succeed(); 306 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); 307 GetOAuth2TokenServiceRequest()->Succeed(); 308 MakeIssueTokenRequestSucceed(); 309 MakeRefreshTokenFetchSucceed(); 310 311 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 312 EXPECT_EQ(kManagedUserToken, token()); 313 } 314 315 TEST_F(ManagedUserRefreshTokenFetcherTest, ExpiredAccessTokenRetry) { 316 // If we get a 401 error for the second time, we should give up instead of 317 // retrying again. 318 StartFetching(); 319 GetOAuth2TokenServiceRequest()->Succeed(); 320 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); 321 GetOAuth2TokenServiceRequest()->Succeed(); 322 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED); 323 324 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 325 EXPECT_EQ(net::ERR_FAILED, error().network_error()); 326 EXPECT_EQ(std::string(), token()); 327 } 328 329 TEST_F(ManagedUserRefreshTokenFetcherTest, MalformedIssueTokenResponse) { 330 StartFetching(); 331 GetOAuth2TokenServiceRequest()->Succeed(); 332 SendResponse(GetIssueTokenRequest(), "choke"); 333 334 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 335 EXPECT_EQ(net::ERR_INVALID_RESPONSE, error().network_error()); 336 EXPECT_EQ(std::string(), token()); 337 } 338 339 TEST_F(ManagedUserRefreshTokenFetcherTest, FetchAccessTokenFailure) { 340 StartFetching(); 341 GetOAuth2TokenServiceRequest()->Fail( 342 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); 343 344 EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, error().state()); 345 EXPECT_EQ(std::string(), token()); 346 } 347 348 TEST_F(ManagedUserRefreshTokenFetcherTest, IssueTokenNetworkError) { 349 StartFetching(); 350 GetOAuth2TokenServiceRequest()->Succeed(); 351 SetNetworkError(GetIssueTokenRequest(), net::ERR_SSL_PROTOCOL_ERROR); 352 353 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 354 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR, error().network_error()); 355 EXPECT_EQ(std::string(), token()); 356 } 357 358 TEST_F(ManagedUserRefreshTokenFetcherTest, FetchRefreshTokenNetworkError) { 359 StartFetching(); 360 GetOAuth2TokenServiceRequest()->Succeed(); 361 MakeIssueTokenRequestSucceed(); 362 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); 363 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 364 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); 365 366 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 367 EXPECT_EQ(net::ERR_FAILED, error().network_error()); 368 EXPECT_EQ(std::string(), token()); 369 } 370 371 TEST_F(ManagedUserRefreshTokenFetcherTest, 372 FetchRefreshTokenTransientNetworkError) { 373 StartFetching(); 374 GetOAuth2TokenServiceRequest()->Succeed(); 375 MakeIssueTokenRequestSucceed(); 376 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED); 377 378 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 379 MakeRefreshTokenFetchSucceed(); 380 381 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 382 EXPECT_EQ(kManagedUserToken, token()); 383 } 384 385 TEST_F(ManagedUserRefreshTokenFetcherTest, FetchRefreshTokenBadRequest) { 386 StartFetching(); 387 GetOAuth2TokenServiceRequest()->Succeed(); 388 MakeIssueTokenRequestSucceed(); 389 SetHttpError(GetRefreshTokenRequest(), net::HTTP_BAD_REQUEST); 390 391 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED, error().state()); 392 EXPECT_EQ(net::ERR_FAILED, error().network_error()); 393 EXPECT_EQ(std::string(), token()); 394 } 395 396 TEST_F(ManagedUserRefreshTokenFetcherTest, CancelWhileFetchingAccessToken) { 397 StartFetching(); 398 Reset(); 399 400 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 401 EXPECT_EQ(std::string(), token()); 402 } 403 404 TEST_F(ManagedUserRefreshTokenFetcherTest, CancelWhileCallingIssueToken) { 405 StartFetching(); 406 GetOAuth2TokenServiceRequest()->Succeed(); 407 Reset(); 408 409 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 410 EXPECT_EQ(std::string(), token()); 411 } 412 413 TEST_F(ManagedUserRefreshTokenFetcherTest, CancelWhileFetchingRefreshToken) { 414 StartFetching(); 415 GetOAuth2TokenServiceRequest()->Succeed(); 416 MakeIssueTokenRequestSucceed(); 417 Reset(); 418 419 EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); 420 EXPECT_EQ(std::string(), token()); 421 } 422