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.
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"
27 const char kAccountId
[] = "account_id";
28 const char kDeviceId
[] = "device_id";
29 const char kDeviceName
[] = "Compy";
30 const char kSupervisedUserId
[] = "abcdef";
32 const char kAccessToken
[] = "accesstoken";
33 const char kAuthorizationCode
[] = "authorizationcode";
34 const char kSupervisedUserToken
[] = "supervisedusertoken";
35 const char kOAuth2RefreshToken
[] = "refreshtoken";
37 const char kIssueTokenResponseFormat
[] =
42 const char kGetRefreshTokenResponseFormat
[] =
44 " \"access_token\": \"<ignored>\","
45 " \"expires_in\": 12345,"
46 " \"refresh_token\": \"%s\""
49 // Utility methods --------------------------------------------------
51 // Slightly hacky way to extract a value from a URL-encoded POST request body.
52 bool GetValueForKey(const std::string
& encoded_string
,
53 const std::string
& key
,
55 GURL
url("http://example.com/?" + encoded_string
);
56 return net::GetValueForKeyInQuery(url
, key
, value
);
59 void SendResponse(net::TestURLFetcher
* url_fetcher
,
60 const std::string
& response
) {
61 url_fetcher
->set_status(
62 net::URLRequestStatus(net::URLRequestStatus::SUCCESS
, 0));
63 url_fetcher
->set_response_code(net::HTTP_OK
);
64 url_fetcher
->SetResponseString(response
);
65 url_fetcher
->delegate()->OnURLFetchComplete(url_fetcher
);
68 void SetNetworkError(net::TestURLFetcher
* url_fetcher
, int error
) {
69 url_fetcher
->set_status(
70 net::URLRequestStatus(net::URLRequestStatus::FAILED
, error
));
71 url_fetcher
->delegate()->OnURLFetchComplete(url_fetcher
);
74 void SetHttpError(net::TestURLFetcher
* url_fetcher
, int error
) {
75 url_fetcher
->set_status(net::URLRequestStatus());
76 url_fetcher
->set_response_code(error
);
77 url_fetcher
->delegate()->OnURLFetchComplete(url_fetcher
);
80 void VerifyTokenRequest(
81 std::vector
<FakeProfileOAuth2TokenService::PendingRequest
> requests
) {
82 ASSERT_EQ(1u, requests
.size());
83 EXPECT_EQ(1u, requests
[0].scopes
.size());
84 EXPECT_EQ(1u, requests
[0].scopes
.count(GaiaConstants::kOAuth1LoginScope
));
89 class SupervisedUserRefreshTokenFetcherTest
: public testing::Test
{
91 SupervisedUserRefreshTokenFetcherTest();
92 virtual ~SupervisedUserRefreshTokenFetcherTest() {}
96 void StartFetchingWithDeviceId(const std::string
& device_id
);
98 net::TestURLFetcher
* GetIssueTokenRequest();
99 net::TestURLFetcher
* GetRefreshTokenRequest();
101 void MakeOAuth2TokenServiceRequestSucceed();
102 void MakeOAuth2TokenServiceRequestFail(GoogleServiceAuthError::State error
);
103 void MakeIssueTokenRequestSucceed();
104 void MakeRefreshTokenFetchSucceed();
108 const GoogleServiceAuthError
& error() const { return error_
; }
109 const std::string
& token() const { return token_
; }
112 void OnTokenFetched(const GoogleServiceAuthError
& error
,
113 const std::string
& token
);
115 content::TestBrowserThreadBundle thread_bundle_
;
116 TestingProfile profile_
;
117 FakeProfileOAuth2TokenService oauth2_token_service_
;
118 net::TestURLFetcherFactory url_fetcher_factory_
;
119 scoped_ptr
<SupervisedUserRefreshTokenFetcher
> token_fetcher_
;
120 std::string device_id_
;
122 GoogleServiceAuthError error_
;
124 base::WeakPtrFactory
<SupervisedUserRefreshTokenFetcherTest
> weak_ptr_factory_
;
127 SupervisedUserRefreshTokenFetcherTest::SupervisedUserRefreshTokenFetcherTest()
128 : error_(GoogleServiceAuthError::NONE
),
129 weak_ptr_factory_(this) {}
131 void SupervisedUserRefreshTokenFetcherTest::StartFetching() {
132 StartFetchingWithDeviceId(std::string());
135 void SupervisedUserRefreshTokenFetcherTest::StartFetchingWithDeviceId(
136 const std::string
& device_id
) {
137 device_id_
= device_id
;
138 oauth2_token_service_
.IssueRefreshToken(kOAuth2RefreshToken
);
139 token_fetcher_
= SupervisedUserRefreshTokenFetcher::Create(
140 &oauth2_token_service_
,
143 profile_
.GetRequestContext()).Pass();
144 token_fetcher_
->Start(
148 &SupervisedUserRefreshTokenFetcherTest::OnTokenFetched
,
149 weak_ptr_factory_
.GetWeakPtr()));
153 SupervisedUserRefreshTokenFetcherTest::GetIssueTokenRequest() {
154 net::TestURLFetcher
* url_fetcher
= url_fetcher_factory_
.GetFetcherByID(1);
158 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_issue_token_url(),
159 url_fetcher
->GetOriginalURL());
160 std::string access_token
;
161 net::HttpRequestHeaders headers
;
162 url_fetcher
->GetExtraRequestHeaders(&headers
);
163 EXPECT_TRUE(headers
.GetHeader("Authorization", &access_token
));
164 EXPECT_EQ(std::string("Bearer ") + kAccessToken
, access_token
);
165 const std::string upload_data
= url_fetcher
->upload_data();
166 std::string supervised_user_id
;
167 EXPECT_TRUE(GetValueForKey(upload_data
, "profile_id", &supervised_user_id
));
168 EXPECT_EQ(kSupervisedUserId
, supervised_user_id
);
169 std::string device_name
;
170 EXPECT_TRUE(GetValueForKey(upload_data
, "device_name", &device_name
));
171 EXPECT_EQ(kDeviceName
, device_name
);
172 std::string device_id
;
173 EXPECT_EQ(!device_id_
.empty(),
174 GetValueForKey(upload_data
, "device_id", &device_id
));
175 EXPECT_EQ(device_id_
, device_id
);
180 SupervisedUserRefreshTokenFetcherTest::GetRefreshTokenRequest() {
181 net::TestURLFetcher
* url_fetcher
= url_fetcher_factory_
.GetFetcherByID(
182 gaia::GaiaOAuthClient::kUrlFetcherId
);
186 EXPECT_EQ(GaiaUrls::GetInstance()->oauth2_token_url(),
187 url_fetcher
->GetOriginalURL());
188 std::string auth_code
;
189 EXPECT_TRUE(GetValueForKey(url_fetcher
->upload_data(), "code", &auth_code
));
190 EXPECT_EQ(kAuthorizationCode
, auth_code
);
195 SupervisedUserRefreshTokenFetcherTest::MakeOAuth2TokenServiceRequestSucceed() {
196 std::vector
<FakeProfileOAuth2TokenService::PendingRequest
> requests
=
197 oauth2_token_service_
.GetPendingRequests();
198 VerifyTokenRequest(requests
);
199 base::Time expiration_date
= base::Time::Now() +
200 base::TimeDelta::FromHours(1);
201 oauth2_token_service_
.IssueTokenForScope(requests
[0].scopes
,
207 SupervisedUserRefreshTokenFetcherTest::MakeOAuth2TokenServiceRequestFail(
208 GoogleServiceAuthError::State error
) {
209 std::vector
<FakeProfileOAuth2TokenService::PendingRequest
> requests
=
210 oauth2_token_service_
.GetPendingRequests();
211 VerifyTokenRequest(requests
);
212 oauth2_token_service_
.IssueErrorForScope(requests
[0].scopes
,
213 GoogleServiceAuthError(error
));
216 void SupervisedUserRefreshTokenFetcherTest::MakeIssueTokenRequestSucceed() {
217 SendResponse(GetIssueTokenRequest(),
218 base::StringPrintf(kIssueTokenResponseFormat
,
219 kAuthorizationCode
));
222 void SupervisedUserRefreshTokenFetcherTest::MakeRefreshTokenFetchSucceed() {
223 SendResponse(GetRefreshTokenRequest(),
224 base::StringPrintf(kGetRefreshTokenResponseFormat
,
225 kSupervisedUserToken
));
228 void SupervisedUserRefreshTokenFetcherTest::Reset() {
229 token_fetcher_
.reset();
232 void SupervisedUserRefreshTokenFetcherTest::OnTokenFetched(
233 const GoogleServiceAuthError
& error
,
234 const std::string
& token
) {
239 // Tests --------------------------------------------------------
241 TEST_F(SupervisedUserRefreshTokenFetcherTest
, Success
) {
243 MakeOAuth2TokenServiceRequestSucceed();
244 MakeIssueTokenRequestSucceed();
245 MakeRefreshTokenFetchSucceed();
247 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
248 EXPECT_EQ(kSupervisedUserToken
, token());
251 TEST_F(SupervisedUserRefreshTokenFetcherTest
, Success_WithDeviceId
) {
252 StartFetchingWithDeviceId(kDeviceId
);
253 MakeOAuth2TokenServiceRequestSucceed();
254 MakeIssueTokenRequestSucceed();
255 MakeRefreshTokenFetchSucceed();
257 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
258 EXPECT_EQ(kSupervisedUserToken
, token());
261 TEST_F(SupervisedUserRefreshTokenFetcherTest
, ExpiredAccessToken
) {
263 MakeOAuth2TokenServiceRequestSucceed();
264 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED
);
265 MakeOAuth2TokenServiceRequestSucceed();
266 MakeIssueTokenRequestSucceed();
267 MakeRefreshTokenFetchSucceed();
269 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
270 EXPECT_EQ(kSupervisedUserToken
, token());
273 TEST_F(SupervisedUserRefreshTokenFetcherTest
, ExpiredAccessTokenRetry
) {
274 // If we get a 401 error for the second time, we should give up instead of
277 MakeOAuth2TokenServiceRequestSucceed();
278 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED
);
279 MakeOAuth2TokenServiceRequestSucceed();
280 SetHttpError(GetIssueTokenRequest(), net::HTTP_UNAUTHORIZED
);
282 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED
, error().state());
283 EXPECT_EQ(net::ERR_FAILED
, error().network_error());
284 EXPECT_EQ(std::string(), token());
287 TEST_F(SupervisedUserRefreshTokenFetcherTest
, MalformedIssueTokenResponse
) {
289 MakeOAuth2TokenServiceRequestSucceed();
290 SendResponse(GetIssueTokenRequest(), "choke");
292 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED
, error().state());
293 EXPECT_EQ(net::ERR_INVALID_RESPONSE
, error().network_error());
294 EXPECT_EQ(std::string(), token());
297 TEST_F(SupervisedUserRefreshTokenFetcherTest
, FetchAccessTokenFailure
) {
299 MakeOAuth2TokenServiceRequestFail(
300 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
);
302 EXPECT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
, error().state());
303 EXPECT_EQ(std::string(), token());
306 TEST_F(SupervisedUserRefreshTokenFetcherTest
, IssueTokenNetworkError
) {
308 MakeOAuth2TokenServiceRequestSucceed();
309 SetNetworkError(GetIssueTokenRequest(), net::ERR_SSL_PROTOCOL_ERROR
);
311 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED
, error().state());
312 EXPECT_EQ(net::ERR_SSL_PROTOCOL_ERROR
, error().network_error());
313 EXPECT_EQ(std::string(), token());
316 TEST_F(SupervisedUserRefreshTokenFetcherTest
, FetchRefreshTokenNetworkError
) {
318 MakeOAuth2TokenServiceRequestSucceed();
319 MakeIssueTokenRequestSucceed();
320 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED
);
321 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
322 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED
);
324 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED
, error().state());
325 EXPECT_EQ(net::ERR_FAILED
, error().network_error());
326 EXPECT_EQ(std::string(), token());
329 TEST_F(SupervisedUserRefreshTokenFetcherTest
,
330 FetchRefreshTokenTransientNetworkError
) {
332 MakeOAuth2TokenServiceRequestSucceed();
333 MakeIssueTokenRequestSucceed();
334 SetNetworkError(GetRefreshTokenRequest(), net::ERR_CONNECTION_REFUSED
);
336 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
337 MakeRefreshTokenFetchSucceed();
339 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
340 EXPECT_EQ(kSupervisedUserToken
, token());
343 TEST_F(SupervisedUserRefreshTokenFetcherTest
, FetchRefreshTokenBadRequest
) {
345 MakeOAuth2TokenServiceRequestSucceed();
346 MakeIssueTokenRequestSucceed();
347 SetHttpError(GetRefreshTokenRequest(), net::HTTP_BAD_REQUEST
);
349 EXPECT_EQ(GoogleServiceAuthError::CONNECTION_FAILED
, error().state());
350 EXPECT_EQ(net::ERR_FAILED
, error().network_error());
351 EXPECT_EQ(std::string(), token());
354 TEST_F(SupervisedUserRefreshTokenFetcherTest
, CancelWhileFetchingAccessToken
) {
358 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
359 EXPECT_EQ(std::string(), token());
362 TEST_F(SupervisedUserRefreshTokenFetcherTest
, CancelWhileCallingIssueToken
) {
364 MakeOAuth2TokenServiceRequestSucceed();
367 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
368 EXPECT_EQ(std::string(), token());
371 TEST_F(SupervisedUserRefreshTokenFetcherTest
, CancelWhileFetchingRefreshToken
) {
373 MakeOAuth2TokenServiceRequestSucceed();
374 MakeIssueTokenRequestSucceed();
377 EXPECT_EQ(GoogleServiceAuthError::NONE
, error().state());
378 EXPECT_EQ(std::string(), token());