oauth2_access_token_fetcher.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/oauth2_access_token_consumer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OAuth2AccessTokenFetcherTest;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Time;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLFetcher;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLRequestContextGetter;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class URLRequestStatus;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Abstracts the details to get OAuth2 access token token from
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OAuth2 refresh token.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See "Using the Refresh Token" section in:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/apis/accounts/docs/OAuth2WebServer.html
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class should be used on a single thread, but it can be whichever thread
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that you like.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Also, do not reuse the same instance. Once Start() is called, the instance
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should not be reused.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Usage:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Create an instance with a consumer.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Call Start()
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * The consumer passed in the constructor will be called on the same
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   thread Start was called with the results.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class can handle one request at a time. To parallelize requests,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// create multiple instances.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OAuth2AccessTokenFetcher : public net::URLFetcherDelegate {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OAuth2AccessTokenFetcher(OAuth2AccessTokenConsumer* consumer,
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           net::URLRequestContextGetter* getter);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~OAuth2AccessTokenFetcher();
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts the flow with the given parameters.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |scopes| can be empty. If it is empty then the access token will have the
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same scope as the refresh token. If not empty, then access token will have
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the scopes specified. In this case, the access token will successfully be
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generated only if refresh token has login scope of a list of scopes that is
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a super-set of the specified scopes.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Start(const std::string& client_id,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& client_secret,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& refresh_token,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::vector<std::string>& scopes);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelRequest();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implementation of net::URLFetcherDelegate
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    INITIAL,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GET_ACCESS_TOKEN_STARTED,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GET_ACCESS_TOKEN_DONE,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ERROR_STATE,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper methods for the flow.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartGetAccessToken();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EndGetAccessToken(const net::URLFetcher* source);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper mehtods for reporting back results.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetTokenSuccess(const std::string& access_token,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const base::Time& expiration_time);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnGetTokenFailure(const GoogleServiceAuthError& error);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Other helpers.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static GURL MakeGetAccessTokenUrl();
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static std::string MakeGetAccessTokenBody(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& client_id,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& client_secret,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& refresh_token,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::vector<std::string>& scopes);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool ParseGetAccessTokenResponse(const net::URLFetcher* source,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          std::string* access_token,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int* expires_in);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // State that is set during construction.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OAuth2AccessTokenConsumer* const consumer_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::URLRequestContextGetter* const getter_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  State state_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // While a fetch is in progress.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<net::URLFetcher> fetcher_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string client_id_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string client_secret_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string refresh_token_;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> scopes_;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class OAuth2AccessTokenFetcherTest;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherTest,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ParseGetAccessTokenResponse);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherTest,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           MakeGetAccessTokenBody);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenFetcher);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_H_
119