| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/webui/chromeos/insession_password_change_handler_chromeos.h" |
| |
| #include <string> |
| |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/values.h" |
| #include "chrome/browser/chromeos/login/auth/chrome_cryptohome_authenticator.h" |
| #include "chrome/browser/chromeos/login/saml/saml_password_expiry_notification.h" |
| #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" |
| #include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/pref_names.h" |
| #include "chromeos/constants/chromeos_switches.h" |
| #include "chromeos/login/auth/saml_password_attributes.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/user_manager/user_manager.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| std::string GetPasswordChangeUrl(Profile* profile) { |
| if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kSamlPasswordChangeUrl)) { |
| return base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| switches::kSamlPasswordChangeUrl); |
| } |
| |
| const policy::UserCloudPolicyManagerChromeOS* user_cloud_policy_manager = |
| policy::UserPolicyManagerFactoryChromeOS::GetCloudPolicyManagerForProfile( |
| profile); |
| if (user_cloud_policy_manager) { |
| const enterprise_management::PolicyData* policy = |
| user_cloud_policy_manager->core()->store()->policy(); |
| if (policy->has_change_password_uri()) { |
| return policy->change_password_uri(); |
| } |
| } |
| |
| return SamlPasswordAttributes::LoadFromPrefs(profile->GetPrefs()) |
| .password_change_url(); |
| } |
| |
| } // namespace |
| |
| InSessionPasswordChangeHandler::InSessionPasswordChangeHandler() = default; |
| InSessionPasswordChangeHandler::~InSessionPasswordChangeHandler() = default; |
| |
| void InSessionPasswordChangeHandler::HandleInitialize( |
| const base::ListValue* value) { |
| Profile* profile = Profile::FromWebUI(web_ui()); |
| CHECK(profile->GetPrefs()->GetBoolean( |
| prefs::kSamlInSessionPasswordChangeEnabled)); |
| |
| AllowJavascript(); |
| base::Value params(base::Value::Type::DICTIONARY); |
| const std::string password_change_url = GetPasswordChangeUrl(profile); |
| if (password_change_url.empty()) { |
| LOG(ERROR) << "Password change url is empty"; |
| return; |
| } |
| params.SetKey("passwordChangeUrl", base::Value(password_change_url)); |
| const user_manager::User* user = |
| ProfileHelper::Get()->GetUserByProfile(profile); |
| if (user) |
| params.SetKey("userName", base::Value(user->GetDisplayEmail())); |
| CallJavascriptFunction("insession.password.change.loadAuthExtension", params); |
| } |
| |
| void InSessionPasswordChangeHandler::HandleChangePassword( |
| const base::ListValue* params) { |
| const base::Value& old_passwords = params->GetList()[0]; |
| const base::Value& new_passwords = params->GetList()[1]; |
| VLOG(4) << "Scraped " << old_passwords.GetList().size() << " old passwords"; |
| VLOG(4) << "Scraped " << new_passwords.GetList().size() << " new passwords"; |
| user_manager::User* user = |
| ProfileHelper::Get()->GetUserByProfile(Profile::FromWebUI(web_ui())); |
| user_manager::UserManager::Get()->SaveForceOnlineSignin(user->GetAccountId(), |
| true); |
| if (new_passwords.GetList().size() == 1 && |
| old_passwords.GetList().size() > 0) { |
| UserContext user_context(*user); |
| user_context.SetKey(Key(new_passwords.GetList()[0].GetString())); |
| authenticator_ = new ChromeCryptohomeAuthenticator(this); |
| authenticator_->MigrateKey(user_context, |
| old_passwords.GetList()[0].GetString()); |
| } |
| } |
| |
| void InSessionPasswordChangeHandler::RegisterMessages() { |
| web_ui()->RegisterMessageCallback( |
| "initialize", |
| base::BindRepeating(&InSessionPasswordChangeHandler::HandleInitialize, |
| weak_factory_.GetWeakPtr())); |
| web_ui()->RegisterMessageCallback( |
| "changePassword", |
| base::BindRepeating(&InSessionPasswordChangeHandler::HandleChangePassword, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| void InSessionPasswordChangeHandler::OnAuthSuccess( |
| const UserContext& user_context) { |
| VLOG(3) << "Cryptohome password is changed."; |
| user_manager::UserManager::Get()->SaveForceOnlineSignin( |
| user_context.GetAccountId(), false); |
| authenticator_.reset(); |
| |
| // Clear expiration time from prefs so that we don't keep nagging the user to |
| // change password (until the SAML provider tells us a new expiration time). |
| Profile* profile = Profile::FromWebUI(web_ui()); |
| SamlPasswordAttributes loaded = |
| SamlPasswordAttributes::LoadFromPrefs(profile->GetPrefs()); |
| SamlPasswordAttributes( |
| /*modified_time=*/base::Time::Now(), /*expiration_time=*/base::Time(), |
| loaded.password_change_url()) |
| .SaveToPrefs(profile->GetPrefs()); |
| DismissSamlPasswordExpiryNotification(profile); |
| } |
| |
| void InSessionPasswordChangeHandler::OnAuthFailure(const AuthFailure& error) { |
| // TODO(rsorokin): Ask user for the old password |
| VLOG(1) << "Failed to change cryptohome password: " << error.GetErrorString(); |
| authenticator_.reset(); |
| } |
| |
| } // namespace chromeos |