Home | History | Annotate | Download | only in managed_mode
      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