[Chromoting] The webapp revokes OAuth refresh tokens when they will no longer be used.

BUG=123018

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132494 0039d316-1c4b-4281-b951-d872f2087c98
parent a47c03d6
...@@ -156,7 +156,7 @@ remoting.HostController.prototype.start = function(hostPin, callback) { ...@@ -156,7 +156,7 @@ remoting.HostController.prototype.start = function(hostPin, callback) {
'hmac:' + that.plugin_.getPinHash(newHostId, hostPin); 'hmac:' + that.plugin_.getPinHash(newHostId, hostPin);
var hostConfig = JSON.stringify({ var hostConfig = JSON.stringify({
xmpp_login: remoting.oauth2.getCachedEmail(), xmpp_login: remoting.oauth2.getCachedEmail(),
oauth_refresh_token: remoting.oauth2.getRefreshToken(), oauth_refresh_token: remoting.oauth2.exportRefreshToken(),
host_id: newHostId, host_id: newHostId,
host_name: hostName, host_name: hostName,
host_secret_hash: hostSecretHash, host_secret_hash: hostSecretHash,
......
...@@ -28,6 +28,9 @@ remoting.OAuth2 = function() { ...@@ -28,6 +28,9 @@ remoting.OAuth2 = function() {
/** @private */ /** @private */
remoting.OAuth2.prototype.KEY_REFRESH_TOKEN_ = 'oauth2-refresh-token'; remoting.OAuth2.prototype.KEY_REFRESH_TOKEN_ = 'oauth2-refresh-token';
/** @private */ /** @private */
remoting.OAuth2.prototype.KEY_REFRESH_TOKEN_REVOKABLE_ =
'oauth2-refresh-token-revokable';
/** @private */
remoting.OAuth2.prototype.KEY_ACCESS_TOKEN_ = 'oauth2-access-token'; remoting.OAuth2.prototype.KEY_ACCESS_TOKEN_ = 'oauth2-access-token';
/** @private */ /** @private */
remoting.OAuth2.prototype.KEY_EMAIL_ = 'remoting-email'; remoting.OAuth2.prototype.KEY_EMAIL_ = 'remoting-email';
...@@ -41,10 +44,12 @@ remoting.OAuth2.prototype.SCOPE_ = ...@@ -41,10 +44,12 @@ remoting.OAuth2.prototype.SCOPE_ =
/** @private */ /** @private */
remoting.OAuth2.prototype.OAUTH2_TOKEN_ENDPOINT_ = remoting.OAuth2.prototype.OAUTH2_TOKEN_ENDPOINT_ =
'https://accounts.google.com/o/oauth2/token'; 'https://accounts.google.com/o/oauth2/token';
/** @private */
remoting.OAuth2.prototype.OAUTH2_REVOKE_TOKEN_ENDPOINT_ =
'https://accounts.google.com/o/oauth2/revoke';
/** @return {boolean} True if the app is already authenticated. */ /** @return {boolean} True if the app is already authenticated. */
remoting.OAuth2.prototype.isAuthenticated = function() { remoting.OAuth2.prototype.isAuthenticated = function() {
if (this.getRefreshToken()) { if (this.getRefreshToken_()) {
return true; return true;
} }
return false; return false;
...@@ -56,22 +61,46 @@ remoting.OAuth2.prototype.isAuthenticated = function() { ...@@ -56,22 +61,46 @@ remoting.OAuth2.prototype.isAuthenticated = function() {
* @return {void} Nothing. * @return {void} Nothing.
*/ */
remoting.OAuth2.prototype.clear = function() { remoting.OAuth2.prototype.clear = function() {
window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_);
window.localStorage.removeItem(this.KEY_EMAIL_); window.localStorage.removeItem(this.KEY_EMAIL_);
this.clearAccessToken(); this.clearAccessToken();
this.clearRefreshToken_();
}; };
/** /**
* Sets the refresh token.
*
* This method also marks the token as revokable, so that this object will
* revoke the token when it no longer needs it.
*
* @param {string} token The new refresh token. * @param {string} token The new refresh token.
* @return {void} Nothing. * @return {void} Nothing.
*/ */
remoting.OAuth2.prototype.setRefreshToken = function(token) { remoting.OAuth2.prototype.setRefreshToken = function(token) {
window.localStorage.setItem(this.KEY_REFRESH_TOKEN_, escape(token)); window.localStorage.setItem(this.KEY_REFRESH_TOKEN_, escape(token));
window.localStorage.setItem(this.KEY_REFRESH_TOKEN_REVOKABLE_, true);
this.clearAccessToken(); this.clearAccessToken();
}; };
/** @return {?string} The refresh token, if authenticated, or NULL. */ /**
remoting.OAuth2.prototype.getRefreshToken = function() { * Gets the refresh token.
*
* This method also marks the refresh token as not revokable, so that this
* object will not revoke the token when it no longer needs it. After this
* object has exported the token, it cannot know whether it is still in use
* when this object no longer needs it.
*
* @return {?string} The refresh token, if authenticated, or NULL.
*/
remoting.OAuth2.prototype.exportRefreshToken = function() {
window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_REVOKABLE_);
return this.getRefreshToken_();
};
/**
* @return {?string} The refresh token, if authenticated, or NULL.
* @private
*/
remoting.OAuth2.prototype.getRefreshToken_ = function() {
var value = window.localStorage.getItem(this.KEY_REFRESH_TOKEN_); var value = window.localStorage.getItem(this.KEY_REFRESH_TOKEN_);
if (typeof value == 'string') { if (typeof value == 'string') {
return unescape(value); return unescape(value);
...@@ -79,6 +108,20 @@ remoting.OAuth2.prototype.getRefreshToken = function() { ...@@ -79,6 +108,20 @@ remoting.OAuth2.prototype.getRefreshToken = function() {
return null; return null;
}; };
/**
* Clears the refresh token.
*
* @return {void} Nothing.
* @private
*/
remoting.OAuth2.prototype.clearRefreshToken_ = function() {
if (window.localStorage.getItem(this.KEY_REFRESH_TOKEN_REVOKABLE_)) {
this.revokeToken_(this.getRefreshToken_());
}
window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_);
window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_REVOKABLE_);
};
/** /**
* @param {string} token The new access token. * @param {string} token The new access token.
* @param {number} expiration Expiration time in milliseconds since epoch. * @param {number} expiration Expiration time in milliseconds since epoch.
...@@ -200,7 +243,7 @@ remoting.OAuth2.prototype.refreshAccessToken = function(onDone) { ...@@ -200,7 +243,7 @@ remoting.OAuth2.prototype.refreshAccessToken = function(onDone) {
var parameters = { var parameters = {
'client_id': this.CLIENT_ID_, 'client_id': this.CLIENT_ID_,
'client_secret': this.CLIENT_SECRET_, 'client_secret': this.CLIENT_SECRET_,
'refresh_token': this.getRefreshToken(), 'refresh_token': this.getRefreshToken_(),
'grant_type': 'refresh_token' 'grant_type': 'refresh_token'
}; };
...@@ -263,6 +306,31 @@ remoting.OAuth2.prototype.exchangeCodeForToken = function(code, onDone) { ...@@ -263,6 +306,31 @@ remoting.OAuth2.prototype.exchangeCodeForToken = function(code, onDone) {
parameters); parameters);
}; };
/**
* Revokes a refresh or an access token.
*
* @param {string?} token An access or refresh token.
* @return {void} Nothing.
* @private
*/
remoting.OAuth2.prototype.revokeToken_ = function(token) {
if (!token || (token.length == 0)) {
return;
}
var parameters = { 'token': token };
/** @param {XMLHttpRequest} xhr The XHR reply. */
var processResponse = function(xhr) {
if (xhr.status != 200) {
console.log('Failed to revoke token. Status: ' + xhr.status +
' ; response: ' + xhr.responseText + ' ; xhr: ', xhr);
}
};
remoting.xhr.post(this.OAUTH2_REVOKE_TOKEN_ENDPOINT_,
processResponse,
parameters);
};
/** /**
* Call myfunc with an access token as the only parameter. * Call myfunc with an access token as the only parameter.
* *
......
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