Commit ec9abae8 authored by jrw's avatar jrw Committed by Commit bot

Added method to host daemon to exchange an auth code for just an OAuth

refresh token.

This change is necessary because, if the host daemon attempts to
retrieve an email address for an auth code from GCD, the request
fails, causing the host daemon to report failure and not return a
refresh token.

BUG=471928

Review URL: https://codereview.chromium.org/1076093003

Cr-Commit-Position: refs/heads/master@{#326895}
parent f09db896
...@@ -49,7 +49,8 @@ const char* kServiceAccountRedirectUri = "oob"; ...@@ -49,7 +49,8 @@ const char* kServiceAccountRedirectUri = "oob";
// Features supported in addition to the base protocol. // Features supported in addition to the base protocol.
const char* kSupportedFeatures[] = { const char* kSupportedFeatures[] = {
"pairingRegistry", "pairingRegistry",
"oauthClient" "oauthClient",
"getRefreshTokenFromAuthCode",
}; };
// Helper to extract the "config" part of a message as a DictionaryValue. // Helper to extract the "config" part of a message as a DictionaryValue.
...@@ -160,7 +161,11 @@ void Me2MeNativeMessagingHost::OnMessage(scoped_ptr<base::Value> message) { ...@@ -160,7 +161,11 @@ void Me2MeNativeMessagingHost::OnMessage(scoped_ptr<base::Value> message) {
} else if (type == "getHostClientId") { } else if (type == "getHostClientId") {
ProcessGetHostClientId(message_dict.Pass(), response.Pass()); ProcessGetHostClientId(message_dict.Pass(), response.Pass());
} else if (type == "getCredentialsFromAuthCode") { } else if (type == "getCredentialsFromAuthCode") {
ProcessGetCredentialsFromAuthCode(message_dict.Pass(), response.Pass()); ProcessGetCredentialsFromAuthCode(
message_dict.Pass(), response.Pass(), true);
} else if (type == "getRefreshTokenFromAuthCode") {
ProcessGetCredentialsFromAuthCode(
message_dict.Pass(), response.Pass(), false);
} else { } else {
LOG(ERROR) << "Unsupported request type: " << type; LOG(ERROR) << "Unsupported request type: " << type;
OnError(); OnError();
...@@ -422,7 +427,8 @@ void Me2MeNativeMessagingHost::ProcessGetHostClientId( ...@@ -422,7 +427,8 @@ void Me2MeNativeMessagingHost::ProcessGetHostClientId(
void Me2MeNativeMessagingHost::ProcessGetCredentialsFromAuthCode( void Me2MeNativeMessagingHost::ProcessGetCredentialsFromAuthCode(
scoped_ptr<base::DictionaryValue> message, scoped_ptr<base::DictionaryValue> message,
scoped_ptr<base::DictionaryValue> response) { scoped_ptr<base::DictionaryValue> response,
bool need_user_email) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
std::string auth_code; std::string auth_code;
...@@ -439,7 +445,7 @@ void Me2MeNativeMessagingHost::ProcessGetCredentialsFromAuthCode( ...@@ -439,7 +445,7 @@ void Me2MeNativeMessagingHost::ProcessGetCredentialsFromAuthCode(
}; };
oauth_client_->GetCredentialsFromAuthCode( oauth_client_->GetCredentialsFromAuthCode(
oauth_client_info, auth_code, base::Bind( oauth_client_info, auth_code, need_user_email, base::Bind(
&Me2MeNativeMessagingHost::SendCredentialsResponse, weak_ptr_, &Me2MeNativeMessagingHost::SendCredentialsResponse, weak_ptr_,
base::Passed(&response))); base::Passed(&response)));
} }
...@@ -513,7 +519,9 @@ void Me2MeNativeMessagingHost::SendCredentialsResponse( ...@@ -513,7 +519,9 @@ void Me2MeNativeMessagingHost::SendCredentialsResponse(
const std::string& refresh_token) { const std::string& refresh_token) {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
response->SetString("userEmail", user_email); if (!user_email.empty()) {
response->SetString("userEmail", user_email);
}
response->SetString("refreshToken", refresh_token); response->SetString("refreshToken", refresh_token);
channel_->SendMessage(response.Pass()); channel_->SendMessage(response.Pass());
} }
......
...@@ -100,7 +100,8 @@ class Me2MeNativeMessagingHost ...@@ -100,7 +100,8 @@ class Me2MeNativeMessagingHost
scoped_ptr<base::DictionaryValue> response); scoped_ptr<base::DictionaryValue> response);
void ProcessGetCredentialsFromAuthCode( void ProcessGetCredentialsFromAuthCode(
scoped_ptr<base::DictionaryValue> message, scoped_ptr<base::DictionaryValue> message,
scoped_ptr<base::DictionaryValue> response); scoped_ptr<base::DictionaryValue> response,
bool need_user_email);
// These Send... methods get called on the DaemonController's internal thread, // These Send... methods get called on the DaemonController's internal thread,
// or on the calling thread if called by the PairingRegistry. // or on the calling thread if called by the PairingRegistry.
......
...@@ -23,13 +23,16 @@ OAuthClient::~OAuthClient() { ...@@ -23,13 +23,16 @@ OAuthClient::~OAuthClient() {
void OAuthClient::GetCredentialsFromAuthCode( void OAuthClient::GetCredentialsFromAuthCode(
const gaia::OAuthClientInfo& oauth_client_info, const gaia::OAuthClientInfo& oauth_client_info,
const std::string& auth_code, const std::string& auth_code,
bool need_user_email,
CompletionCallback on_done) { CompletionCallback on_done) {
if (!on_done_.is_null()) { if (!on_done_.is_null()) {
pending_requests_.push(Request(oauth_client_info, auth_code, on_done)); pending_requests_.push(
Request(oauth_client_info, auth_code, need_user_email, on_done));
return; return;
} }
need_user_email_ = need_user_email;
on_done_ = on_done; on_done_ = on_done;
// Map the authorization code to refresh and access tokens. // Map the authorization code to refresh and access tokens.
gaia_oauth_client_.GetTokensFromAuthCode(oauth_client_info, auth_code, gaia_oauth_client_.GetTokensFromAuthCode(oauth_client_info, auth_code,
...@@ -41,8 +44,12 @@ void OAuthClient::OnGetTokensResponse( ...@@ -41,8 +44,12 @@ void OAuthClient::OnGetTokensResponse(
const std::string& access_token, const std::string& access_token,
int expires_in_seconds) { int expires_in_seconds) {
refresh_token_ = refresh_token; refresh_token_ = refresh_token;
// Get the email corresponding to the access token. if (need_user_email_) {
gaia_oauth_client_.GetUserEmail(access_token, kMaxGaiaRetries, this); // Get the email corresponding to the access token.
gaia_oauth_client_.GetUserEmail(access_token, kMaxGaiaRetries, this);
} else {
SendResponse("", refresh_token_);
}
} }
void OAuthClient::OnRefreshTokenResponse( void OAuthClient::OnRefreshTokenResponse(
...@@ -64,7 +71,10 @@ void OAuthClient::SendResponse(const std::string& user_email, ...@@ -64,7 +71,10 @@ void OAuthClient::SendResponse(const std::string& user_email,
pending_requests_.pop(); pending_requests_.pop();
// GetCredentialsFromAuthCode is asynchronous, so it's safe to call it here. // GetCredentialsFromAuthCode is asynchronous, so it's safe to call it here.
GetCredentialsFromAuthCode( GetCredentialsFromAuthCode(
request.oauth_client_info, request.auth_code, request.on_done); request.oauth_client_info,
request.auth_code,
request.need_user_email,
request.on_done);
} }
} }
...@@ -83,9 +93,11 @@ void OAuthClient::OnNetworkError(int response_code) { ...@@ -83,9 +93,11 @@ void OAuthClient::OnNetworkError(int response_code) {
OAuthClient::Request::Request( OAuthClient::Request::Request(
const gaia::OAuthClientInfo& oauth_client_info, const gaia::OAuthClientInfo& oauth_client_info,
const std::string& auth_code, const std::string& auth_code,
bool need_user_email,
CompletionCallback on_done) { CompletionCallback on_done) {
this->oauth_client_info = oauth_client_info; this->oauth_client_info = oauth_client_info;
this->auth_code = auth_code; this->auth_code = auth_code;
this->need_user_email = need_user_email;
this->on_done = on_done; this->on_done = on_done;
} }
......
...@@ -35,15 +35,17 @@ class OAuthClient : public gaia::GaiaOAuthClient::Delegate { ...@@ -35,15 +35,17 @@ class OAuthClient : public gaia::GaiaOAuthClient::Delegate {
~OAuthClient() override; ~OAuthClient() override;
// Redeems |auth_code| using |oauth_client_info| to obtain |refresh_token| and // Redeems |auth_code| using |oauth_client_info| to obtain
// |access_token|, then uses the userinfo endpoint to obtain |user_email|. // |refresh_token| and |access_token|, then, if |need_user_email| is
// Calls CompletionCallback with |user_email| and |refresh_token| when done, // true, uses the userinfo endpoint to obtain |user_email|. Calls
// or with empty strings on error. // CompletionCallback with |user_email| and |refresh_token| when
// If a request is received while another one is being processed, it is // done, or with empty strings on error. If a request is received
// enqueued and processed after the first one is finished. // while another one is being processed, it is enqueued and
// processed after the first one is finished.
void GetCredentialsFromAuthCode( void GetCredentialsFromAuthCode(
const gaia::OAuthClientInfo& oauth_client_info, const gaia::OAuthClientInfo& oauth_client_info,
const std::string& auth_code, const std::string& auth_code,
bool need_user_email,
CompletionCallback on_done); CompletionCallback on_done);
// gaia::GaiaOAuthClient::Delegate // gaia::GaiaOAuthClient::Delegate
...@@ -61,10 +63,12 @@ class OAuthClient : public gaia::GaiaOAuthClient::Delegate { ...@@ -61,10 +63,12 @@ class OAuthClient : public gaia::GaiaOAuthClient::Delegate {
struct Request { struct Request {
Request(const gaia::OAuthClientInfo& oauth_client_info, Request(const gaia::OAuthClientInfo& oauth_client_info,
const std::string& auth_code, const std::string& auth_code,
bool need_user_email,
CompletionCallback on_done); CompletionCallback on_done);
virtual ~Request(); virtual ~Request();
gaia::OAuthClientInfo oauth_client_info; gaia::OAuthClientInfo oauth_client_info;
std::string auth_code; std::string auth_code;
bool need_user_email;
CompletionCallback on_done; CompletionCallback on_done;
}; };
...@@ -74,6 +78,7 @@ class OAuthClient : public gaia::GaiaOAuthClient::Delegate { ...@@ -74,6 +78,7 @@ class OAuthClient : public gaia::GaiaOAuthClient::Delegate {
std::queue<Request> pending_requests_; std::queue<Request> pending_requests_;
gaia::GaiaOAuthClient gaia_oauth_client_; gaia::GaiaOAuthClient gaia_oauth_client_;
std::string refresh_token_; std::string refresh_token_;
bool need_user_email_;
CompletionCallback on_done_; CompletionCallback on_done_;
DISALLOW_COPY_AND_ASSIGN(OAuthClient); DISALLOW_COPY_AND_ASSIGN(OAuthClient);
......
...@@ -294,6 +294,14 @@ remoting.HostDaemonFacade.prototype.handleIncomingMessage_ = ...@@ -294,6 +294,14 @@ remoting.HostDaemonFacade.prototype.handleIncomingMessage_ =
throw 'Missing userEmail or refreshToken'; throw 'Missing userEmail or refreshToken';
} }
case 'getRefreshTokenFromAuthCodeResponse':
var refreshToken = base.getStringAttr(message, 'refreshToken');
if (refreshToken) {
return refreshToken;
} else {
throw 'Missing refreshToken';
}
default: default:
throw 'Unexpected native message: ' + message; throw 'Unexpected native message: ' + message;
} }
...@@ -495,7 +503,6 @@ remoting.HostDaemonFacade.prototype.getHostClientId = function() { ...@@ -495,7 +503,6 @@ remoting.HostDaemonFacade.prototype.getHostClientId = function() {
}; };
/** /**
*
* @param {string} authorizationCode OAuth authorization code. * @param {string} authorizationCode OAuth authorization code.
* @return {!Promise<{remoting.XmppCredentials}>} * @return {!Promise<{remoting.XmppCredentials}>}
*/ */
...@@ -506,3 +513,15 @@ remoting.HostDaemonFacade.prototype.getCredentialsFromAuthCode = ...@@ -506,3 +513,15 @@ remoting.HostDaemonFacade.prototype.getCredentialsFromAuthCode =
authorizationCode: authorizationCode authorizationCode: authorizationCode
}); });
}; };
/**
* @param {string} authorizationCode OAuth authorization code.
* @return {!Promise<string>}
*/
remoting.HostDaemonFacade.prototype.getRefreshTokenFromAuthCode =
function(authorizationCode) {
return this.postMessage_({
type: 'getRefreshTokenFromAuthCode',
authorizationCode: authorizationCode
});
};
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