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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
69 'gaiaPath', // Gaia path to use without a leading slash. | 69 'gaiaPath', // Gaia path to use without a leading slash. |
70 'hl', // Language code for the user interface. | 70 'hl', // Language code for the user interface. |
71 'email', // Pre-fill the email field in Gaia UI. | 71 'email', // Pre-fill the email field in Gaia UI. |
72 'service', // Name of Gaia service. | 72 'service', // Name of Gaia service. |
73 'continueUrl', // Continue url to use. | 73 'continueUrl', // Continue url to use. |
74 'frameUrl', // Initial frame URL to use. If empty defaults to | 74 'frameUrl', // Initial frame URL to use. If empty defaults to |
75 // gaiaUrl. | 75 // gaiaUrl. |
76 'constrained', // Whether the extension is loaded in a constrained | 76 'constrained', // Whether the extension is loaded in a constrained |
77 // window. | 77 // window. |
78 'clientId', // Chrome client id. | 78 'clientId', // Chrome client id. |
79 'useEafe', // Whether to use EAFE. | |
79 'needPassword', // Whether the host is interested in getting a password. | 80 'needPassword', // Whether the host is interested in getting a password. |
80 // If this set to |false|, |confirmPasswordCallback| is | 81 // If this set to |false|, |confirmPasswordCallback| is |
81 // not called before dispatching |authCopleted|. | 82 // not called before dispatching |authCopleted|. |
82 // Default is |true|. | 83 // Default is |true|. |
83 'flow', // One of 'default', 'enterprise', or 'theftprotection'. | 84 'flow', // One of 'default', 'enterprise', or 'theftprotection'. |
84 'enterpriseDomain', // Domain in which hosting device is (or should be) | 85 'enterpriseDomain', // Domain in which hosting device is (or should be) |
85 // enrolled. | 86 // enrolled. |
86 'emailDomain', // Value used to prefill domain for email. | 87 'emailDomain', // Value used to prefill domain for email. |
87 'deviceId', // User device ID (sync Id). | 88 'deviceId', // User device ID (sync Id). |
88 'sessionIsEphemeral', // User session would be ephemeral. | 89 'sessionIsEphemeral', // User session would be ephemeral. |
(...skipping 22 matching lines...) Expand all Loading... | |
111 this.continueUrl_ = null; | 112 this.continueUrl_ = null; |
112 this.continueUrlWithoutParams_ = null; | 113 this.continueUrlWithoutParams_ = null; |
113 this.initialFrameUrl_ = null; | 114 this.initialFrameUrl_ = null; |
114 this.reloadUrl_ = null; | 115 this.reloadUrl_ = null; |
115 this.trusted_ = true; | 116 this.trusted_ = true; |
116 this.oauth_code_ = null; | 117 this.oauth_code_ = null; |
117 this.deviceId_ = null; | 118 this.deviceId_ = null; |
118 this.sessionIsEphemeral_ = null; | 119 this.sessionIsEphemeral_ = null; |
119 this.onBeforeSetHeadersSet_ = false; | 120 this.onBeforeSetHeadersSet_ = false; |
120 | 121 |
122 this.useEafe_ = false; | |
123 this.clientId_ = null; | |
124 | |
121 this.samlHandler_ = new cr.login.SamlHandler(this.webview_); | 125 this.samlHandler_ = new cr.login.SamlHandler(this.webview_); |
122 this.confirmPasswordCallback = null; | 126 this.confirmPasswordCallback = null; |
123 this.noPasswordCallback = null; | 127 this.noPasswordCallback = null; |
124 this.insecureContentBlockedCallback = null; | 128 this.insecureContentBlockedCallback = null; |
125 this.samlApiUsedCallback = null; | 129 this.samlApiUsedCallback = null; |
126 this.missingGaiaInfoCallback = null; | 130 this.missingGaiaInfoCallback = null; |
127 this.needPassword = true; | 131 this.needPassword = true; |
128 this.samlHandler_.addEventListener( | 132 this.samlHandler_.addEventListener( |
129 'insecureContentBlocked', | 133 'insecureContentBlocked', |
130 this.onInsecureContentBlocked_.bind(this)); | 134 this.onInsecureContentBlocked_.bind(this)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 */ | 190 */ |
187 Authenticator.prototype.load = function(authMode, data) { | 191 Authenticator.prototype.load = function(authMode, data) { |
188 this.clearCredentials_(); | 192 this.clearCredentials_(); |
189 this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN; | 193 this.idpOrigin_ = data.gaiaUrl || IDP_ORIGIN; |
190 this.continueUrl_ = data.continueUrl || CONTINUE_URL; | 194 this.continueUrl_ = data.continueUrl || CONTINUE_URL; |
191 this.continueUrlWithoutParams_ = | 195 this.continueUrlWithoutParams_ = |
192 this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) || | 196 this.continueUrl_.substring(0, this.continueUrl_.indexOf('?')) || |
193 this.continueUrl_; | 197 this.continueUrl_; |
194 this.isConstrainedWindow_ = data.constrained == '1'; | 198 this.isConstrainedWindow_ = data.constrained == '1'; |
195 this.isNewGaiaFlowChromeOS = data.isNewGaiaFlowChromeOS; | 199 this.isNewGaiaFlowChromeOS = data.isNewGaiaFlowChromeOS; |
200 this.useEafe_ = data.useEafe || false; | |
201 this.clientId_ = data.clientId; | |
196 | 202 |
197 this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); | 203 this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); |
198 this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; | 204 this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; |
199 // Don't block insecure content for desktop flow because it lands on | 205 // Don't block insecure content for desktop flow because it lands on |
200 // http. Otherwise, block insecure content as long as gaia is https. | 206 // http. Otherwise, block insecure content as long as gaia is https. |
201 this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP && | 207 this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP && |
202 this.idpOrigin_.indexOf('https://') == 0; | 208 this.idpOrigin_.indexOf('https://') == 0; |
203 this.needPassword = !('needPassword' in data) || data.needPassword; | 209 this.needPassword = !('needPassword' in data) || data.needPassword; |
204 | 210 |
205 if (this.isNewGaiaFlowChromeOS) { | 211 if (this.isNewGaiaFlowChromeOS) { |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 */ | 431 */ |
426 Authenticator.prototype.onMessageFromWebview_ = function(e) { | 432 Authenticator.prototype.onMessageFromWebview_ = function(e) { |
427 if (!this.isWebviewEvent_(e)) | 433 if (!this.isWebviewEvent_(e)) |
428 return; | 434 return; |
429 | 435 |
430 // The event origin does not have a trailing slash. | 436 // The event origin does not have a trailing slash. |
431 if (e.origin != this.idpOrigin_.substring(0, this.idpOrigin_.length - 1)) { | 437 if (e.origin != this.idpOrigin_.substring(0, this.idpOrigin_.length - 1)) { |
432 return; | 438 return; |
433 } | 439 } |
434 | 440 |
441 // EAFE passes back auth code via message. | |
442 if (this.useEafe_ && | |
443 typeof e.data == 'object' && | |
444 e.data.hasOwnProperty('authorizationCode')) { | |
445 assert(!this.oauth_code_); | |
446 this.oauth_code_ = e.data.authorizationCode; | |
447 this.dispatchEvent( | |
448 new CustomEvent('authCompleted', | |
449 { | |
450 detail: { | |
451 authCodeOnly: true, | |
452 authCode: this.oauth_code_ | |
453 } | |
454 })); | |
455 return; | |
456 } | |
457 | |
435 // Gaia messages must be an object with 'method' property. | 458 // Gaia messages must be an object with 'method' property. |
436 if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) { | 459 if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) { |
437 return; | 460 return; |
438 } | 461 } |
439 | 462 |
440 var msg = e.data; | 463 var msg = e.data; |
441 if (msg.method == 'attemptLogin') { | 464 if (msg.method == 'attemptLogin') { |
442 this.email_ = msg.email; | 465 this.email_ = msg.email; |
443 this.password_ = msg.password; | 466 this.password_ = msg.password; |
444 this.chooseWhatToSync_ = msg.chooseWhatToSync; | 467 this.chooseWhatToSync_ = msg.chooseWhatToSync; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
623 * Invoked when the webview finishes loading a page. | 646 * Invoked when the webview finishes loading a page. |
624 * @private | 647 * @private |
625 */ | 648 */ |
626 Authenticator.prototype.onLoadStop_ = function(e) { | 649 Authenticator.prototype.onLoadStop_ = function(e) { |
627 if (!this.loaded_) { | 650 if (!this.loaded_) { |
628 this.loaded_ = true; | 651 this.loaded_ = true; |
629 this.dispatchEvent(new Event('ready')); | 652 this.dispatchEvent(new Event('ready')); |
630 // Focus webview after dispatching event when webview is already visible. | 653 // Focus webview after dispatching event when webview is already visible. |
631 this.webview_.focus(); | 654 this.webview_.focus(); |
632 } | 655 } |
656 | |
657 // Sends client id to EAFE on every loadstop after a small timeout. This is | |
658 // needed because EAFE sits behind SSO and initialize asynchrounouly | |
659 // and we don't know for sure when it is loaded and ready to listen | |
660 // for message. The postMessage is guarded by EAFE's origin. | |
661 if (this.useEafe_) { | |
662 window.setTimeout((function() { | |
Nikita (slow)
2015/04/23 21:14:02
nit: I suppose you can drop window here.
xiyuan
2015/04/23 21:30:48
Both styles (w/ or w/o window) are used in chromiu
| |
663 var msg = { | |
664 'clientId': this.clientId_ | |
665 }; | |
666 this.webview_.contentWindow.postMessage(msg, this.idpOrigin_); | |
667 }).bind(this), 500); | |
Nikita (slow)
2015/04/23 21:14:01
nit: extract constant.
Are you sure that 500 ms is
xiyuan
2015/04/23 21:30:48
Constact extracted and added comment.
500ms is an
| |
668 } | |
633 }; | 669 }; |
634 | 670 |
635 /** | 671 /** |
636 * Invoked when the webview navigates withing the current document. | 672 * Invoked when the webview navigates withing the current document. |
637 * @private | 673 * @private |
638 */ | 674 */ |
639 Authenticator.prototype.onLoadCommit_ = function(e) { | 675 Authenticator.prototype.onLoadCommit_ = function(e) { |
640 if (this.oauth_code_) { | 676 if (this.oauth_code_) { |
641 this.skipForNow_ = true; | 677 this.skipForNow_ = true; |
642 this.maybeCompleteAuth_(); | 678 this.maybeCompleteAuth_(); |
(...skipping 28 matching lines...) Expand all Loading... | |
671 Authenticator.AuthMode = AuthMode; | 707 Authenticator.AuthMode = AuthMode; |
672 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; | 708 Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS; |
673 | 709 |
674 return { | 710 return { |
675 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old | 711 // TODO(guohui, xiyuan): Rename GaiaAuthHost to Authenticator once the old |
676 // iframe-based flow is deprecated. | 712 // iframe-based flow is deprecated. |
677 GaiaAuthHost: Authenticator, | 713 GaiaAuthHost: Authenticator, |
678 Authenticator: Authenticator | 714 Authenticator: Authenticator |
679 }; | 715 }; |
680 }); | 716 }); |
OLD | NEW |