[High5] Allow offline login using PIN
When the user has only a pin factor, allow the user to use pin to login offline. Screenshot: https://screenshot.googleplex.com/7g9yggSd9WsZjms Bug: b:370865046 Change-Id: I64f2560244bfc199a836901c24a8a965a4d7f852 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5936977 Reviewed-by: Denis Kuznetsov <antrim@chromium.org> Commit-Queue: Yunke Zhou <yunkez@google.com> Reviewed-by: Hardik Goyal <hardikgoyal@chromium.org> Reviewed-by: Maksim Ivanov <emaxx@chromium.org> Cr-Commit-Position: refs/heads/main@{#1373331}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
b0c5660c96
commit
1fcc8c122d
chrome
@ -1895,12 +1895,18 @@
|
||||
<message name="IDS_OFFLINE_LOGIN_PASSWORD" desc="Password field text on the offline login screen. Note: should be the same as the one used on the Gaia sign-in page.">
|
||||
Enter your password
|
||||
</message>
|
||||
<message name="IDS_OFFLINE_LOGIN_PIN" desc="PIN field placeholder text on the offline login screen.">
|
||||
Enter your PIN
|
||||
</message>
|
||||
<message name="IDS_OFFLINE_LOGIN_INVALID_EMAIL" desc="Alert message about invalid email on the offline login screen. Note: should be the same as the one used on the Gaia sign-in page.">
|
||||
Please enter a valid email address
|
||||
</message>
|
||||
<message name="IDS_OFFLINE_LOGIN_INVALID_PASSWORD" desc="Alert message about mismatching email and password on the device">
|
||||
The email and password you entered don't match
|
||||
</message>
|
||||
<message name="IDS_OFFLINE_LOGIN_INVALID_PIN" desc="Alert message about mismatching email and PIN on the device">
|
||||
The email and PIN you entered don't match
|
||||
</message>
|
||||
<message name="IDS_OFFLINE_LOGIN_NEXT_BUTTON_TEXT" desc="Text shown on next button during offline signin flow dialog. Note: should be the same as the one used on the Gaia sign-in page.">
|
||||
Next
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
41ac6cb8edf9b724fdf5ee0bd10f41c6141ebbf5
|
@ -0,0 +1 @@
|
||||
96b12f9ce663a2dc8fc8d73342b064e60a0ace85
|
@ -21,6 +21,7 @@
|
||||
#include "chrome/browser/ui/webui/ash/login/offline_login_screen_handler.h"
|
||||
#include "chrome/grit/branded_strings.h"
|
||||
#include "chrome/grit/generated_resources.h"
|
||||
#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
|
||||
#include "chromeos/ash/components/login/auth/public/auth_types.h"
|
||||
#include "chromeos/ash/components/login/auth/public/key.h"
|
||||
#include "chromeos/ash/components/login/auth/public/user_context.h"
|
||||
@ -77,6 +78,7 @@ std::string OfflineLoginScreen::GetResultString(Result result) {
|
||||
OfflineLoginScreen::OfflineLoginScreen(base::WeakPtr<OfflineLoginView> view,
|
||||
const ScreenExitCallback& exit_callback)
|
||||
: BaseScreen(OfflineLoginView::kScreenId, OobeScreenPriority::DEFAULT),
|
||||
auth_factor_editor_(UserDataAuthClient::Get()),
|
||||
view_(std::move(view)),
|
||||
exit_callback_(exit_callback) {
|
||||
network_state_informer_ = base::MakeRefCounted<NetworkStateInformer>();
|
||||
@ -112,6 +114,7 @@ void OfflineLoginScreen::ShowImpl() {
|
||||
void OfflineLoginScreen::HideImpl() {
|
||||
scoped_observer_.reset();
|
||||
idle_detector_.reset();
|
||||
authenticate_by_pin_ = false;
|
||||
if (view_)
|
||||
view_->Hide();
|
||||
}
|
||||
@ -155,11 +158,13 @@ void OfflineLoginScreen::HandleCompleteAuth(const std::string& email,
|
||||
|
||||
UserContext user_context(*user);
|
||||
user_context.SetKey(Key(password));
|
||||
user_context.SetLocalPasswordInput(LocalPasswordInput{password});
|
||||
// Save the user's plaintext password for possible authentication to a
|
||||
// network. See https://crbug.com/386606 for details.
|
||||
user_context.SetPasswordKey(Key(password));
|
||||
user_context.SetIsUsingPin(false);
|
||||
if (!authenticate_by_pin_) {
|
||||
user_context.SetLocalPasswordInput(LocalPasswordInput{password});
|
||||
// Save the user's plaintext password for possible authentication to a
|
||||
// network. See https://crbug.com/386606 for details.
|
||||
user_context.SetPasswordKey(Key(password));
|
||||
}
|
||||
user_context.SetIsUsingPin(authenticate_by_pin_);
|
||||
CHECK(account_id.GetAccountType() != AccountType::ACTIVE_DIRECTORY)
|
||||
<< "Incorrect Active Directory user type " << user_context.GetUserType();
|
||||
user_context.SetIsUsingOAuth(false);
|
||||
@ -205,12 +210,31 @@ void OfflineLoginScreen::HandleEmailSubmitted(const std::string& email) {
|
||||
user_manager::UserManager::Get()->FindUser(account_id);
|
||||
if (user && user->force_online_signin()) {
|
||||
RecordEvent(OfflineLoginEvent::kOfflineLoginBlockedByInvalidToken);
|
||||
view_->ShowPasswordPage();
|
||||
view_->ShowOnlineRequiredDialog();
|
||||
return;
|
||||
}
|
||||
|
||||
auth_factor_editor_.GetAuthFactorsConfiguration(
|
||||
std::make_unique<UserContext>(*user),
|
||||
base::BindOnce(&OfflineLoginScreen::OnGetAuthFactorsConfiguration,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void OfflineLoginScreen::OnGetAuthFactorsConfiguration(
|
||||
std::unique_ptr<UserContext> user_context,
|
||||
std::optional<AuthenticationError> error) {
|
||||
if (error.has_value()) {
|
||||
LOG(ERROR) << "Failed to get auth factors configuration, code "
|
||||
<< error->get_cryptohome_error();
|
||||
} else {
|
||||
const auto& config = user_context->GetAuthFactorsConfiguration();
|
||||
// Allow authentication by PIN if that is the user's only auth factor.
|
||||
authenticate_by_pin_ =
|
||||
!config.HasConfiguredFactor(cryptohome::AuthFactorType::kPassword) &&
|
||||
config.HasConfiguredFactor(cryptohome::AuthFactorType::kPin);
|
||||
}
|
||||
RecordEvent(OfflineLoginEvent::kOfflineLoginEnabled);
|
||||
view_->ShowPasswordPage();
|
||||
view_->ShowPasswordPage(authenticate_by_pin_);
|
||||
}
|
||||
|
||||
void OfflineLoginScreen::StartIdleDetection() {
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "base/scoped_observation.h"
|
||||
#include "chrome/browser/ash/login/screens/base_screen.h"
|
||||
#include "chrome/browser/ui/webui/ash/login/network_state_informer.h"
|
||||
#include "chromeos/ash/components/login/auth/auth_factor_editor.h"
|
||||
#include "chromeos/ash/experiences/idle_detector/idle_detector.h"
|
||||
|
||||
namespace ash {
|
||||
@ -56,8 +57,20 @@ class OfflineLoginScreen
|
||||
const std::string& password);
|
||||
void HandleEmailSubmitted(const std::string& username);
|
||||
|
||||
void OnGetAuthFactorsConfiguration(std::unique_ptr<UserContext> user_context,
|
||||
std::optional<AuthenticationError> error);
|
||||
|
||||
// The editor is used to call `ListAuthFactors` to fetch password & pin factor
|
||||
// status. It does not change factor status.
|
||||
// TODO: Update `Authenticator` to allow AuthSession to start earlier so we
|
||||
// could get auth factor status from the AuthSession.
|
||||
AuthFactorEditor auth_factor_editor_;
|
||||
|
||||
base::WeakPtr<OfflineLoginView> view_;
|
||||
|
||||
// Whether the user has only pin factor and should be authenticated by pin.
|
||||
bool authenticate_by_pin_ = false;
|
||||
|
||||
// True when network is available.
|
||||
bool is_network_available_ = false;
|
||||
|
||||
|
@ -238,9 +238,10 @@ found in the LICENSE file.
|
||||
</div>
|
||||
<cr-input id="passwordInput" value="{{password}}"
|
||||
on-keydown="onKeyDown" disabled="[[disabled]]"
|
||||
type="password" required error-message="[[i18nDynamic(
|
||||
locale, 'offlineLoginInvalidPassword')]]"
|
||||
placeholder="[[i18nDynamic(locale, 'offlineLoginPassword')]]">
|
||||
type="password" required
|
||||
error-message="[[passwordErrorText(locale, authenticateByPin)]]"
|
||||
placeholder=
|
||||
"[[passwordPlaceholderText(locale,authenticateByPin)]]">
|
||||
</cr-input>
|
||||
<div class="layout horizontal-reverse">
|
||||
<gaia-button on-click="onForgotPasswordClicked" link
|
||||
|
@ -101,6 +101,14 @@ export class OfflineLogin extends OfflineLoginBase {
|
||||
value: '',
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the user should be authenticated by pin or password.
|
||||
*/
|
||||
authenticateByPin: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
|
||||
/**
|
||||
* Proper e-mail with domain, displayed on password page.
|
||||
*/
|
||||
@ -127,6 +135,7 @@ export class OfflineLogin extends OfflineLoginBase {
|
||||
private displayDomain: string;
|
||||
private email: string;
|
||||
private password: string;
|
||||
private authenticateByPin: boolean;
|
||||
private fullEmail: string;
|
||||
private activeSection: string;
|
||||
private animationInProgress: boolean;
|
||||
@ -197,6 +206,7 @@ export class OfflineLogin extends OfflineLoginBase {
|
||||
this.manager = '';
|
||||
this.email = '';
|
||||
this.fullEmail = '';
|
||||
this.authenticateByPin = false;
|
||||
this.shadowRoot!.querySelector<CrInputElement>('#emailInput')!.invalid =
|
||||
false;
|
||||
this.shadowRoot!.querySelector<CrInputElement>('#passwordInput')!.invalid =
|
||||
@ -204,7 +214,8 @@ export class OfflineLogin extends OfflineLoginBase {
|
||||
this.activeSection = LoginSection.EMAIL;
|
||||
}
|
||||
|
||||
proceedToPasswordPage(): void {
|
||||
proceedToPasswordPage(authenticateByPin: boolean): void {
|
||||
this.authenticateByPin = authenticateByPin;
|
||||
this.switchToPasswordCard(true /* animated */);
|
||||
}
|
||||
|
||||
@ -343,6 +354,19 @@ export class OfflineLogin extends OfflineLoginBase {
|
||||
}
|
||||
this.onNextButtonClicked();
|
||||
}
|
||||
|
||||
private passwordPlaceholderText(locale: string, authenticateByPin: boolean):
|
||||
string {
|
||||
const key = authenticateByPin ? 'offlineLoginPin' : 'offlineLoginPassword';
|
||||
return this.i18nDynamic(locale, key);
|
||||
}
|
||||
|
||||
private passwordErrorText(locale: string, authenticateByPin: boolean):
|
||||
string {
|
||||
const key = authenticateByPin ? 'offlineLoginInvalidPin' :
|
||||
'offlineLoginInvalidPassword';
|
||||
return this.i18nDynamic(locale, key);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
@ -21,9 +21,11 @@ void OfflineLoginScreenHandler::DeclareLocalizedValues(
|
||||
::login::LocalizedValuesBuilder* builder) {
|
||||
builder->Add("offlineLoginEmail", IDS_OFFLINE_LOGIN_EMAIL);
|
||||
builder->Add("offlineLoginPassword", IDS_OFFLINE_LOGIN_PASSWORD);
|
||||
builder->Add("offlineLoginPin", IDS_OFFLINE_LOGIN_PIN);
|
||||
builder->Add("offlineLoginInvalidEmail", IDS_OFFLINE_LOGIN_INVALID_EMAIL);
|
||||
builder->Add("offlineLoginInvalidPassword",
|
||||
IDS_OFFLINE_LOGIN_INVALID_PASSWORD);
|
||||
builder->Add("offlineLoginInvalidPin", IDS_OFFLINE_LOGIN_INVALID_PIN);
|
||||
builder->Add("offlineLoginNextBtn", IDS_OFFLINE_LOGIN_NEXT_BUTTON_TEXT);
|
||||
builder->Add("offlineLoginForgotPasswordBtn",
|
||||
IDS_OFFLINE_LOGIN_FORGOT_PASSWORD_BUTTON_TEXT);
|
||||
@ -47,8 +49,8 @@ void OfflineLoginScreenHandler::Reset() {
|
||||
CallExternalAPI("reset");
|
||||
}
|
||||
|
||||
void OfflineLoginScreenHandler::ShowPasswordPage() {
|
||||
CallExternalAPI("proceedToPasswordPage");
|
||||
void OfflineLoginScreenHandler::ShowPasswordPage(bool authenticate_by_pin) {
|
||||
CallExternalAPI("proceedToPasswordPage", authenticate_by_pin);
|
||||
}
|
||||
|
||||
void OfflineLoginScreenHandler::ShowOnlineRequiredDialog() {
|
||||
|
@ -29,7 +29,7 @@ class OfflineLoginView {
|
||||
virtual void Reset() = 0;
|
||||
|
||||
// Proceeds to the password input dialog.
|
||||
virtual void ShowPasswordPage() = 0;
|
||||
virtual void ShowPasswordPage(bool authenticate_by_pin) = 0;
|
||||
|
||||
// Shows error pop-up when the user cannot login offline.
|
||||
virtual void ShowOnlineRequiredDialog() = 0;
|
||||
@ -60,7 +60,7 @@ class OfflineLoginScreenHandler final : public BaseScreenHandler,
|
||||
void Show(base::Value::Dict params) override;
|
||||
void Hide() override;
|
||||
void Reset() override;
|
||||
void ShowPasswordPage() override;
|
||||
void ShowPasswordPage(bool authenticate_by_pin) override;
|
||||
void ShowOnlineRequiredDialog() override;
|
||||
void ShowPasswordMismatchMessage() override;
|
||||
base::WeakPtr<OfflineLoginView> AsWeakPtr() override;
|
||||
|
Reference in New Issue
Block a user