Commit 8273a85b authored by courage@chromium.org's avatar courage@chromium.org

revoke unused OAuth2 tokens on signout and re-signin

A number of users have been reporting problems with the identity API. Gaia investigations reveal that these users have overflowed a limit on the number of login tokens they can have for Chrome. Revoking tokens we don't need any longer should mitigate the problem. 

This is identical to https://codereview.chromium.org/13249007/ but with a corrected base url.

BUG=224462

Review URL: https://chromiumcodereview.appspot.com/13599003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@192491 0039d316-1c4b-4281-b951-d872f2087c98
parent 536445df
...@@ -328,6 +328,7 @@ bool SigninManager::PrepareForSignin(SigninType type, ...@@ -328,6 +328,7 @@ bool SigninManager::PrepareForSignin(SigninType type,
// need to try again, but take care to leave state around tracking that the // need to try again, but take care to leave state around tracking that the
// user has successfully signed in once before with this username, so that on // user has successfully signed in once before with this username, so that on
// restart we don't think sync setup has never completed. // restart we don't think sync setup has never completed.
RevokeOAuthLoginToken();
ClearTransientSigninData(); ClearTransientSigninData();
type_ = type; type_ = type;
possibly_invalid_username_.assign(username); possibly_invalid_username_.assign(username);
...@@ -558,10 +559,27 @@ void SigninManager::SignOut() { ...@@ -558,10 +559,27 @@ void SigninManager::SignOut() {
chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
content::Source<Profile>(profile_), content::Source<Profile>(profile_),
content::Details<const GoogleServiceSignoutDetails>(&details)); content::Details<const GoogleServiceSignoutDetails>(&details));
RevokeOAuthLoginToken();
token_service->ResetCredentialsInMemory(); token_service->ResetCredentialsInMemory();
token_service->EraseTokensFromDB(); token_service->EraseTokensFromDB();
} }
void SigninManager::RevokeOAuthLoginToken() {
TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
if (token_service->HasOAuthLoginToken()) {
revoke_token_fetcher_.reset(
new GaiaAuthFetcher(this,
GaiaConstants::kChromeSource,
profile_->GetRequestContext()));
revoke_token_fetcher_->StartRevokeOAuth2Token(
token_service->GetOAuth2LoginRefreshToken());
}
}
void SigninManager::OnOAuth2RevokeTokenCompleted() {
revoke_token_fetcher_.reset(NULL);
}
bool SigninManager::AuthInProgress() const { bool SigninManager::AuthInProgress() const {
return !possibly_invalid_username_.empty(); return !possibly_invalid_username_.empty();
} }
......
...@@ -185,6 +185,7 @@ class SigninManager : public GaiaAuthConsumer, ...@@ -185,6 +185,7 @@ class SigninManager : public GaiaAuthConsumer,
virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) OVERRIDE; virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) OVERRIDE;
virtual void OnClientOAuthFailure( virtual void OnClientOAuthFailure(
const GoogleServiceAuthError& error) OVERRIDE; const GoogleServiceAuthError& error) OVERRIDE;
virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE;
virtual void OnGetUserInfoSuccess(const UserInfoMap& data) OVERRIDE; virtual void OnGetUserInfoSuccess(const UserInfoMap& data) OVERRIDE;
virtual void OnGetUserInfoFailure( virtual void OnGetUserInfoFailure(
const GoogleServiceAuthError& error) OVERRIDE; const GoogleServiceAuthError& error) OVERRIDE;
...@@ -282,6 +283,10 @@ class SigninManager : public GaiaAuthConsumer, ...@@ -282,6 +283,10 @@ class SigninManager : public GaiaAuthConsumer,
void HandleAuthError(const GoogleServiceAuthError& error, void HandleAuthError(const GoogleServiceAuthError& error,
bool clear_transient_data); bool clear_transient_data);
// Called to tell GAIA that we will no longer be using the current refresh
// token.
void RevokeOAuthLoginToken();
#if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS) #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS)
// Callback invoked once policy registration is complete. If registration // Callback invoked once policy registration is complete. If registration
// fails, |client| will be null. // fails, |client| will be null.
...@@ -340,6 +345,9 @@ class SigninManager : public GaiaAuthConsumer, ...@@ -340,6 +345,9 @@ class SigninManager : public GaiaAuthConsumer,
// UbertokenFetcher to login to user to the web property. // UbertokenFetcher to login to user to the web property.
scoped_ptr<UbertokenFetcher> ubertoken_fetcher_; scoped_ptr<UbertokenFetcher> ubertoken_fetcher_;
// OAuth revocation fetcher for sign outs.
scoped_ptr<GaiaAuthFetcher> revoke_token_fetcher_;
// Helper object to listen for changes to signin preferences stored in non- // Helper object to listen for changes to signin preferences stored in non-
// profile-specific local prefs (like kGoogleServicesUsernamePattern). // profile-specific local prefs (like kGoogleServicesUsernamePattern).
PrefChangeRegistrar local_state_pref_registrar_; PrefChangeRegistrar local_state_pref_registrar_;
......
...@@ -72,6 +72,8 @@ class GaiaAuthConsumer { ...@@ -72,6 +72,8 @@ class GaiaAuthConsumer {
virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) {} virtual void OnClientOAuthSuccess(const ClientOAuthResult& result) {}
virtual void OnClientOAuthFailure(const GoogleServiceAuthError& error) {} virtual void OnClientOAuthFailure(const GoogleServiceAuthError& error) {}
virtual void OnOAuth2RevokeTokenCompleted() {}
virtual void OnGetUserInfoSuccess(const UserInfoMap& data) {} virtual void OnGetUserInfoSuccess(const UserInfoMap& data) {}
virtual void OnGetUserInfoFailure(const GoogleServiceAuthError& error) {} virtual void OnGetUserInfoFailure(const GoogleServiceAuthError& error) {}
......
...@@ -91,6 +91,9 @@ const char GaiaAuthFetcher::kOAuth2CodeToTokenPairBodyFormat[] = ...@@ -91,6 +91,9 @@ const char GaiaAuthFetcher::kOAuth2CodeToTokenPairBodyFormat[] =
"client_secret=%s&" "client_secret=%s&"
"code=%s"; "code=%s";
// static // static
const char GaiaAuthFetcher::kOAuth2RevokeTokenBodyFormat[] =
"token=%s";
// static
const char GaiaAuthFetcher::kGetUserInfoFormat[] = const char GaiaAuthFetcher::kGetUserInfoFormat[] =
"LSID=%s"; "LSID=%s";
// static // static
...@@ -180,6 +183,7 @@ GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer, ...@@ -180,6 +183,7 @@ GaiaAuthFetcher::GaiaAuthFetcher(GaiaAuthConsumer* consumer,
client_login_gurl_(GaiaUrls::GetInstance()->client_login_url()), client_login_gurl_(GaiaUrls::GetInstance()->client_login_url()),
issue_auth_token_gurl_(GaiaUrls::GetInstance()->issue_auth_token_url()), issue_auth_token_gurl_(GaiaUrls::GetInstance()->issue_auth_token_url()),
oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()), oauth2_token_gurl_(GaiaUrls::GetInstance()->oauth2_token_url()),
oauth2_revoke_gurl_(GaiaUrls::GetInstance()->oauth2_revoke_url()),
get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()), get_user_info_gurl_(GaiaUrls::GetInstance()->get_user_info_url()),
merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()), merge_session_gurl_(GaiaUrls::GetInstance()->merge_session_url()),
uberauth_token_gurl_(base::StringPrintf(kUberAuthTokenURLFormat, uberauth_token_gurl_(base::StringPrintf(kUberAuthTokenURLFormat,
...@@ -328,6 +332,12 @@ std::string GaiaAuthFetcher::MakeGetTokenPairBody( ...@@ -328,6 +332,12 @@ std::string GaiaAuthFetcher::MakeGetTokenPairBody(
encoded_auth_code.c_str()); encoded_auth_code.c_str());
} }
// static
std::string GaiaAuthFetcher::MakeRevokeTokenBody(
const std::string& auth_token) {
return base::StringPrintf(kOAuth2RevokeTokenBodyFormat, auth_token.c_str());
}
// static // static
std::string GaiaAuthFetcher::MakeGetUserInfoBody(const std::string& lsid) { std::string GaiaAuthFetcher::MakeGetUserInfoBody(const std::string& lsid) {
std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true); std::string encoded_lsid = net::EscapeUrlEncodedData(lsid, true);
...@@ -652,6 +662,21 @@ void GaiaAuthFetcher::StartLsoForOAuthLoginTokenExchange( ...@@ -652,6 +662,21 @@ void GaiaAuthFetcher::StartLsoForOAuthLoginTokenExchange(
fetcher_->Start(); fetcher_->Start();
} }
void GaiaAuthFetcher::StartRevokeOAuth2Token(const std::string& auth_token) {
DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
DVLOG(1) << "Starting OAuth2 token revocation";
request_body_ = MakeRevokeTokenBody(auth_token);
fetcher_.reset(CreateGaiaFetcher(getter_,
request_body_,
"",
oauth2_revoke_gurl_,
kLoadFlagsIgnoreCookies,
this));
fetch_pending_ = true;
fetcher_->Start();
}
void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange( void GaiaAuthFetcher::StartCookieForOAuthLoginTokenExchange(
const std::string& session_index) { const std::string& session_index) {
DCHECK(!fetch_pending_) << "Tried to fetch two things at once!"; DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";
...@@ -991,6 +1016,13 @@ void GaiaAuthFetcher::OnOAuth2TokenPairFetched( ...@@ -991,6 +1016,13 @@ void GaiaAuthFetcher::OnOAuth2TokenPairFetched(
} }
} }
void GaiaAuthFetcher::OnOAuth2RevokeTokenFetched(
const std::string& data,
const net::URLRequestStatus& status,
int response_code) {
consumer_->OnOAuth2RevokeTokenCompleted();
}
void GaiaAuthFetcher::OnGetUserInfoFetched( void GaiaAuthFetcher::OnGetUserInfoFetched(
const std::string& data, const std::string& data,
const net::URLRequestStatus& status, const net::URLRequestStatus& status,
...@@ -1119,6 +1151,8 @@ void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) { ...@@ -1119,6 +1151,8 @@ void GaiaAuthFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
OnClientOAuthFetched(data, status, response_code); OnClientOAuthFetched(data, status, response_code);
} else if (url == oauth_login_gurl_) { } else if (url == oauth_login_gurl_) {
OnOAuthLoginFetched(data, status, response_code); OnOAuthLoginFetched(data, status, response_code);
} else if (url == oauth2_revoke_gurl_) {
OnOAuth2RevokeTokenFetched(data, status, response_code);
} else { } else {
NOTREACHED(); NOTREACHED();
} }
......
...@@ -100,6 +100,12 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate { ...@@ -100,6 +100,12 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
// called on the consumer on the original thread. // called on the consumer on the original thread.
void StartLsoForOAuthLoginTokenExchange(const std::string& auth_token); void StartLsoForOAuthLoginTokenExchange(const std::string& auth_token);
// Start a request to revoke |auth_token|.
//
// Either OnRevokeOAuth2TokenSuccess or OnRevokeOAuth2TokenSuccess will be
// called on the consumer on the original thread.
void StartRevokeOAuth2Token(const std::string& auth_token);
// Start a request to exchange the cookies of a signed-in user session // Start a request to exchange the cookies of a signed-in user session
// for an OAuthLogin-scoped oauth2 token. In the case of a session with // for an OAuthLogin-scoped oauth2 token. In the case of a session with
// multiple accounts signed in, |session_index| indicate the which of accounts // multiple accounts signed in, |session_index| indicate the which of accounts
...@@ -216,6 +222,8 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate { ...@@ -216,6 +222,8 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
static const char kClientLoginToOAuth2BodyFormat[]; static const char kClientLoginToOAuth2BodyFormat[];
// The format of the POST body to get OAuth2 token pair from auth code. // The format of the POST body to get OAuth2 token pair from auth code.
static const char kOAuth2CodeToTokenPairBodyFormat[]; static const char kOAuth2CodeToTokenPairBodyFormat[];
// The format of the POST body to revoke an OAuth2 token.
static const char kOAuth2RevokeTokenBodyFormat[];
// The format of the POST body for GetUserInfo. // The format of the POST body for GetUserInfo.
static const char kGetUserInfoFormat[]; static const char kGetUserInfoFormat[];
// The format of the POST body for MergeSession. // The format of the POST body for MergeSession.
...@@ -273,6 +281,10 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate { ...@@ -273,6 +281,10 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
const net::URLRequestStatus& status, const net::URLRequestStatus& status,
int response_code); int response_code);
void OnOAuth2RevokeTokenFetched(const std::string& data,
const net::URLRequestStatus& status,
int response_code);
void OnGetUserInfoFetched(const std::string& data, void OnGetUserInfoFetched(const std::string& data,
const net::URLRequestStatus& status, const net::URLRequestStatus& status,
int response_code); int response_code);
...@@ -338,6 +350,8 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate { ...@@ -338,6 +350,8 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
static std::string MakeGetAuthCodeBody(); static std::string MakeGetAuthCodeBody();
// Given auth code, create body to get OAuth2 token pair. // Given auth code, create body to get OAuth2 token pair.
static std::string MakeGetTokenPairBody(const std::string& auth_code); static std::string MakeGetTokenPairBody(const std::string& auth_code);
// Given an OAuth2 token, create body to revoke the token.
std::string MakeRevokeTokenBody(const std::string& auth_token);
// Supply the lsid returned from ClientLogin in order to fetch // Supply the lsid returned from ClientLogin in order to fetch
// user information. // user information.
static std::string MakeGetUserInfoBody(const std::string& lsid); static std::string MakeGetUserInfoBody(const std::string& lsid);
...@@ -392,6 +406,7 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate { ...@@ -392,6 +406,7 @@ class GaiaAuthFetcher : public net::URLFetcherDelegate {
const GURL client_login_gurl_; const GURL client_login_gurl_;
const GURL issue_auth_token_gurl_; const GURL issue_auth_token_gurl_;
const GURL oauth2_token_gurl_; const GURL oauth2_token_gurl_;
const GURL oauth2_revoke_gurl_;
const GURL get_user_info_gurl_; const GURL get_user_info_gurl_;
const GURL merge_session_gurl_; const GURL merge_session_gurl_;
const GURL uberauth_token_gurl_; const GURL uberauth_token_gurl_;
......
...@@ -30,6 +30,7 @@ const char kOAuthRevokeTokenUrlSuffix[] = "/AuthSubRevokeToken"; ...@@ -30,6 +30,7 @@ const char kOAuthRevokeTokenUrlSuffix[] = "/AuthSubRevokeToken";
// API calls from accounts.google.com (LSO) // API calls from accounts.google.com (LSO)
const char kGetOAuthTokenUrlSuffix[] = "/o/oauth/GetOAuthToken/"; const char kGetOAuthTokenUrlSuffix[] = "/o/oauth/GetOAuthToken/";
const char kClientLoginToOAuth2UrlSuffix[] = "/o/oauth2/programmatic_auth"; const char kClientLoginToOAuth2UrlSuffix[] = "/o/oauth2/programmatic_auth";
const char kOAuth2RevokeUrlSuffix[] = "/o/oauth2/revoke";
const char kOAuth2TokenUrlSuffix[] = "/o/oauth2/token"; const char kOAuth2TokenUrlSuffix[] = "/o/oauth2/token";
const char kClientOAuthUrlSuffix[] = "/ClientOAuth"; const char kClientOAuthUrlSuffix[] = "/ClientOAuth";
...@@ -115,6 +116,7 @@ GaiaUrls::GaiaUrls() { ...@@ -115,6 +116,7 @@ GaiaUrls::GaiaUrls() {
std::string client_login_to_oauth2_url = lso_origin_url_ + std::string client_login_to_oauth2_url = lso_origin_url_ +
kClientLoginToOAuth2UrlSuffix; kClientLoginToOAuth2UrlSuffix;
std::string oauth2_token_url = lso_origin_url_ + kOAuth2TokenUrlSuffix; std::string oauth2_token_url = lso_origin_url_ + kOAuth2TokenUrlSuffix;
oauth2_revoke_url_ = lso_origin_url_ + kOAuth2RevokeUrlSuffix;
// URLs from www.googleapis.com. // URLs from www.googleapis.com.
oauth_wrap_bridge_user_info_scope_ = google_apis_origin_url_ + oauth_wrap_bridge_user_info_scope_ = google_apis_origin_url_ +
...@@ -234,6 +236,9 @@ const std::string& GaiaUrls::oauth2_issue_token_url() { ...@@ -234,6 +236,9 @@ const std::string& GaiaUrls::oauth2_issue_token_url() {
return oauth2_issue_token_url_; return oauth2_issue_token_url_;
} }
const std::string& GaiaUrls::oauth2_revoke_url() {
return oauth2_revoke_url_;
}
const std::string& GaiaUrls::gaia_login_form_realm() { const std::string& GaiaUrls::gaia_login_form_realm() {
return gaia_login_form_realm_; return gaia_login_form_realm_;
......
...@@ -40,6 +40,7 @@ class GaiaUrls { ...@@ -40,6 +40,7 @@ class GaiaUrls {
const std::string& client_login_to_oauth2_url(); const std::string& client_login_to_oauth2_url();
const std::string& oauth2_token_url(); const std::string& oauth2_token_url();
const std::string& oauth2_issue_token_url(); const std::string& oauth2_issue_token_url();
const std::string& oauth2_revoke_url();
const std::string& gaia_login_form_realm(); const std::string& gaia_login_form_realm();
...@@ -76,6 +77,7 @@ class GaiaUrls { ...@@ -76,6 +77,7 @@ class GaiaUrls {
std::string client_login_to_oauth2_url_; std::string client_login_to_oauth2_url_;
std::string oauth2_token_url_; std::string oauth2_token_url_;
std::string oauth2_issue_token_url_; std::string oauth2_issue_token_url_;
std::string oauth2_revoke_url_;
std::string gaia_login_form_realm_; std::string gaia_login_form_realm_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment