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

Side by Side Diff: chrome/browser/resources/gaia_auth_host/authenticator.js

Issue 1344443002: Implement new password separated sign in flow for chrome desktop. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: merged Created 5 years, 2 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <include src="saml_handler.js"> 5 <include src="saml_handler.js">
6 6
7 /** 7 /**
8 * @fileoverview An UI component to authenciate to Chrome. The component hosts 8 * @fileoverview An UI component to authenciate to Chrome. The component hosts
9 * IdP web pages in a webview. A client who is interested in monitoring 9 * IdP web pages in a webview. A client who is interested in monitoring
10 * authentication events should pass a listener object of type 10 * authentication events should pass a listener object of type
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 Authenticator.prototype.load = function(authMode, data) { 195 Authenticator.prototype.load = function(authMode, data) {
196 this.authMode = authMode; 196 this.authMode = authMode;
197 this.clearCredentials_(); 197 this.clearCredentials_();
198 // gaiaUrl parameter is used for testing. Once defined, it is never changed. 198 // gaiaUrl parameter is used for testing. Once defined, it is never changed.
199 this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN; 199 this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN;
200 this.continueUrl_ = data.continueUrl || CONTINUE_URL; 200 this.continueUrl_ = data.continueUrl || CONTINUE_URL;
201 this.continueUrlWithoutParams_ = 201 this.continueUrlWithoutParams_ =
202 this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) || 202 this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) ||
203 this.continueUrl_; 203 this.continueUrl_;
204 this.isConstrainedWindow_ = data.constrained == '1'; 204 this.isConstrainedWindow_ = data.constrained == '1';
205 this.isNewGaiaFlowChromeOS = data.isNewGaiaFlowChromeOS; 205 this.isNewGaiaFlow = data.isNewGaiaFlow;
206 this.useEafe_ = data.useEafe || false; 206 this.useEafe_ = data.useEafe || false;
207 this.clientId_ = data.clientId; 207 this.clientId_ = data.clientId;
208 this.gapsCookie_ = data.gapsCookie; 208 this.gapsCookie_ = data.gapsCookie;
209 this.gapsCookieSent_ = false; 209 this.gapsCookieSent_ = false;
210 this.newGapsCookie_ = null; 210 this.newGapsCookie_ = null;
211 this.dontResizeNonEmbeddedPages = data.dontResizeNonEmbeddedPages; 211 this.dontResizeNonEmbeddedPages = data.dontResizeNonEmbeddedPages;
212 212
213 this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); 213 this.initialFrameUrl_ = this.constructInitialFrameUrl_(data);
214 this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; 214 this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_;
215 // Don't block insecure content for desktop flow because it lands on 215 // Don't block insecure content for desktop flow because it lands on
216 // http. Otherwise, block insecure content as long as gaia is https. 216 // http. Otherwise, block insecure content as long as gaia is https.
217 this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP && 217 this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP &&
218 this.idpOrigin_.indexOf('https://') == 0; 218 this.idpOrigin_.indexOf('https://') == 0;
219 this.needPassword = !('needPassword' in data) || data.needPassword; 219 this.needPassword = !('needPassword' in data) || data.needPassword;
220 220
221 if (this.isNewGaiaFlowChromeOS) { 221 if (this.isNewGaiaFlow) {
222 this.webview_.contextMenus.onShow.addListener(function(e) { 222 this.webview_.contextMenus.onShow.addListener(function(e) {
223 e.preventDefault(); 223 e.preventDefault();
224 }); 224 });
225 225
226 if (!this.onBeforeSetHeadersSet_) { 226 if (!this.onBeforeSetHeadersSet_) {
227 this.onBeforeSetHeadersSet_ = true; 227 this.onBeforeSetHeadersSet_ = true;
228 var filterPrefix = this.idpOrigin_ + EMBEDDED_SETUP_CHROMEOS_ENDPOINT; 228 var filterPrefix = this.idpOrigin_ + EMBEDDED_SETUP_CHROMEOS_ENDPOINT;
229 // This depends on gaiaUrl parameter, that is why it is here. 229 // This depends on gaiaUrl parameter, that is why it is here.
230 this.webview_.request.onBeforeSendHeaders.addListener( 230 this.webview_.request.onBeforeSendHeaders.addListener(
231 this.onBeforeSendHeaders_.bind(this), 231 this.onBeforeSendHeaders_.bind(this),
232 {urls: [filterPrefix + '?*', filterPrefix + '/*']}, 232 {urls: [filterPrefix + '?*', filterPrefix + '/*']},
233 ['requestHeaders', 'blocking']); 233 ['requestHeaders', 'blocking']);
234 } 234 }
235 } 235 }
236 236
237 this.webview_.src = this.reloadUrl_; 237 this.webview_.src = this.reloadUrl_;
238 }; 238 };
239 239
240 /** 240 /**
241 * Reloads the authenticator component. 241 * Reloads the authenticator component.
242 */ 242 */
243 Authenticator.prototype.reload = function() { 243 Authenticator.prototype.reload = function() {
244 this.clearCredentials_(); 244 this.clearCredentials_();
245 this.webview_.src = this.reloadUrl_; 245 this.webview_.src = this.reloadUrl_;
246 }; 246 };
247 247
248 Authenticator.prototype.constructInitialFrameUrl_ = function(data) { 248 Authenticator.prototype.constructInitialFrameUrl_ = function(data) {
249 var path = data.gaiaPath; 249 var path = data.gaiaPath;
250 if (!path && this.isNewGaiaFlowChromeOS) 250 if (!path && this.isNewGaiaFlow)
251 path = EMBEDDED_SETUP_CHROMEOS_ENDPOINT; 251 path = EMBEDDED_SETUP_CHROMEOS_ENDPOINT;
252 if (!path) 252 if (!path)
253 path = IDP_PATH; 253 path = IDP_PATH;
254 var url = this.idpOrigin_ + path; 254 var url = this.idpOrigin_ + path;
255 255
256 if (this.isNewGaiaFlowChromeOS) { 256 if (this.isNewGaiaFlow) {
257 if (data.chromeType) 257 if (data.chromeType)
258 url = appendParam(url, 'chrometype', data.chromeType); 258 url = appendParam(url, 'chrometype', data.chromeType);
259 if (data.clientId) 259 if (data.clientId)
260 url = appendParam(url, 'client_id', data.clientId); 260 url = appendParam(url, 'client_id', data.clientId);
261 if (data.enterpriseDomain) 261 if (data.enterpriseDomain)
262 url = appendParam(url, 'manageddomain', data.enterpriseDomain); 262 url = appendParam(url, 'manageddomain', data.enterpriseDomain);
263 if (data.clientVersion) 263 if (data.clientVersion)
264 url = appendParam(url, 'client_version', data.clientVersion); 264 url = appendParam(url, 'client_version', data.clientVersion);
265 if (data.platformVersion) 265 if (data.platformVersion)
266 url = appendParam(url, 'platform_version', data.platformVersion); 266 url = appendParam(url, 'platform_version', data.platformVersion);
267 if (data.releaseChannel) 267 if (data.releaseChannel)
268 url = appendParam(url, 'release_channel', data.releaseChannel); 268 url = appendParam(url, 'release_channel', data.releaseChannel);
269 if (data.endpointGen) 269 if (data.endpointGen)
270 url = appendParam(url, 'endpoint_gen', data.endpointGen); 270 url = appendParam(url, 'endpoint_gen', data.endpointGen);
271 } else { 271 } else {
272 url = appendParam(url, 'continue', this.continueUrl_); 272 url = appendParam(url, 'continue', this.continueUrl_);
273 url = appendParam(url, 'service', data.service || SERVICE_ID); 273 url = appendParam(url, 'service', data.service || SERVICE_ID);
274 } 274 }
275 if (data.hl) 275 if (data.hl)
276 url = appendParam(url, 'hl', data.hl); 276 url = appendParam(url, 'hl', data.hl);
277 if (data.gaiaId) 277 if (data.gaiaId)
278 url = appendParam(url, 'user_id', data.gaiaId); 278 url = appendParam(url, 'user_id', data.gaiaId);
279 if (data.email) 279 if (data.email) {
280 url = appendParam(url, 'Email', data.email); 280 // The email fields allow for the following possibilities:
281 //
282 // 1/ If neither Email nor email_hint is supplied, then the email text
283 // field is blank and the user must type an email to proceed.
284 //
285 // 2/ If Email is supplied, then the email is hardcoded and the user
286 // cannot change it. The user is asked for password. This is useful for
287 // re-auth scenarios, where chrome needs the user to authenticate for a
288 // specific account and only that account.
289 //
290 // 3/ If email_hint is supplied, gaia will prefill the email text field
291 // using the given email address, but the user can still change it and
292 // then proceed. This is used on desktop when the user disconnects their
293 // profile then reconnects, to encourage them to use the same account.
294 if (data.readOnlyEmail) {
295 url = appendParam(url, 'Email', data.email);
296 } else {
297 url = appendParam(url, 'email_hint', data.email);
298 }
299 }
281 if (this.isConstrainedWindow_) 300 if (this.isConstrainedWindow_)
282 url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE); 301 url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE);
283 if (data.flow) 302 if (data.flow)
284 url = appendParam(url, 'flow', data.flow); 303 url = appendParam(url, 'flow', data.flow);
285 if (data.emailDomain) 304 if (data.emailDomain)
286 url = appendParam(url, 'emaildomain', data.emailDomain); 305 url = appendParam(url, 'emaildomain', data.emailDomain);
287 return url; 306 return url;
288 }; 307 };
289 308
290 /** 309 /**
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 // Removes "" around. 409 // Removes "" around.
391 this.email_ = signinDetails['email'].slice(1, -1); 410 this.email_ = signinDetails['email'].slice(1, -1);
392 this.gaiaId_ = signinDetails['obfuscatedid'].slice(1, -1); 411 this.gaiaId_ = signinDetails['obfuscatedid'].slice(1, -1);
393 this.sessionIndex_ = signinDetails['sessionindex']; 412 this.sessionIndex_ = signinDetails['sessionindex'];
394 } else if (headerName == LOCATION_HEADER) { 413 } else if (headerName == LOCATION_HEADER) {
395 // If the "choose what to sync" checkbox was clicked, then the continue 414 // If the "choose what to sync" checkbox was clicked, then the continue
396 // URL will contain a source=3 field. 415 // URL will contain a source=3 field.
397 var location = decodeURIComponent(header.value); 416 var location = decodeURIComponent(header.value);
398 this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/); 417 this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/);
399 } else if ( 418 } else if (
400 this.isNewGaiaFlowChromeOS && headerName == SET_COOKIE_HEADER) { 419 this.isNewGaiaFlow && headerName == SET_COOKIE_HEADER) {
401 var headerValue = header.value; 420 var headerValue = header.value;
402 if (headerValue.indexOf(OAUTH_CODE_COOKIE + '=', 0) == 0) { 421 if (headerValue.indexOf(OAUTH_CODE_COOKIE + '=', 0) == 0) {
403 this.oauthCode_ = 422 this.oauthCode_ =
404 headerValue.substring(OAUTH_CODE_COOKIE.length + 1).split(';')[0]; 423 headerValue.substring(OAUTH_CODE_COOKIE.length + 1).split(';')[0];
405 } 424 }
406 if (headerValue.indexOf(GAPS_COOKIE + '=', 0) == 0) { 425 if (headerValue.indexOf(GAPS_COOKIE + '=', 0) == 0) {
407 this.newGapsCookie_ = 426 this.newGapsCookie_ =
408 headerValue.substring(GAPS_COOKIE.length + 1).split(';')[0]; 427 headerValue.substring(GAPS_COOKIE.length + 1).split(';')[0];
409 } 428 }
410 } 429 }
(...skipping 26 matching lines...) Expand all
437 }; 456 };
438 457
439 /** 458 /**
440 * Handler for webView.request.onBeforeSendHeaders . 459 * Handler for webView.request.onBeforeSendHeaders .
441 * @return {!Object} Modified request headers. 460 * @return {!Object} Modified request headers.
442 * @private 461 * @private
443 */ 462 */
444 Authenticator.prototype.onBeforeSendHeaders_ = function(details) { 463 Authenticator.prototype.onBeforeSendHeaders_ = function(details) {
445 // We should re-send cookie if first request was unsuccessful (i.e. no new 464 // We should re-send cookie if first request was unsuccessful (i.e. no new
446 // GAPS cookie was received). 465 // GAPS cookie was received).
447 if (this.isNewGaiaFlowChromeOS && this.gapsCookie_ && 466 if (this.isNewGaiaFlow && this.gapsCookie_ &&
448 (!this.gapsCookieSent_ || !this.newGapsCookie_)) { 467 (!this.gapsCookieSent_ || !this.newGapsCookie_)) {
449 var headers = details.requestHeaders; 468 var headers = details.requestHeaders;
450 var found = false; 469 var found = false;
451 var gapsCookie = this.gapsCookie_; 470 var gapsCookie = this.gapsCookie_;
452 471
453 for (var i = 0, l = headers.length; i < l; ++i) { 472 for (var i = 0, l = headers.length; i < l; ++i) {
454 if (headers[i].name == COOKIE_HEADER) { 473 if (headers[i].name == COOKIE_HEADER) {
455 headers[i].value = this.updateCookieValue_(headers[i].value, 474 headers[i].value = this.updateCookieValue_(headers[i].value,
456 GAPS_COOKIE, gapsCookie); 475 GAPS_COOKIE, gapsCookie);
457 found = true; 476 found = true;
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 this.webview_.contentWindow.postMessage(msg, this.idpOrigin_); 754 this.webview_.contentWindow.postMessage(msg, this.idpOrigin_);
736 }).bind(this), EAFE_INITIAL_MESSAGE_DELAY_IN_MS); 755 }).bind(this), EAFE_INITIAL_MESSAGE_DELAY_IN_MS);
737 } 756 }
738 }; 757 };
739 758
740 /** 759 /**
741 * Invoked when the webview navigates withing the current document. 760 * Invoked when the webview navigates withing the current document.
742 * @private 761 * @private
743 */ 762 */
744 Authenticator.prototype.onLoadCommit_ = function(e) { 763 Authenticator.prototype.onLoadCommit_ = function(e) {
745 if (this.oauthCode_) { 764 if (this.oauthCode_)
746 this.skipForNow_ = true;
747 this.maybeCompleteAuth_(); 765 this.maybeCompleteAuth_();
748 }
749 }; 766 };
750 767
751 /** 768 /**
752 * Returns |true| if event |e| was sent from the hosted webview. 769 * Returns |true| if event |e| was sent from the hosted webview.
753 * @private 770 * @private
754 */ 771 */
755 Authenticator.prototype.isWebviewEvent_ = function(e) { 772 Authenticator.prototype.isWebviewEvent_ = function(e) {
756 // Note: <webview> prints error message to console if |contentWindow| is not 773 // Note: <webview> prints error message to console if |contentWindow| is not
757 // defined. 774 // defined.
758 // TODO(dzhioev): remove the message. http://crbug.com/469522 775 // TODO(dzhioev): remove the message. http://crbug.com/469522
(...skipping 17 matching lines...) Expand all
776 Authenticator.AuthMode = AuthMode; 793 Authenticator.AuthMode = AuthMode;
777 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; 794 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS;
778 795
779 return { 796 return {
780 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old 797 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old
781 // iframe-based flow is deprecated. 798 // iframe-based flow is deprecated.
782 GaiaAuthHost: Authenticator, 799 GaiaAuthHost: Authenticator,
783 Authenticator: Authenticator 800 Authenticator: Authenticator
784 }; 801 };
785 }); 802 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698