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

Side by Side Diff: chrome/browser/resources/gaia_auth/main.js

Issue 258123002: Implement a second version of the credentials passing API (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: One more s/requested_version/requestedVersion/ I had missed. Thank you for catching this, browser_t… Created 6 years, 7 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
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 * Authenticator class wraps the communications between Gaia and its host. 6 * Authenticator class wraps the communications between Gaia and its host.
7 */ 7 */
8 function Authenticator() { 8 function Authenticator() {
9 } 9 }
10 10
11 /** 11 /**
12 * Gaia auth extension url origin. 12 * Gaia auth extension url origin.
13 * @type {string} 13 * @type {string}
14 */ 14 */
15 Authenticator.THIS_EXTENSION_ORIGIN = 15 Authenticator.THIS_EXTENSION_ORIGIN =
16 'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik'; 16 'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik';
17 17
18 /** 18 /**
19 * The lowest version of the credentials passing API supported.
20 * @type {number}
21 */
22 Authenticator.MIN_API_VERSION_VERSION = 1;
23
24 /**
25 * The highest version of the credentials passing API supported.
26 * @type {number}
27 */
28 Authenticator.MAX_API_VERSION_VERSION = 2;
29
30 /**
31 * The key types supported for credentials passing API 2 and higher.
32 * @type {Array} Array of strings.
33 */
34 Authenticator.API_KEY_TYPES = [
35 'KEY_TYPE_PASSWORD_PLAIN',
36 ];
37
38 /**
19 * Singleton getter of Authenticator. 39 * Singleton getter of Authenticator.
20 * @return {Object} The singleton instance of Authenticator. 40 * @return {Object} The singleton instance of Authenticator.
21 */ 41 */
22 Authenticator.getInstance = function() { 42 Authenticator.getInstance = function() {
23 if (!Authenticator.instance_) { 43 if (!Authenticator.instance_) {
24 Authenticator.instance_ = new Authenticator(); 44 Authenticator.instance_ = new Authenticator();
25 } 45 }
26 return Authenticator.instance_; 46 return Authenticator.instance_;
27 }; 47 };
28 48
29 Authenticator.prototype = { 49 Authenticator.prototype = {
30 email_: null, 50 email_: null,
31 password_: null, 51
52 // Depending on the key type chosen, this will contain the plain text password
53 // or a credential derived from it along with the information required to
54 // repeat the derivation, such as a salt. The information will be encoded so
55 // that it contains printable ASCII characters only. The exact encoding is TBD
56 // when support for key types other than plain text password is added.
57 passwordBytes_: null,
58
32 attemptToken_: null, 59 attemptToken_: null,
33 60
34 // Input params from extension initialization URL. 61 // Input params from extension initialization URL.
35 inputLang_: undefined, 62 inputLang_: undefined,
36 intputEmail_: undefined, 63 intputEmail_: undefined,
37 64
38 isSAMLFlow_: false, 65 isSAMLFlow_: false,
39 isSAMLEnabled_: false, 66 isSAMLEnabled_: false,
40 supportChannel_: null, 67 supportChannel_: null,
41 68
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 }, 195 },
169 196
170 /** 197 /**
171 * Invoked when the signin flow is complete. 198 * Invoked when the signin flow is complete.
172 * @param {Object=} opt_extraMsg Optional extra info to send. 199 * @param {Object=} opt_extraMsg Optional extra info to send.
173 */ 200 */
174 completeLogin_: function(opt_extraMsg) { 201 completeLogin_: function(opt_extraMsg) {
175 var msg = { 202 var msg = {
176 'method': 'completeLogin', 203 'method': 'completeLogin',
177 'email': (opt_extraMsg && opt_extraMsg.email) || this.email_, 204 'email': (opt_extraMsg && opt_extraMsg.email) || this.email_,
178 'password': (opt_extraMsg && opt_extraMsg.password) || this.password_, 205 'password': (opt_extraMsg && opt_extraMsg.password) ||
206 this.passwordBytes_,
179 'usingSAML': this.isSAMLFlow_, 207 'usingSAML': this.isSAMLFlow_,
180 'chooseWhatToSync': this.chooseWhatToSync_ || false, 208 'chooseWhatToSync': this.chooseWhatToSync_ || false,
181 'skipForNow': opt_extraMsg && opt_extraMsg.skipForNow, 209 'skipForNow': opt_extraMsg && opt_extraMsg.skipForNow,
182 'sessionIndex': opt_extraMsg && opt_extraMsg.sessionIndex 210 'sessionIndex': opt_extraMsg && opt_extraMsg.sessionIndex
183 }; 211 };
184 window.parent.postMessage(msg, this.parentPage_); 212 window.parent.postMessage(msg, this.parentPage_);
185 if (this.isSAMLEnabled_) 213 if (this.isSAMLEnabled_)
186 this.supportChannel_.send({name: 'resetAuth'}); 214 this.supportChannel_.send({name: 'resetAuth'});
187 }, 215 },
188 216
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 /** 252 /**
225 * Invoked when the background page sends 'onHostedPageLoaded' message. 253 * Invoked when the background page sends 'onHostedPageLoaded' message.
226 * @param {!Object} msg Details sent with the message. 254 * @param {!Object} msg Details sent with the message.
227 */ 255 */
228 onAuthPageLoaded_: function(msg) { 256 onAuthPageLoaded_: function(msg) {
229 var isSAMLPage = msg.url.indexOf(this.gaiaUrl_) != 0; 257 var isSAMLPage = msg.url.indexOf(this.gaiaUrl_) != 0;
230 258
231 if (isSAMLPage && !this.isSAMLFlow_) { 259 if (isSAMLPage && !this.isSAMLFlow_) {
232 // GAIA redirected to a SAML login page. The credentials provided to this 260 // GAIA redirected to a SAML login page. The credentials provided to this
233 // page will determine what user gets logged in. The credentials obtained 261 // page will determine what user gets logged in. The credentials obtained
234 // from the GAIA login from are no longer relevant and can be discarded. 262 // from the GAIA login form are no longer relevant and can be discarded.
235 this.isSAMLFlow_ = true; 263 this.isSAMLFlow_ = true;
236 this.email_ = null; 264 this.email_ = null;
237 this.password_ = null; 265 this.passwordBytes_ = null;
238 } 266 }
239 267
240 window.parent.postMessage({ 268 window.parent.postMessage({
241 'method': 'authPageLoaded', 269 'method': 'authPageLoaded',
242 'isSAML': this.isSAMLFlow_, 270 'isSAML': this.isSAMLFlow_,
243 'domain': extractDomain(msg.url) 271 'domain': extractDomain(msg.url)
244 }, this.parentPage_); 272 }, this.parentPage_);
245 }, 273 },
246 274
247 /** 275 /**
248 * Invoked when the background page sends an 'onInsecureContentBlocked' 276 * Invoked when the background page sends an 'onInsecureContentBlocked'
249 * message. 277 * message.
250 */ 278 */
251 onInsecureContentBlocked_: function() { 279 onInsecureContentBlocked_: function() {
252 window.parent.postMessage({'method': 'insecureContentBlocked'}, 280 window.parent.postMessage({'method': 'insecureContentBlocked'},
253 this.parentPage_); 281 this.parentPage_);
254 }, 282 },
255 283
256 /** 284 /**
257 * Invoked when one of the credential passing API methods is called by a SAML 285 * Invoked when one of the credential passing API methods is called by a SAML
258 * provider. 286 * provider.
259 * @param {!Object} msg Details of the API call. 287 * @param {!Object} msg Details of the API call.
260 */ 288 */
261 onAPICall_: function(msg) { 289 onAPICall_: function(msg) {
262 var call = msg.call; 290 var call = msg.call;
291 if (call.method == 'initialize') {
292 // TODO(bartfab): There was no |requestedVersion| parameter in version 1
293 // of the API. Remove this code once all consumers have switched to
294 // version 2 or higher.
295 if (!call.hasOwnProperty('requestedVersion')) {
296 if (Authenticator.MIN_API_VERSION_VERSION == 1) {
297 this.apiVersion_ = 1;
298 this.initialized_ = true;
299 this.sendInitializationSuccess_();
300 }
301 // The glue code for API version 1 interprets all responses as success.
302 // Instead of reporting failure, do not send any response at all.
303 return;
304 }
305
306 if (!Number.isInteger(call.requestedVersion) ||
307 call.requestedVersion < Authenticator.MIN_API_VERSION_VERSION) {
308 this.sendInitializationFailure_();
309 return;
310 }
311
312 this.apiVersion_ = Math.min(call.requestedVersion,
313 Authenticator.MAX_API_VERSION_VERSION);
314 this.initialized_ = true;
315 this.sendInitializationSuccess_();
316 return;
317 }
318
263 if (call.method == 'add') { 319 if (call.method == 'add') {
320 if (this.apiVersion_ > 1 &&
321 Authenticator.API_KEY_TYPES.indexOf(call.keyType) == -1) {
322 console.error('Authenticator.onAPICall_: unsupported key type');
323 return;
324 }
264 this.apiToken_ = call.token; 325 this.apiToken_ = call.token;
265 this.email_ = call.user; 326 this.email_ = call.user;
266 this.password_ = call.password; 327 if (this.apiVersion_ == 1)
328 this.passwordBytes_ = call.password;
329 else
330 this.passwordBytes_ = call.passwordBytes;
267 } else if (call.method == 'confirm') { 331 } else if (call.method == 'confirm') {
268 if (call.token != this.apiToken_) 332 if (call.token != this.apiToken_)
269 console.error('Authenticator.onAPICall_: token mismatch'); 333 console.error('Authenticator.onAPICall_: token mismatch');
270 } else { 334 } else {
271 console.error('Authenticator.onAPICall_: unknown message'); 335 console.error('Authenticator.onAPICall_: unknown message');
272 } 336 }
273 }, 337 },
274 338
339 sendInitializationSuccess_: function() {
340 var response = {
341 result: 'initialized',
342 version: this.apiVersion_
343 };
344 if (this.apiVersion_ >= 2)
345 response['keyTypes'] = Authenticator.API_KEY_TYPES;
346
347 this.supportChannel_.send({name: 'apiResponse', response: response});
348 },
349
350 sendInitializationFailure_: function() {
351 this.supportChannel_.send({
352 name: 'apiResponse',
353 response: {result: 'initialization_failed'}
354 });
355 },
356
275 onConfirmLogin_: function() { 357 onConfirmLogin_: function() {
276 if (!this.isSAMLFlow_) { 358 if (!this.isSAMLFlow_) {
277 this.completeLogin_(); 359 this.completeLogin_();
278 return; 360 return;
279 } 361 }
280 362
281 var apiUsed = !!this.password_; 363 var apiUsed = !!this.passwordBytes_;
282 364
283 // Retrieve the e-mail address of the user who just authenticated from GAIA. 365 // Retrieve the e-mail address of the user who just authenticated from GAIA.
284 window.parent.postMessage({method: 'retrieveAuthenticatedUserEmail', 366 window.parent.postMessage({method: 'retrieveAuthenticatedUserEmail',
285 attemptToken: this.attemptToken_, 367 attemptToken: this.attemptToken_,
286 apiUsed: apiUsed}, 368 apiUsed: apiUsed},
287 this.parentPage_); 369 this.parentPage_);
288 370
289 if (!apiUsed) { 371 if (!apiUsed) {
290 this.supportChannel_.sendWithCallback( 372 this.supportChannel_.sendWithCallback(
291 {name: 'getScrapedPasswords'}, 373 {name: 'getScrapedPasswords'},
292 function(passwords) { 374 function(passwords) {
293 if (passwords.length == 0) { 375 if (passwords.length == 0) {
294 window.parent.postMessage( 376 window.parent.postMessage(
295 {method: 'noPassword', email: this.email_}, 377 {method: 'noPassword', email: this.email_},
296 this.parentPage_); 378 this.parentPage_);
297 } else { 379 } else {
298 window.parent.postMessage({method: 'confirmPassword', 380 window.parent.postMessage({method: 'confirmPassword',
299 email: this.email_, 381 email: this.email_,
300 passwordCount: passwords.length}, 382 passwordCount: passwords.length},
301 this.parentPage_); 383 this.parentPage_);
302 } 384 }
303 }.bind(this)); 385 }.bind(this));
304 } 386 }
305 }, 387 },
306 388
307 maybeCompleteSAMLLogin_: function() { 389 maybeCompleteSAMLLogin_: function() {
308 // SAML login is complete when the user's e-mail address has been retrieved 390 // SAML login is complete when the user's e-mail address has been retrieved
309 // from GAIA and the user has successfully confirmed the password. 391 // from GAIA and the user has successfully confirmed the password.
310 if (this.email_ !== null && this.password_ !== null) 392 if (this.email_ !== null && this.passwordBytes_ !== null)
311 this.completeLogin_(); 393 this.completeLogin_();
312 }, 394 },
313 395
314 onVerifyConfirmedPassword_: function(password) { 396 onVerifyConfirmedPassword_: function(password) {
315 this.supportChannel_.sendWithCallback( 397 this.supportChannel_.sendWithCallback(
316 {name: 'getScrapedPasswords'}, 398 {name: 'getScrapedPasswords'},
317 function(passwords) { 399 function(passwords) {
318 for (var i = 0; i < passwords.length; ++i) { 400 for (var i = 0; i < passwords.length; ++i) {
319 if (passwords[i] == password) { 401 if (passwords[i] == password) {
320 this.password_ = passwords[i]; 402 this.passwordBytes_ = passwords[i];
321 this.maybeCompleteSAMLLogin_(); 403 this.maybeCompleteSAMLLogin_();
322 return; 404 return;
323 } 405 }
324 } 406 }
325 window.parent.postMessage( 407 window.parent.postMessage(
326 {method: 'confirmPassword', email: this.email_}, 408 {method: 'confirmPassword', email: this.email_},
327 this.parentPage_); 409 this.parentPage_);
328 }.bind(this)); 410 }.bind(this));
329 }, 411 },
330 412
331 onMessage: function(e) { 413 onMessage: function(e) {
332 var msg = e.data; 414 var msg = e.data;
333 if (msg.method == 'attemptLogin' && this.isGaiaMessage_(e)) { 415 if (msg.method == 'attemptLogin' && this.isGaiaMessage_(e)) {
334 this.email_ = msg.email; 416 this.email_ = msg.email;
335 this.password_ = msg.password; 417 this.passwordBytes_ = msg.password;
336 this.attemptToken_ = msg.attemptToken; 418 this.attemptToken_ = msg.attemptToken;
337 this.chooseWhatToSync_ = msg.chooseWhatToSync; 419 this.chooseWhatToSync_ = msg.chooseWhatToSync;
338 this.isSAMLFlow_ = false; 420 this.isSAMLFlow_ = false;
339 if (this.isSAMLEnabled_) 421 if (this.isSAMLEnabled_)
340 this.supportChannel_.send({name: 'startAuth'}); 422 this.supportChannel_.send({name: 'startAuth'});
341 } else if (msg.method == 'clearOldAttempts' && this.isGaiaMessage_(e)) { 423 } else if (msg.method == 'clearOldAttempts' && this.isGaiaMessage_(e)) {
342 this.email_ = null; 424 this.email_ = null;
343 this.password_ = null; 425 this.passwordBytes_ = null;
344 this.attemptToken_ = null; 426 this.attemptToken_ = null;
345 this.isSAMLFlow_ = false; 427 this.isSAMLFlow_ = false;
346 this.onLoginUILoaded_(); 428 this.onLoginUILoaded_();
347 if (this.isSAMLEnabled_) 429 if (this.isSAMLEnabled_)
348 this.supportChannel_.send({name: 'resetAuth'}); 430 this.supportChannel_.send({name: 'resetAuth'});
349 } else if (msg.method == 'setAuthenticatedUserEmail' && 431 } else if (msg.method == 'setAuthenticatedUserEmail' &&
350 this.isParentMessage_(e)) { 432 this.isParentMessage_(e)) {
351 if (this.attemptToken_ == msg.attemptToken) { 433 if (this.attemptToken_ == msg.attemptToken) {
352 this.email_ = msg.email; 434 this.email_ = msg.email;
353 this.maybeCompleteSAMLLogin_(); 435 this.maybeCompleteSAMLLogin_();
354 } 436 }
355 } else if (msg.method == 'confirmLogin' && this.isInternalMessage_(e)) { 437 } else if (msg.method == 'confirmLogin' && this.isInternalMessage_(e)) {
356 if (this.attemptToken_ == msg.attemptToken) 438 if (this.attemptToken_ == msg.attemptToken)
357 this.onConfirmLogin_(); 439 this.onConfirmLogin_();
358 else 440 else
359 console.error('Authenticator.onMessage: unexpected attemptToken!?'); 441 console.error('Authenticator.onMessage: unexpected attemptToken!?');
360 } else if (msg.method == 'verifyConfirmedPassword' && 442 } else if (msg.method == 'verifyConfirmedPassword' &&
361 this.isParentMessage_(e)) { 443 this.isParentMessage_(e)) {
362 this.onVerifyConfirmedPassword_(msg.password); 444 this.onVerifyConfirmedPassword_(msg.password);
363 } else if (msg.method == 'redirectToSignin' && 445 } else if (msg.method == 'redirectToSignin' &&
364 this.isParentMessage_(e)) { 446 this.isParentMessage_(e)) {
365 $('gaia-frame').src = this.constructInitialFrameUrl_(); 447 $('gaia-frame').src = this.constructInitialFrameUrl_();
366 } else { 448 } else {
367 console.error('Authenticator.onMessage: unknown message + origin!?'); 449 console.error('Authenticator.onMessage: unknown message + origin!?');
368 } 450 }
369 } 451 }
370 }; 452 };
371 453
372 Authenticator.getInstance().initialize(); 454 Authenticator.getInstance().initialize();
OLDNEW
« no previous file with comments | « chrome/browser/resources/gaia_auth/background.js ('k') | chrome/browser/resources/gaia_auth/saml_injected.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698