Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: remoting/webapp/oauth2.js

Issue 10080010: [Chromoting] The webapp revokes OAuth refresh tokens when they will no longer be used. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Log an error more thoroughly. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/webapp/host_controller.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview 6 * @fileoverview
7 * OAuth2 class that handles retrieval/storage of an OAuth2 token. 7 * OAuth2 class that handles retrieval/storage of an OAuth2 token.
8 * 8 *
9 * Uses a content script to trampoline the OAuth redirect page back into the 9 * Uses a content script to trampoline the OAuth redirect page back into the
10 * extension context. This works around the lack of native support for 10 * extension context. This works around the lack of native support for
(...skipping 10 matching lines...) Expand all
21 21
22 22
23 /** @constructor */ 23 /** @constructor */
24 remoting.OAuth2 = function() { 24 remoting.OAuth2 = function() {
25 }; 25 };
26 26
27 // Constants representing keys used for storing persistent state. 27 // Constants representing keys used for storing persistent state.
28 /** @private */ 28 /** @private */
29 remoting.OAuth2.prototype.KEY_REFRESH_TOKEN_ = 'oauth2-refresh-token'; 29 remoting.OAuth2.prototype.KEY_REFRESH_TOKEN_ = 'oauth2-refresh-token';
30 /** @private */ 30 /** @private */
31 remoting.OAuth2.prototype.KEY_REFRESH_TOKEN_REVOKABLE_ =
32 'oauth2-refresh-token-revokable';
33 /** @private */
31 remoting.OAuth2.prototype.KEY_ACCESS_TOKEN_ = 'oauth2-access-token'; 34 remoting.OAuth2.prototype.KEY_ACCESS_TOKEN_ = 'oauth2-access-token';
32 /** @private */ 35 /** @private */
33 remoting.OAuth2.prototype.KEY_EMAIL_ = 'remoting-email'; 36 remoting.OAuth2.prototype.KEY_EMAIL_ = 'remoting-email';
34 37
35 // Constants for parameters used in retrieving the OAuth2 credentials. 38 // Constants for parameters used in retrieving the OAuth2 credentials.
36 /** @private */ 39 /** @private */
37 remoting.OAuth2.prototype.SCOPE_ = 40 remoting.OAuth2.prototype.SCOPE_ =
38 'https://www.googleapis.com/auth/chromoting ' + 41 'https://www.googleapis.com/auth/chromoting ' +
39 'https://www.googleapis.com/auth/googletalk ' + 42 'https://www.googleapis.com/auth/googletalk ' +
40 'https://www.googleapis.com/auth/userinfo#email'; 43 'https://www.googleapis.com/auth/userinfo#email';
41 /** @private */ 44 /** @private */
42 remoting.OAuth2.prototype.OAUTH2_TOKEN_ENDPOINT_ = 45 remoting.OAuth2.prototype.OAUTH2_TOKEN_ENDPOINT_ =
43 'https://accounts.google.com/o/oauth2/token'; 46 'https://accounts.google.com/o/oauth2/token';
44 47 /** @private */
48 remoting.OAuth2.prototype.OAUTH2_REVOKE_TOKEN_ENDPOINT_ =
49 'https://accounts.google.com/o/oauth2/revoke';
45 /** @return {boolean} True if the app is already authenticated. */ 50 /** @return {boolean} True if the app is already authenticated. */
46 remoting.OAuth2.prototype.isAuthenticated = function() { 51 remoting.OAuth2.prototype.isAuthenticated = function() {
47 if (this.getRefreshToken()) { 52 if (this.getRefreshToken_()) {
48 return true; 53 return true;
49 } 54 }
50 return false; 55 return false;
51 }; 56 };
52 57
53 /** 58 /**
54 * Removes all storage, and effectively unauthenticates the user. 59 * Removes all storage, and effectively unauthenticates the user.
55 * 60 *
56 * @return {void} Nothing. 61 * @return {void} Nothing.
57 */ 62 */
58 remoting.OAuth2.prototype.clear = function() { 63 remoting.OAuth2.prototype.clear = function() {
59 window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_);
60 window.localStorage.removeItem(this.KEY_EMAIL_); 64 window.localStorage.removeItem(this.KEY_EMAIL_);
61 this.clearAccessToken(); 65 this.clearAccessToken();
66 this.clearRefreshToken_();
62 }; 67 };
63 68
64 /** 69 /**
70 * Sets the refresh token.
71 *
72 * This method also marks the token as revokable, so that this object will
73 * revoke the token when it no longer needs it.
74 *
65 * @param {string} token The new refresh token. 75 * @param {string} token The new refresh token.
66 * @return {void} Nothing. 76 * @return {void} Nothing.
67 */ 77 */
68 remoting.OAuth2.prototype.setRefreshToken = function(token) { 78 remoting.OAuth2.prototype.setRefreshToken = function(token) {
69 window.localStorage.setItem(this.KEY_REFRESH_TOKEN_, escape(token)); 79 window.localStorage.setItem(this.KEY_REFRESH_TOKEN_, escape(token));
80 window.localStorage.setItem(this.KEY_REFRESH_TOKEN_REVOKABLE_, true);
70 this.clearAccessToken(); 81 this.clearAccessToken();
71 }; 82 };
72 83
73 /** @return {?string} The refresh token, if authenticated, or NULL. */ 84 /**
74 remoting.OAuth2.prototype.getRefreshToken = function() { 85 * Gets the refresh token.
86 *
87 * This method also marks the refresh token as not revokable, so that this
88 * object will not revoke the token when it no longer needs it. After this
89 * object has exported the token, it cannot know whether it is still in use
90 * when this object no longer needs it.
91 *
92 * @return {?string} The refresh token, if authenticated, or NULL.
93 */
94 remoting.OAuth2.prototype.exportRefreshToken = function() {
95 window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_REVOKABLE_);
96 return this.getRefreshToken_();
97 };
98
99 /**
100 * @return {?string} The refresh token, if authenticated, or NULL.
101 * @private
102 */
103 remoting.OAuth2.prototype.getRefreshToken_ = function() {
75 var value = window.localStorage.getItem(this.KEY_REFRESH_TOKEN_); 104 var value = window.localStorage.getItem(this.KEY_REFRESH_TOKEN_);
76 if (typeof value == 'string') { 105 if (typeof value == 'string') {
77 return unescape(value); 106 return unescape(value);
78 } 107 }
79 return null; 108 return null;
80 }; 109 };
81 110
82 /** 111 /**
112 * Clears the refresh token.
113 *
114 * @return {void} Nothing.
115 * @private
116 */
117 remoting.OAuth2.prototype.clearRefreshToken_ = function() {
118 if (window.localStorage.getItem(this.KEY_REFRESH_TOKEN_REVOKABLE_)) {
119 this.revokeToken_(this.getRefreshToken_());
120 }
121 window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_);
122 window.localStorage.removeItem(this.KEY_REFRESH_TOKEN_REVOKABLE_);
123 };
124
125 /**
83 * @param {string} token The new access token. 126 * @param {string} token The new access token.
84 * @param {number} expiration Expiration time in milliseconds since epoch. 127 * @param {number} expiration Expiration time in milliseconds since epoch.
85 * @return {void} Nothing. 128 * @return {void} Nothing.
86 */ 129 */
87 remoting.OAuth2.prototype.setAccessToken = function(token, expiration) { 130 remoting.OAuth2.prototype.setAccessToken = function(token, expiration) {
88 var access_token = {'token': token, 'expiration': expiration}; 131 var access_token = {'token': token, 'expiration': expiration};
89 window.localStorage.setItem(this.KEY_ACCESS_TOKEN_, 132 window.localStorage.setItem(this.KEY_ACCESS_TOKEN_,
90 JSON.stringify(access_token)); 133 JSON.stringify(access_token));
91 }; 134 };
92 135
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 * @return {void} Nothing. 236 * @return {void} Nothing.
194 */ 237 */
195 remoting.OAuth2.prototype.refreshAccessToken = function(onDone) { 238 remoting.OAuth2.prototype.refreshAccessToken = function(onDone) {
196 if (!this.isAuthenticated()) { 239 if (!this.isAuthenticated()) {
197 throw 'Not Authenticated.'; 240 throw 'Not Authenticated.';
198 } 241 }
199 242
200 var parameters = { 243 var parameters = {
201 'client_id': this.CLIENT_ID_, 244 'client_id': this.CLIENT_ID_,
202 'client_secret': this.CLIENT_SECRET_, 245 'client_secret': this.CLIENT_SECRET_,
203 'refresh_token': this.getRefreshToken(), 246 'refresh_token': this.getRefreshToken_(),
204 'grant_type': 'refresh_token' 247 'grant_type': 'refresh_token'
205 }; 248 };
206 249
207 /** @type {remoting.OAuth2} */ 250 /** @type {remoting.OAuth2} */
208 var that = this; 251 var that = this;
209 /** @param {XMLHttpRequest} xhr The XHR reply. */ 252 /** @param {XMLHttpRequest} xhr The XHR reply. */
210 var processTokenResponse = function(xhr) { 253 var processTokenResponse = function(xhr) {
211 that.processTokenResponse_(xhr); 254 that.processTokenResponse_(xhr);
212 onDone(xhr); 255 onDone(xhr);
213 }; 256 };
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 var processTokenResponse = function(xhr) { 300 var processTokenResponse = function(xhr) {
258 that.processTokenResponse_(xhr); 301 that.processTokenResponse_(xhr);
259 onDone(xhr); 302 onDone(xhr);
260 }; 303 };
261 remoting.xhr.post(this.OAUTH2_TOKEN_ENDPOINT_, 304 remoting.xhr.post(this.OAUTH2_TOKEN_ENDPOINT_,
262 processTokenResponse, 305 processTokenResponse,
263 parameters); 306 parameters);
264 }; 307 };
265 308
266 /** 309 /**
310 * Revokes a refresh or an access token.
311 *
312 * @param {string?} token An access or refresh token.
313 * @return {void} Nothing.
314 * @private
315 */
316 remoting.OAuth2.prototype.revokeToken_ = function(token) {
317 if (!token || (token.length == 0)) {
318 return;
319 }
320 var parameters = { 'token': token };
321
322 /** @param {XMLHttpRequest} xhr The XHR reply. */
323 var processResponse = function(xhr) {
324 if (xhr.status != 200) {
325 console.log('Failed to revoke token. Status: ' + xhr.status +
326 ' ; response: ' + xhr.responseText + ' ; xhr: ', xhr);
327 }
328 };
329 remoting.xhr.post(this.OAUTH2_REVOKE_TOKEN_ENDPOINT_,
330 processResponse,
331 parameters);
332 };
333
334 /**
267 * Call myfunc with an access token as the only parameter. 335 * Call myfunc with an access token as the only parameter.
268 * 336 *
269 * This will refresh the access token if necessary. If the access token 337 * This will refresh the access token if necessary. If the access token
270 * cannot be refreshed, an error is thrown. 338 * cannot be refreshed, an error is thrown.
271 * 339 *
272 * The access token will remain valid for at least 2 minutes. 340 * The access token will remain valid for at least 2 minutes.
273 * 341 *
274 * @param {function(string):void} myfunc 342 * @param {function(string):void} myfunc
275 * Function to invoke with access token. 343 * Function to invoke with access token.
276 * @return {void} Nothing. 344 * @return {void} Nothing.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 * @return {?string} The email address, if it has been cached by a previous call 398 * @return {?string} The email address, if it has been cached by a previous call
331 * to getEmail, otherwise null. 399 * to getEmail, otherwise null.
332 */ 400 */
333 remoting.OAuth2.prototype.getCachedEmail = function() { 401 remoting.OAuth2.prototype.getCachedEmail = function() {
334 var value = window.localStorage.getItem(this.KEY_EMAIL_); 402 var value = window.localStorage.getItem(this.KEY_EMAIL_);
335 if (typeof value == 'string') { 403 if (typeof value == 'string') {
336 return value; 404 return value;
337 } 405 }
338 return null; 406 return null;
339 }; 407 };
OLDNEW
« no previous file with comments | « remoting/webapp/host_controller.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698