123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- // Copyright 2020 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 "ash/in_session_auth/webauthn_dialog_controller_impl.h"
- #include "ash/in_session_auth/auth_dialog_contents_view.h"
- #include "ash/in_session_auth/webauthn_request_registrar_impl.h"
- #include "ash/public/cpp/in_session_auth_dialog_client.h"
- #include "ash/session/session_controller_impl.h"
- #include "ash/shell.h"
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/strings/string_util.h"
- #include "components/user_manager/known_user.h"
- #include "ui/aura/window.h"
- #include "ui/views/widget/widget.h"
- namespace ash {
- WebAuthNDialogControllerImpl::WebAuthNDialogControllerImpl()
- : webauthn_request_registrar_(
- std::make_unique<WebAuthnRequestRegistrarImpl>()) {}
- WebAuthNDialogControllerImpl::~WebAuthNDialogControllerImpl() = default;
- void WebAuthNDialogControllerImpl::SetClient(
- InSessionAuthDialogClient* client) {
- client_ = client;
- }
- void WebAuthNDialogControllerImpl::ShowAuthenticationDialog(
- aura::Window* source_window,
- const std::string& origin_name,
- FinishCallback finish_callback) {
- DCHECK(client_);
- // Concurrent requests are not supported.
- DCHECK(!dialog_);
- source_window_tracker_.Add(source_window);
- finish_callback_ = std::move(finish_callback);
- AccountId account_id =
- Shell::Get()->session_controller()->GetActiveAccountId();
- // GAIA password option is not offered.
- uint32_t auth_methods = AuthDialogContentsView::kAuthPassword;
- if (client_->IsFingerprintAuthAvailable(account_id)) {
- client_->StartFingerprintAuthSession(
- account_id,
- base::BindOnce(
- &WebAuthNDialogControllerImpl::OnStartFingerprintAuthSession,
- weak_factory_.GetWeakPtr(), account_id, auth_methods, source_window,
- origin_name));
- // OnStartFingerprintAuthSession checks PIN availability.
- return;
- }
- client_->CheckPinAuthAvailability(
- account_id,
- base::BindOnce(&WebAuthNDialogControllerImpl::OnPinCanAuthenticate,
- weak_factory_.GetWeakPtr(), auth_methods, source_window,
- origin_name));
- }
- void WebAuthNDialogControllerImpl::OnStartFingerprintAuthSession(
- AccountId account_id,
- uint32_t auth_methods,
- aura::Window* source_window,
- const std::string& origin_name,
- bool success) {
- if (success)
- auth_methods |= AuthDialogContentsView::kAuthFingerprint;
- client_->CheckPinAuthAvailability(
- account_id,
- base::BindOnce(&WebAuthNDialogControllerImpl::OnPinCanAuthenticate,
- weak_factory_.GetWeakPtr(), auth_methods, source_window,
- origin_name));
- }
- void WebAuthNDialogControllerImpl::OnPinCanAuthenticate(
- uint32_t auth_methods,
- aura::Window* source_window,
- const std::string& origin_name,
- bool pin_auth_available) {
- if (pin_auth_available)
- auth_methods |= AuthDialogContentsView::kAuthPin;
- if (auth_methods == 0) {
- // If neither fingerprint nor PIN is available, we shouldn't receive the
- // request.
- LOG(ERROR) << "Neither fingerprint nor PIN is available.";
- Cancel();
- return;
- }
- if (!source_window_tracker_.Contains(source_window)) {
- LOG(ERROR) << "Source window is no longer available.";
- Cancel();
- return;
- }
- Shell* shell = Shell::Get();
- AccountId account_id = shell->session_controller()->GetActiveAccountId();
- const UserSession* session =
- shell->session_controller()->GetUserSessionByAccountId(account_id);
- DCHECK(session);
- UserAvatar avatar = session->user_info.avatar;
- // TODO(b/156258540): move UserSelectionScreen::BuildAshUserAvatarForUser to
- // somewhere that UserToUserSession could call, to support animated avatars.
- AuthDialogContentsView::AuthMethodsMetadata auth_metadata;
- auth_metadata.autosubmit_pin_length =
- user_manager::KnownUser(shell->local_state())
- .GetUserPinLength(account_id);
- source_window_tracker_.Remove(source_window);
- dialog_ = std::make_unique<InSessionAuthDialog>(
- auth_methods, source_window, origin_name, auth_metadata, avatar);
- }
- void WebAuthNDialogControllerImpl::DestroyAuthenticationDialog() {
- DCHECK(client_);
- if (!dialog_)
- return;
- if (dialog_->GetAuthMethods() & AuthDialogContentsView::kAuthFingerprint)
- client_->EndFingerprintAuthSession();
- dialog_.reset();
- source_window_tracker_.RemoveAll();
- }
- void WebAuthNDialogControllerImpl::AuthenticateUserWithPasswordOrPin(
- const std::string& password,
- bool authenticated_by_pin,
- OnAuthenticateCallback callback) {
- DCHECK(client_);
- // TODO(b/156258540): Check that PIN is enabled / set up for this user.
- if (authenticated_by_pin &&
- !base::ContainsOnlyChars(password, "0123456789")) {
- OnAuthenticateComplete(std::move(callback), false);
- return;
- }
- client_->AuthenticateUserWithPasswordOrPin(
- password, authenticated_by_pin,
- base::BindOnce(&WebAuthNDialogControllerImpl::OnAuthenticateComplete,
- weak_factory_.GetWeakPtr(), std::move(callback)));
- }
- void WebAuthNDialogControllerImpl::AuthenticateUserWithFingerprint(
- base::OnceCallback<void(bool, FingerprintState)> views_callback) {
- DCHECK(client_);
- client_->AuthenticateUserWithFingerprint(
- base::BindOnce(&WebAuthNDialogControllerImpl::OnFingerprintAuthComplete,
- weak_factory_.GetWeakPtr(), std::move(views_callback)));
- }
- void WebAuthNDialogControllerImpl::OnAuthenticateComplete(
- OnAuthenticateCallback callback,
- bool success) {
- if (success) {
- std::move(callback).Run(/*success=*/true, /*can_use_pin=*/true);
- OnAuthSuccess();
- return;
- }
- // PIN might be locked out after an unsuccessful authentication, check if it's
- // still available so the UI can be updated.
- AccountId account_id =
- Shell::Get()->session_controller()->GetActiveAccountId();
- client_->CheckPinAuthAvailability(
- account_id, base::BindOnce(std::move(callback), /*success=*/false));
- }
- void WebAuthNDialogControllerImpl::OnFingerprintAuthComplete(
- base::OnceCallback<void(bool, FingerprintState)> views_callback,
- bool success,
- FingerprintState fingerprint_state) {
- // If success is false and retry is allowed, the view will start another
- // fingerprint check.
- std::move(views_callback).Run(success, fingerprint_state);
- if (success)
- OnAuthSuccess();
- }
- void WebAuthNDialogControllerImpl::OnAuthSuccess() {
- DestroyAuthenticationDialog();
- if (finish_callback_)
- std::move(finish_callback_).Run(true);
- }
- void WebAuthNDialogControllerImpl::Cancel() {
- DestroyAuthenticationDialog();
- if (finish_callback_)
- std::move(finish_callback_).Run(false);
- }
- void WebAuthNDialogControllerImpl::OpenInSessionAuthHelpPage() {
- DCHECK(client_);
- client_->OpenInSessionAuthHelpPage();
- }
- void WebAuthNDialogControllerImpl::CheckAvailability(
- FinishCallback on_availability_checked) const {
- // Assumes the requests are for the active user (no teleported window).
- AccountId account_id =
- Shell::Get()->session_controller()->GetActiveAccountId();
- if (client_->IsFingerprintAuthAvailable(account_id)) {
- std::move(on_availability_checked).Run(true);
- return;
- }
- client_->CheckPinAuthAvailability(account_id,
- std::move(on_availability_checked));
- }
- } // namespace ash
|