| 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 13 matching lines...) Expand all Loading... |
| 24 'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/success.html'; | 24 'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/success.html'; |
| 25 var SIGN_IN_HEADER = 'google-accounts-signin'; | 25 var SIGN_IN_HEADER = 'google-accounts-signin'; |
| 26 var EMBEDDED_FORM_HEADER = 'google-accounts-embedded'; | 26 var EMBEDDED_FORM_HEADER = 'google-accounts-embedded'; |
| 27 var LOCATION_HEADER = 'location'; | 27 var LOCATION_HEADER = 'location'; |
| 28 var COOKIE_HEADER = 'cookie'; | 28 var COOKIE_HEADER = 'cookie'; |
| 29 var SET_COOKIE_HEADER = 'set-cookie'; | 29 var SET_COOKIE_HEADER = 'set-cookie'; |
| 30 var OAUTH_CODE_COOKIE = 'oauth_code'; | 30 var OAUTH_CODE_COOKIE = 'oauth_code'; |
| 31 var GAPS_COOKIE = 'GAPS'; | 31 var GAPS_COOKIE = 'GAPS'; |
| 32 var SERVICE_ID = 'chromeoslogin'; | 32 var SERVICE_ID = 'chromeoslogin'; |
| 33 var EMBEDDED_SETUP_CHROMEOS_ENDPOINT = 'embedded/setup/chromeos'; | 33 var EMBEDDED_SETUP_CHROMEOS_ENDPOINT = 'embedded/setup/chromeos'; |
| 34 var SAML_REDIRECTION_PATH = 'samlredirect'; |
| 34 | 35 |
| 35 /** | 36 /** |
| 36 * The source URL parameter for the constrained signin flow. | 37 * The source URL parameter for the constrained signin flow. |
| 37 */ | 38 */ |
| 38 var CONSTRAINED_FLOW_SOURCE = 'chrome'; | 39 var CONSTRAINED_FLOW_SOURCE = 'chrome'; |
| 39 | 40 |
| 40 /** | 41 /** |
| 41 * Enum for the authorization mode, must match AuthMode defined in | 42 * Enum for the authorization mode, must match AuthMode defined in |
| 42 * chrome/browser/ui/webui/inline_login_ui.cc. | 43 * chrome/browser/ui/webui/inline_login_ui.cc. |
| 43 * @enum {number} | 44 * @enum {number} |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 this.idpOrigin_ = null; | 132 this.idpOrigin_ = null; |
| 132 this.continueUrl_ = null; | 133 this.continueUrl_ = null; |
| 133 this.continueUrlWithoutParams_ = null; | 134 this.continueUrlWithoutParams_ = null; |
| 134 this.initialFrameUrl_ = null; | 135 this.initialFrameUrl_ = null; |
| 135 this.reloadUrl_ = null; | 136 this.reloadUrl_ = null; |
| 136 this.trusted_ = true; | 137 this.trusted_ = true; |
| 137 this.oauthCode_ = null; | 138 this.oauthCode_ = null; |
| 138 this.gapsCookie_ = null; | 139 this.gapsCookie_ = null; |
| 139 this.gapsCookieSent_ = false; | 140 this.gapsCookieSent_ = false; |
| 140 this.newGapsCookie_ = null; | 141 this.newGapsCookie_ = null; |
| 142 this.readyFired_ = false; |
| 141 | 143 |
| 142 this.useEafe_ = false; | 144 this.useEafe_ = false; |
| 143 this.clientId_ = null; | 145 this.clientId_ = null; |
| 144 | 146 |
| 145 this.samlHandler_ = new cr.login.SamlHandler(this.webview_); | 147 this.samlHandler_ = new cr.login.SamlHandler(this.webview_); |
| 146 this.confirmPasswordCallback = null; | 148 this.confirmPasswordCallback = null; |
| 147 this.noPasswordCallback = null; | 149 this.noPasswordCallback = null; |
| 148 this.insecureContentBlockedCallback = null; | 150 this.insecureContentBlockedCallback = null; |
| 149 this.samlApiUsedCallback = null; | 151 this.samlApiUsedCallback = null; |
| 150 this.missingGaiaInfoCallback = null; | 152 this.missingGaiaInfoCallback = null; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 window.addEventListener( | 184 window.addEventListener( |
| 183 'popstate', this.onPopState_.bind(this), false); | 185 'popstate', this.onPopState_.bind(this), false); |
| 184 } | 186 } |
| 185 | 187 |
| 186 Authenticator.prototype = Object.create(cr.EventTarget.prototype); | 188 Authenticator.prototype = Object.create(cr.EventTarget.prototype); |
| 187 | 189 |
| 188 /** | 190 /** |
| 189 * Reinitializes authentication parameters so that a failed login attempt | 191 * Reinitializes authentication parameters so that a failed login attempt |
| 190 * would not result in an infinite loop. | 192 * would not result in an infinite loop. |
| 191 */ | 193 */ |
| 192 Authenticator.prototype.clearCredentials_ = function() { | 194 Authenticator.prototype.resetStates_ = function() { |
| 193 this.email_ = null; | 195 this.email_ = null; |
| 194 this.gaiaId_ = null; | 196 this.gaiaId_ = null; |
| 195 this.password_ = null; | 197 this.password_ = null; |
| 196 this.oauthCode_ = null; | 198 this.oauthCode_ = null; |
| 197 this.gapsCookie_ = null; | 199 this.gapsCookie_ = null; |
| 198 this.gapsCookieSent_ = false; | 200 this.gapsCookieSent_ = false; |
| 199 this.newGapsCookie_ = null; | 201 this.newGapsCookie_ = null; |
| 202 this.readyFired_ = false; |
| 200 this.chooseWhatToSync_ = false; | 203 this.chooseWhatToSync_ = false; |
| 201 this.skipForNow_ = false; | 204 this.skipForNow_ = false; |
| 202 this.sessionIndex_ = null; | 205 this.sessionIndex_ = null; |
| 203 this.trusted_ = true; | 206 this.trusted_ = true; |
| 204 this.authFlow = AuthFlow.DEFAULT; | 207 this.authFlow = AuthFlow.DEFAULT; |
| 205 this.samlHandler_.reset(); | 208 this.samlHandler_.reset(); |
| 206 }; | 209 }; |
| 207 | 210 |
| 208 /** | 211 /** |
| 209 * Loads the authenticator component with the given parameters. | 212 * Loads the authenticator component with the given parameters. |
| 210 * @param {AuthMode} authMode Authorization mode. | 213 * @param {AuthMode} authMode Authorization mode. |
| 211 * @param {Object} data Parameters for the authorization flow. | 214 * @param {Object} data Parameters for the authorization flow. |
| 212 */ | 215 */ |
| 213 Authenticator.prototype.load = function(authMode, data) { | 216 Authenticator.prototype.load = function(authMode, data) { |
| 214 this.authMode = authMode; | 217 this.authMode = authMode; |
| 215 this.clearCredentials_(); | 218 this.resetStates_(); |
| 216 // gaiaUrl parameter is used for testing. Once defined, it is never changed. | 219 // gaiaUrl parameter is used for testing. Once defined, it is never changed. |
| 217 this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN; | 220 this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN; |
| 218 this.continueUrl_ = data.continueUrl || CONTINUE_URL; | 221 this.continueUrl_ = data.continueUrl || CONTINUE_URL; |
| 219 this.continueUrlWithoutParams_ = | 222 this.continueUrlWithoutParams_ = |
| 220 this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) || | 223 this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) || |
| 221 this.continueUrl_; | 224 this.continueUrl_; |
| 222 this.isConstrainedWindow_ = data.constrained == '1'; | 225 this.isConstrainedWindow_ = data.constrained == '1'; |
| 223 this.isNewGaiaFlow = data.isNewGaiaFlow; | 226 this.isNewGaiaFlow = data.isNewGaiaFlow; |
| 224 this.useEafe_ = data.useEafe || false; | 227 this.useEafe_ = data.useEafe || false; |
| 225 this.clientId_ = data.clientId; | 228 this.clientId_ = data.clientId; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 252 } | 255 } |
| 253 } | 256 } |
| 254 | 257 |
| 255 this.webview_.src = this.reloadUrl_; | 258 this.webview_.src = this.reloadUrl_; |
| 256 }; | 259 }; |
| 257 | 260 |
| 258 /** | 261 /** |
| 259 * Reloads the authenticator component. | 262 * Reloads the authenticator component. |
| 260 */ | 263 */ |
| 261 Authenticator.prototype.reload = function() { | 264 Authenticator.prototype.reload = function() { |
| 262 this.clearCredentials_(); | 265 this.resetStates_(); |
| 263 this.webview_.src = this.reloadUrl_; | 266 this.webview_.src = this.reloadUrl_; |
| 264 }; | 267 }; |
| 265 | 268 |
| 266 Authenticator.prototype.constructInitialFrameUrl_ = function(data) { | 269 Authenticator.prototype.constructInitialFrameUrl_ = function(data) { |
| 270 if (data.doSamlRedirect) { |
| 271 var url = this.idpOrigin_ + SAML_REDIRECTION_PATH; |
| 272 url = appendParam(url, 'domain', data.enterpriseDomain); |
| 273 url = appendParam(url, 'continue', data.gaiaUrl + |
| 274 'o/oauth2/programmatic_auth?hl=' + data.hl + |
| 275 '&scope=https%3A%2F%2Fwww.google.com%2Faccounts%2FOAuthLogin&' + |
| 276 'client_id=' + encodeURIComponent(data.clientId) + |
| 277 '&access_type=offline'); |
| 278 |
| 279 return url; |
| 280 } |
| 281 |
| 267 var path = data.gaiaPath; | 282 var path = data.gaiaPath; |
| 268 if (!path && this.isNewGaiaFlow) | 283 if (!path && this.isNewGaiaFlow) |
| 269 path = EMBEDDED_SETUP_CHROMEOS_ENDPOINT; | 284 path = EMBEDDED_SETUP_CHROMEOS_ENDPOINT; |
| 270 if (!path) | 285 if (!path) |
| 271 path = IDP_PATH; | 286 path = IDP_PATH; |
| 272 var url = this.idpOrigin_ + path; | 287 var url = this.idpOrigin_ + path; |
| 273 | 288 |
| 274 if (this.isNewGaiaFlow) { | 289 if (this.isNewGaiaFlow) { |
| 275 if (data.chromeType) | 290 if (data.chromeType) |
| 276 url = appendParam(url, 'chrometype', data.chromeType); | 291 url = appendParam(url, 'chrometype', data.chromeType); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 304 if (this.isConstrainedWindow_) | 319 if (this.isConstrainedWindow_) |
| 305 url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE); | 320 url = appendParam(url, 'source', CONSTRAINED_FLOW_SOURCE); |
| 306 if (data.flow) | 321 if (data.flow) |
| 307 url = appendParam(url, 'flow', data.flow); | 322 url = appendParam(url, 'flow', data.flow); |
| 308 if (data.emailDomain) | 323 if (data.emailDomain) |
| 309 url = appendParam(url, 'emaildomain', data.emailDomain); | 324 url = appendParam(url, 'emaildomain', data.emailDomain); |
| 310 return url; | 325 return url; |
| 311 }; | 326 }; |
| 312 | 327 |
| 313 /** | 328 /** |
| 329 * Dispatches the 'ready' event if it hasn't been dispatched already for the |
| 330 * current content. |
| 331 * @private |
| 332 */ |
| 333 Authenticator.prototype.fireReadyEvent_ = function() { |
| 334 if (!this.readyFired_) { |
| 335 this.dispatchEvent(new Event('ready')); |
| 336 this.readyFired_ = true; |
| 337 } |
| 338 }; |
| 339 |
| 340 /** |
| 314 * Invoked when a main frame request in the webview has completed. | 341 * Invoked when a main frame request in the webview has completed. |
| 315 * @private | 342 * @private |
| 316 */ | 343 */ |
| 317 Authenticator.prototype.onRequestCompleted_ = function(details) { | 344 Authenticator.prototype.onRequestCompleted_ = function(details) { |
| 318 var currentUrl = details.url; | 345 var currentUrl = details.url; |
| 319 | 346 |
| 320 if (!this.isNewGaiaFlow && | 347 if (!this.isNewGaiaFlow && |
| 321 currentUrl.lastIndexOf(this.continueUrlWithoutParams_, 0) == 0) { | 348 currentUrl.lastIndexOf(this.continueUrlWithoutParams_, 0) == 0) { |
| 322 if (currentUrl.indexOf('ntp=1') >= 0) | 349 if (currentUrl.indexOf('ntp=1') >= 0) |
| 323 this.skipForNow_ = true; | 350 this.skipForNow_ = true; |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 password: this.password_ || '', | 679 password: this.password_ || '', |
| 653 authCode: this.oauthCode_, | 680 authCode: this.oauthCode_, |
| 654 usingSAML: this.authFlow == AuthFlow.SAML, | 681 usingSAML: this.authFlow == AuthFlow.SAML, |
| 655 chooseWhatToSync: this.chooseWhatToSync_, | 682 chooseWhatToSync: this.chooseWhatToSync_, |
| 656 skipForNow: this.skipForNow_, | 683 skipForNow: this.skipForNow_, |
| 657 sessionIndex: this.sessionIndex_ || '', | 684 sessionIndex: this.sessionIndex_ || '', |
| 658 trusted: this.trusted_, | 685 trusted: this.trusted_, |
| 659 gapsCookie: this.newGapsCookie_ || this.gapsCookie_ || '', | 686 gapsCookie: this.newGapsCookie_ || this.gapsCookie_ || '', |
| 660 } | 687 } |
| 661 })); | 688 })); |
| 662 this.clearCredentials_(); | 689 this.resetStates_(); |
| 663 }; | 690 }; |
| 664 | 691 |
| 665 /** | 692 /** |
| 666 * Invoked when |samlHandler_| fires 'insecureContentBlocked' event. | 693 * Invoked when |samlHandler_| fires 'insecureContentBlocked' event. |
| 667 * @private | 694 * @private |
| 668 */ | 695 */ |
| 669 Authenticator.prototype.onInsecureContentBlocked_ = function(e) { | 696 Authenticator.prototype.onInsecureContentBlocked_ = function(e) { |
| 670 if (this.insecureContentBlockedCallback) { | 697 if (this.insecureContentBlockedCallback) { |
| 671 this.insecureContentBlockedCallback(e.detail.url); | 698 this.insecureContentBlockedCallback(e.detail.url); |
| 672 } else { | 699 } else { |
| 673 console.error('Authenticator: Insecure content blocked.'); | 700 console.error('Authenticator: Insecure content blocked.'); |
| 674 } | 701 } |
| 675 }; | 702 }; |
| 676 | 703 |
| 677 /** | 704 /** |
| 678 * Invoked when |samlHandler_| fires 'authPageLoaded' event. | 705 * Invoked when |samlHandler_| fires 'authPageLoaded' event. |
| 679 * @private | 706 * @private |
| 680 */ | 707 */ |
| 681 Authenticator.prototype.onAuthPageLoaded_ = function(e) { | 708 Authenticator.prototype.onAuthPageLoaded_ = function(e) { |
| 682 if (!e.detail.isSAMLPage) | 709 if (!e.detail.isSAMLPage) |
| 683 return; | 710 return; |
| 684 | 711 |
| 685 this.authDomain = this.samlHandler_.authDomain; | 712 this.authDomain = this.samlHandler_.authDomain; |
| 686 this.authFlow = AuthFlow.SAML; | 713 this.authFlow = AuthFlow.SAML; |
| 714 |
| 715 this.fireReadyEvent_(); |
| 687 }; | 716 }; |
| 688 | 717 |
| 689 /** | 718 /** |
| 690 * Invoked when a link is dropped on the webview. | 719 * Invoked when a link is dropped on the webview. |
| 691 * @private | 720 * @private |
| 692 */ | 721 */ |
| 693 Authenticator.prototype.onDropLink_ = function(e) { | 722 Authenticator.prototype.onDropLink_ = function(e) { |
| 694 this.dispatchEvent(new CustomEvent('dropLink', {detail: e.url})); | 723 this.dispatchEvent(new CustomEvent('dropLink', {detail: e.url})); |
| 695 }; | 724 }; |
| 696 | 725 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 717 | 746 |
| 718 // Posts a message to IdP pages to initiate communication. | 747 // Posts a message to IdP pages to initiate communication. |
| 719 var currentUrl = this.webview_.src; | 748 var currentUrl = this.webview_.src; |
| 720 if (currentUrl.lastIndexOf(this.idpOrigin_) == 0) { | 749 if (currentUrl.lastIndexOf(this.idpOrigin_) == 0) { |
| 721 var msg = { | 750 var msg = { |
| 722 'method': 'handshake', | 751 'method': 'handshake', |
| 723 }; | 752 }; |
| 724 | 753 |
| 725 this.webview_.contentWindow.postMessage(msg, currentUrl); | 754 this.webview_.contentWindow.postMessage(msg, currentUrl); |
| 726 | 755 |
| 727 this.dispatchEvent(new Event('ready')); | 756 this.fireReadyEvent_(); |
| 728 // Focus webview after dispatching event when webview is already visible. | 757 // Focus webview after dispatching event when webview is already visible. |
| 729 this.webview_.focus(); | 758 this.webview_.focus(); |
| 730 } | 759 } |
| 731 }; | 760 }; |
| 732 | 761 |
| 733 /** | 762 /** |
| 734 * Invoked when the webview fails loading a page. | 763 * Invoked when the webview fails loading a page. |
| 735 * @private | 764 * @private |
| 736 */ | 765 */ |
| 737 Authenticator.prototype.onLoadAbort_ = function(e) { | 766 Authenticator.prototype.onLoadAbort_ = function(e) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 Authenticator.AuthMode = AuthMode; | 827 Authenticator.AuthMode = AuthMode; |
| 799 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; | 828 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; |
| 800 | 829 |
| 801 return { | 830 return { |
| 802 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old | 831 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old |
| 803 // iframe-based flow is deprecated. | 832 // iframe-based flow is deprecated. |
| 804 GaiaAuthHost: Authenticator, | 833 GaiaAuthHost: Authenticator, |
| 805 Authenticator: Authenticator | 834 Authenticator: Authenticator |
| 806 }; | 835 }; |
| 807 }); | 836 }); |
| OLD | NEW |