Chromium Code Reviews| Index: chrome/browser/resources/gaia_auth_host/authenticator.js |
| diff --git a/chrome/browser/resources/gaia_auth_host/authenticator.js b/chrome/browser/resources/gaia_auth_host/authenticator.js |
| index 87f9c386141b030847f1b6e221a155830913563b..6409227317564dcf8d46219ff3e0a3f9ee2356e4 100644 |
| --- a/chrome/browser/resources/gaia_auth_host/authenticator.js |
| +++ b/chrome/browser/resources/gaia_auth_host/authenticator.js |
| @@ -2,6 +2,8 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +<include src="saml_handler.js"> |
| + |
| /** |
| * @fileoverview An UI component to authenciate to Chrome. The component hosts |
| * IdP web pages in a webview. A client who is interested in monitoring |
| @@ -9,6 +11,7 @@ |
| * cr.login.GaiaAuthHost.Listener as defined in this file. After initialization, |
| * call {@code load} to start the authentication flow. |
| */ |
| + |
| cr.define('cr.login', function() { |
| 'use strict'; |
| @@ -95,6 +98,16 @@ cr.define('cr.login', function() { |
| this.trusted_ = true; |
| this.oauth_code_ = null; |
| + this.samlHandler_ = new cr.login.SamlHandler(this.webview_); |
| + this.confirmPasswordCallback = null; |
| + this.noPasswordCallback = null; |
| + this.insecureContentBlockedCallback = null; |
| + this.samlApiUsedCallback = null; |
| + this.needPassword = true; |
| + this.samlHandler_.addEventListener( |
| + 'insecureContentBlocked', |
| + this.onInsecureContentBlocked_.bind(this)); |
| + |
| this.webview_.addEventListener('droplink', this.onDropLink_.bind(this)); |
| this.webview_.addEventListener( |
| 'newwindow', this.onNewWindow_.bind(this)); |
| @@ -120,8 +133,6 @@ cr.define('cr.login', function() { |
| 'popstate', this.onPopState_.bind(this), false); |
| } |
| - // TODO(guohui,xiyuan): no need to inherit EventTarget once we deprecate the |
| - // old event-based signin flow. |
| Authenticator.prototype = Object.create(cr.EventTarget.prototype); |
| /** |
| @@ -141,6 +152,11 @@ cr.define('cr.login', function() { |
| this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); |
| this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; |
| this.authFlow_ = AuthFlow.DEFAULT; |
| + this.samlHandler_.reset(); |
| + // Don't block insecure content for desktop flow because it lands on |
| + // http. Otherwise, block insecure content as long as gaia is https. |
| + this.samlHandler_.blockInsecureContent = authMode != AuthMode.DESKTOP && |
| + this.idpOrigin_.indexOf('https://') == 0; |
| this.webview_.src = this.reloadUrl_; |
| @@ -153,6 +169,7 @@ cr.define('cr.login', function() { |
| Authenticator.prototype.reload = function() { |
| this.webview_.src = this.reloadUrl_; |
| this.authFlow_ = AuthFlow.DEFAULT; |
| + this.samlHandler_.reset(); |
| this.loaded_ = false; |
| }; |
| @@ -190,7 +207,7 @@ cr.define('cr.login', function() { |
| if (currentUrl.indexOf('ntp=1') >= 0) |
| this.skipForNow_ = true; |
| - this.onAuthCompleted_(); |
| + this.maybeCompleteAuth_(); |
| return; |
| } |
| @@ -215,7 +232,6 @@ cr.define('cr.login', function() { |
| } |
| this.updateHistoryState_(currentUrl); |
| - |
| }; |
| /** |
| @@ -306,6 +322,11 @@ cr.define('cr.login', function() { |
| return; |
| } |
| + // Gaia messages must be an object with 'method' property. |
| + if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) { |
| + return; |
| + } |
| + |
| var msg = e.data; |
| if (msg.method == 'attemptLogin') { |
| this.email_ = msg.email; |
| @@ -315,6 +336,62 @@ cr.define('cr.login', function() { |
| }; |
| /** |
| + * Invoked by the hosting page to verify the Saml password. |
| + */ |
| + Authenticator.prototype.verifyConfirmedPassword = function(password) { |
| + if (!this.samlHandler_.verifyConfirmedPassword(password)) { |
| + // Invoke confirm password callback asynchronously because the |
| + // verification was based on messages and caller (GaiaSigninScreen) |
| + // does not expect it to be called immediately. |
| + // TODO(xiyuan): Change to synchronous call when iframe based code |
| + // is removed. |
| + var invokeConfirmPassword = (function() { |
| + this.confirmPasswordCallback(this.samlHandler_.scrapedPasswordCount); |
| + }).bind(this); |
| + window.setTimeout(invokeConfirmPassword, 0); |
| + return; |
| + } |
| + |
| + this.password_ = password; |
| + this.onAuthCompleted_(); |
| + }; |
| + |
| + /** |
| + * Check Saml flow and start password confirmation flow if needed. Otherwise, |
| + * continue with auto completion. |
| + * @private |
| + */ |
| + Authenticator.prototype.maybeCompleteAuth_ = function() { |
| + if (this.authFlow_ != AuthFlow.SAML) { |
| + this.onAuthCompleted_(); |
| + return; |
| + } |
| + |
| + if (this.samlHandler_.samlApiUsed) { |
| + if (this.samlApiUsedCallback) { |
| + this.samlApiUsedCallback(); |
| + } |
| + this.password_ = this.samlHandler_.apiPasswordBytes; |
| + } else if (this.samlHandler_.scrapedPasswordCount == 0) { |
| + if (this.noPasswordCallback) { |
| + this.noPasswordCallback(this.email_); |
| + } else { |
| + console.error('Authenticator: No password scraped for SAML.'); |
| + return; |
| + } |
| + } else if (this.needPassword) { |
| + if (this.confirmPasswordCallback) { |
| + // Confirm scraped password. The flow follows in |
| + // verifyConfirmedPassword. |
| + this.confirmPasswordCallback(this.samlHandler_.scrapedPasswordCount); |
| + return; |
| + } |
| + } |
| + |
| + this.onAuthCompleted_(); |
| + }; |
| + |
| + /** |
| * Invoked to process authentication completion. |
| * @private |
| */ |
| @@ -339,6 +416,18 @@ cr.define('cr.login', function() { |
| }; |
| /** |
| + * Invoked when |samlHandler_| fires 'insecureContentBlocked' event. |
| + * @private |
| + */ |
| + Authenticator.prototype.onInsecureContentBlocked_ = function(e) { |
| + if (this.insecureContentBlockedCallback) { |
| + this.insecureContentBlockedCallback(e.details.url); |
| + } else { |
| + console.error('Authenticator: Insecure content blocked.'); |
| + } |
| + }; |
| + |
| + /** |
| * Invoked when a link is dropped on the webview. |
| * @private |
| */ |
| @@ -390,7 +479,7 @@ cr.define('cr.login', function() { |
| // TODO(rsorokin): Investigate whether this breaks SAML. |
|
Dmitry Polukhin
2015/03/13 11:56:19
nit, it seems this todo can be removed now.
xiyuan
2015/03/17 22:00:15
Done.
|
| if (this.oauth_code_) { |
| this.skipForNow_ = true; |
| - this.onAuthCompleted_(); |
| + this.maybeCompleteAuth_(); |
| } |
| }; |