Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 | 211 |
| 212 this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); | 212 this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); |
| 213 this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; | 213 this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; |
| 214 // Don't block insecure content for desktop flow because it lands on | 214 // Don't block insecure content for desktop flow because it lands on |
| 215 // http. Otherwise, block insecure content as long as gaia is https. | 215 // http. Otherwise, block insecure content as long as gaia is https. |
| 216 this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP && | 216 this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP && |
| 217 this.idpOrigin_.indexOf('https://') == 0; | 217 this.idpOrigin_.indexOf('https://') == 0; |
| 218 this.needPassword = !('needPassword' in data) || data.needPassword; | 218 this.needPassword = !('needPassword' in data) || data.needPassword; |
| 219 | 219 |
| 220 if (this.isNewGaiaFlowChromeOS) { | 220 if (this.isNewGaiaFlow) { |
| 221 this.webview_.contextMenus.onShow.addListener(function(e) { | 221 this.webview_.contextMenus.onShow.addListener(function(e) { |
| 222 e.preventDefault(); | 222 e.preventDefault(); |
| 223 }); | 223 }); |
| 224 | 224 |
| 225 if (!this.onBeforeSetHeadersSet_) { | 225 if (!this.onBeforeSetHeadersSet_) { |
| 226 this.onBeforeSetHeadersSet_ = true; | 226 this.onBeforeSetHeadersSet_ = true; |
| 227 var filterPrefix = this.idpOrigin_ + EMBEDDED_SETUP_CHROMEOS_ENDPOINT; | 227 var filterPrefix = this.idpOrigin_ + EMBEDDED_SETUP_CHROMEOS_ENDPOINT; |
| 228 // This depends on gaiaUrl parameter, that is why it is here. | 228 // This depends on gaiaUrl parameter, that is why it is here. |
| 229 this.webview_.request.onBeforeSendHeaders.addListener( | 229 this.webview_.request.onBeforeSendHeaders.addListener( |
| 230 this.onBeforeSendHeaders_.bind(this), | 230 this.onBeforeSendHeaders_.bind(this), |
| 231 {urls: [filterPrefix + '?*', filterPrefix + '/*']}, | 231 {urls: [filterPrefix + '?*', filterPrefix + '/*']}, |
| 232 ['requestHeaders', 'blocking']); | 232 ['requestHeaders', 'blocking']); |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 this.webview_.src = this.reloadUrl_; | 236 this.webview_.src = this.reloadUrl_; |
| 237 }; | 237 }; |
| 238 | 238 |
| 239 /** | 239 /** |
| 240 * Reloads the authenticator component. | 240 * Reloads the authenticator component. |
| 241 */ | 241 */ |
| 242 Authenticator.prototype.reload = function() { | 242 Authenticator.prototype.reload = function() { |
| 243 this.clearCredentials_(); | 243 this.clearCredentials_(); |
| 244 this.webview_.src = this.reloadUrl_; | 244 this.webview_.src = this.reloadUrl_; |
| 245 }; | 245 }; |
| 246 | 246 |
| 247 Authenticator.prototype.constructInitialFrameUrl_ = function(data) { | 247 Authenticator.prototype.constructInitialFrameUrl_ = function(data) { |
| 248 var path = data.gaiaPath; | 248 var path = data.gaiaPath; |
| 249 if (!path && this.isNewGaiaFlowChromeOS) | 249 if (!path && this.isNewGaiaFlow) |
| 250 path = EMBEDDED_SETUP_CHROMEOS_ENDPOINT; | 250 path = EMBEDDED_SETUP_CHROMEOS_ENDPOINT; |
| 251 if (!path) | 251 if (!path) |
| 252 path = IDP_PATH; | 252 path = IDP_PATH; |
| 253 var url = this.idpOrigin_ + path; | 253 var url = this.idpOrigin_ + path; |
| 254 | 254 |
| 255 if (this.isNewGaiaFlowChromeOS) { | 255 if (this.isNewGaiaFlow) { |
| 256 if (data.chromeType) | 256 if (data.chromeType) |
| 257 url = appendParam(url, 'chrometype', data.chromeType); | 257 url = appendParam(url, 'chrometype', data.chromeType); |
| 258 if (data.clientId) | 258 if (data.clientId) |
| 259 url = appendParam(url, 'client_id', data.clientId); | 259 url = appendParam(url, 'client_id', data.clientId); |
| 260 if (data.enterpriseDomain) | 260 if (data.enterpriseDomain) |
| 261 url = appendParam(url, 'manageddomain', data.enterpriseDomain); | 261 url = appendParam(url, 'manageddomain', data.enterpriseDomain); |
| 262 if (data.clientVersion) | 262 if (data.clientVersion) |
| 263 url = appendParam(url, 'client_version', data.clientVersion); | 263 url = appendParam(url, 'client_version', data.clientVersion); |
| 264 if (data.platformVersion) | 264 if (data.platformVersion) |
| 265 url = appendParam(url, 'platform_version', data.platformVersion); | 265 url = appendParam(url, 'platform_version', data.platformVersion); |
| 266 if (data.releaseChannel) | 266 if (data.releaseChannel) |
| 267 url = appendParam(url, 'release_channel', data.releaseChannel); | 267 url = appendParam(url, 'release_channel', data.releaseChannel); |
| 268 if (data.endpointGen) | 268 if (data.endpointGen) |
| 269 url = appendParam(url, 'endpoint_gen', data.endpointGen); | 269 url = appendParam(url, 'endpoint_gen', data.endpointGen); |
| 270 } else { | 270 } else { |
| 271 url = appendParam(url, 'continue', this.continueUrl_); | 271 url = appendParam(url, 'continue', this.continueUrl_); |
| 272 url = appendParam(url, 'service', data.service || SERVICE_ID); | 272 url = appendParam(url, 'service', data.service || SERVICE_ID); |
| 273 } | 273 } |
| 274 if (data.hl) | 274 if (data.hl) |
| 275 url = appendParam(url, 'hl', data.hl); | 275 url = appendParam(url, 'hl', data.hl); |
| 276 if (data.gaiaId) | 276 if (data.gaiaId) |
| 277 url = appendParam(url, 'user_id', data.gaiaId); | 277 url = appendParam(url, 'user_id', data.gaiaId); |
| 278 if (data.email) | 278 if (data.email) { |
| 279 url = appendParam(url, 'Email', data.email); | 279 if (data.readOnlyEmail) { |
|
achuithb
2015/09/28 21:51:37
Is a comment explaining readOnlyEmails appropriate
Roger Tawa OOO till Jul 10th
2015/10/02 01:16:31
Done.
| |
| 280 url = appendParam(url, 'Email', data.email); | |
| 281 } else { | |
| 282 url = appendParam(url, 'email_hint', data.email); | |
| 283 } | |
| 284 } | |
| 280 if (this.isConstrainedWindow_) | 285 if (this.isConstrainedWindow_) |
| 281 url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE); | 286 url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE); |
| 282 if (data.flow) | 287 if (data.flow) |
| 283 url = appendParam(url, 'flow', data.flow); | 288 url = appendParam(url, 'flow', data.flow); |
| 284 if (data.emailDomain) | 289 if (data.emailDomain) |
| 285 url = appendParam(url, 'emaildomain', data.emailDomain); | 290 url = appendParam(url, 'emaildomain', data.emailDomain); |
| 286 return url; | 291 return url; |
| 287 }; | 292 }; |
| 288 | 293 |
| 289 /** | 294 /** |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 384 // Removes "" around. | 389 // Removes "" around. |
| 385 this.email_ = signinDetails['email'].slice(1, -1); | 390 this.email_ = signinDetails['email'].slice(1, -1); |
| 386 this.gaiaId_ = signinDetails['obfuscatedid'].slice(1, -1); | 391 this.gaiaId_ = signinDetails['obfuscatedid'].slice(1, -1); |
| 387 this.sessionIndex_ = signinDetails['sessionindex']; | 392 this.sessionIndex_ = signinDetails['sessionindex']; |
| 388 } else if (headerName == LOCATION_HEADER) { | 393 } else if (headerName == LOCATION_HEADER) { |
| 389 // If the "choose what to sync" checkbox was clicked, then the continue | 394 // If the "choose what to sync" checkbox was clicked, then the continue |
| 390 // URL will contain a source=3 field. | 395 // URL will contain a source=3 field. |
| 391 var location = decodeURIComponent(header.value); | 396 var location = decodeURIComponent(header.value); |
| 392 this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/); | 397 this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/); |
| 393 } else if ( | 398 } else if ( |
| 394 this.isNewGaiaFlowChromeOS && headerName == SET_COOKIE_HEADER) { | 399 this.isNewGaiaFlow && headerName == SET_COOKIE_HEADER) { |
| 395 var headerValue = header.value; | 400 var headerValue = header.value; |
| 396 if (headerValue.indexOf(OAUTH_CODE_COOKIE + '=', 0) == 0) { | 401 if (headerValue.indexOf(OAUTH_CODE_COOKIE + '=', 0) == 0) { |
| 397 this.oauthCode_ = | 402 this.oauthCode_ = |
| 398 headerValue.substring(OAUTH_CODE_COOKIE.length + 1).split(';')[0]; | 403 headerValue.substring(OAUTH_CODE_COOKIE.length + 1).split(';')[0]; |
| 399 } | 404 } |
| 400 if (headerValue.indexOf(GAPS_COOKIE + '=', 0) == 0) { | 405 if (headerValue.indexOf(GAPS_COOKIE + '=', 0) == 0) { |
| 401 this.newGapsCookie_ = | 406 this.newGapsCookie_ = |
| 402 headerValue.substring(GAPS_COOKIE.length + 1).split(';')[0]; | 407 headerValue.substring(GAPS_COOKIE.length + 1).split(';')[0]; |
| 403 } | 408 } |
| 404 } | 409 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 431 }; | 436 }; |
| 432 | 437 |
| 433 /** | 438 /** |
| 434 * Handler for webView.request.onBeforeSendHeaders . | 439 * Handler for webView.request.onBeforeSendHeaders . |
| 435 * @return {!Object} Modified request headers. | 440 * @return {!Object} Modified request headers. |
| 436 * @private | 441 * @private |
| 437 */ | 442 */ |
| 438 Authenticator.prototype.onBeforeSendHeaders_ = function(details) { | 443 Authenticator.prototype.onBeforeSendHeaders_ = function(details) { |
| 439 // We should re-send cookie if first request was unsuccessful (i.e. no new | 444 // We should re-send cookie if first request was unsuccessful (i.e. no new |
| 440 // GAPS cookie was received). | 445 // GAPS cookie was received). |
| 441 if (this.isNewGaiaFlowChromeOS && this.gapsCookie_ && | 446 if (this.isNewGaiaFlow && this.gapsCookie_ && |
| 442 (!this.gapsCookieSent_ || !this.newGapsCookie_)) { | 447 (!this.gapsCookieSent_ || !this.newGapsCookie_)) { |
| 443 var headers = details.requestHeaders; | 448 var headers = details.requestHeaders; |
| 444 var found = false; | 449 var found = false; |
| 445 var gapsCookie = this.gapsCookie_; | 450 var gapsCookie = this.gapsCookie_; |
| 446 | 451 |
| 447 for (var i = 0, l = headers.length; i < l; ++i) { | 452 for (var i = 0, l = headers.length; i < l; ++i) { |
| 448 if (headers[i].name == COOKIE_HEADER) { | 453 if (headers[i].name == COOKIE_HEADER) { |
| 449 headers[i].value = this.updateCookieValue_(headers[i].value, | 454 headers[i].value = this.updateCookieValue_(headers[i].value, |
| 450 GAPS_COOKIE, gapsCookie); | 455 GAPS_COOKIE, gapsCookie); |
| 451 found = true; | 456 found = true; |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 729 this.webview_.contentWindow.postMessage(msg, this.idpOrigin_); | 734 this.webview_.contentWindow.postMessage(msg, this.idpOrigin_); |
| 730 }).bind(this), EAFE_INITIAL_MESSAGE_DELAY_IN_MS); | 735 }).bind(this), EAFE_INITIAL_MESSAGE_DELAY_IN_MS); |
| 731 } | 736 } |
| 732 }; | 737 }; |
| 733 | 738 |
| 734 /** | 739 /** |
| 735 * Invoked when the webview navigates withing the current document. | 740 * Invoked when the webview navigates withing the current document. |
| 736 * @private | 741 * @private |
| 737 */ | 742 */ |
| 738 Authenticator.prototype.onLoadCommit_ = function(e) { | 743 Authenticator.prototype.onLoadCommit_ = function(e) { |
| 739 if (this.oauthCode_) { | 744 if (this.oauthCode_) |
| 740 this.skipForNow_ = true; | |
| 741 this.maybeCompleteAuth_(); | 745 this.maybeCompleteAuth_(); |
| 742 } | |
| 743 }; | 746 }; |
| 744 | 747 |
| 745 /** | 748 /** |
| 746 * Returns |true| if event |e| was sent from the hosted webview. | 749 * Returns |true| if event |e| was sent from the hosted webview. |
| 747 * @private | 750 * @private |
| 748 */ | 751 */ |
| 749 Authenticator.prototype.isWebviewEvent_ = function(e) { | 752 Authenticator.prototype.isWebviewEvent_ = function(e) { |
| 750 // Note: <webview> prints error message to console if |contentWindow| is not | 753 // Note: <webview> prints error message to console if |contentWindow| is not |
| 751 // defined. | 754 // defined. |
| 752 // TODO(dzhioev): remove the message. http://crbug.com/469522 | 755 // TODO(dzhioev): remove the message. http://crbug.com/469522 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 770 Authenticator.AuthMode = AuthMode; | 773 Authenticator.AuthMode = AuthMode; |
| 771 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; | 774 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; |
| 772 | 775 |
| 773 return { | 776 return { |
| 774 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old | 777 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old |
| 775 // iframe-based flow is deprecated. | 778 // iframe-based flow is deprecated. |
| 776 GaiaAuthHost: Authenticator, | 779 GaiaAuthHost: Authenticator, |
| 777 Authenticator: Authenticator | 780 Authenticator: Authenticator |
| 778 }; | 781 }; |
| 779 }); | 782 }); |
| OLD | NEW |