// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/components/in_session_auth/in_session_auth.h"
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/auth/active_session_auth_controller.h"
#include "ash/public/cpp/in_session_auth_dialog_controller.h"
#include "ash/public/cpp/session/session_controller.h"
#include "base/functional/overloaded.h"
#include "base/notreached.h"
#include "chromeos/ash/components/osauth/impl/request/password_manager_auth_request.h"
#include "chromeos/ash/components/osauth/impl/request/settings_auth_request.h"
#include "chromeos/ash/components/osauth/impl/request/webauthn_auth_request.h"
#include "chromeos/ash/components/osauth/public/auth_session_storage.h"
#include "chromeos/ash/components/osauth/public/request/auth_request.h"
namespace chromeos::auth {
using AuthReason = std::variant<ash::InSessionAuthDialogController::Reason,
ash::AuthRequest::Reason>;
AuthReason ToAshReason(chromeos::auth::mojom::Reason reason) {
switch (reason) {
case chromeos::auth::mojom::Reason::kAccessPasswordManager:
// In theory, execution shouldn't reach this case because this
// implementation of the `chromeos::auth::mojom::InSessionAuth` should
// only be reachable from ash.
return ash::features::IsUseAuthPanelInSessionEnabled()
? AuthReason{ash::AuthRequest::Reason::kPasswordManager}
: AuthReason{ash::InSessionAuthDialogController::
kAccessPasswordManager};
case chromeos::auth::mojom::Reason::kAccessAuthenticationSettings:
return ash::features::IsUseAuthPanelInSessionEnabled()
? AuthReason{ash::AuthRequest::Reason::kSettings}
: AuthReason{ash::InSessionAuthDialogController::
kAccessAuthenticationSettings};
case chromeos::auth::mojom::Reason::kAccessMultideviceSettings:
return ash::InSessionAuthDialogController::kAccessMultideviceSettings;
}
}
InSessionAuth::InSessionAuth() {}
InSessionAuth::~InSessionAuth() = default;
void InSessionAuth::BindReceiver(
mojo::PendingReceiver<chromeos::auth::mojom::InSessionAuth> receiver) {
receivers_.Add(this, std::move(receiver));
}
std::unique_ptr<ash::AuthRequest> InSessionAuth::AuthRequestFromReason(
ash::AuthRequest::Reason reason,
RequestTokenCallback callback) {
switch (reason) {
case ash::AuthRequest::Reason::kPasswordManager:
return std::make_unique<ash::PasswordManagerAuthRequest>(
base::BindOnce(&InSessionAuth::OnAuthComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
case ash::AuthRequest::Reason::kSettings:
return std::make_unique<ash::SettingsAuthRequest>(
base::BindOnce(&InSessionAuth::OnAuthComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
case ash::AuthRequest::Reason::kWebAuthN:
// WebAuthN authentication requests are not made using this
// mojo method.
NOTREACHED();
}
NOTREACHED();
}
void InSessionAuth::RequestToken(chromeos::auth::mojom::Reason reason,
const std::optional<std::string>& prompt,
RequestTokenCallback callback) {
auto visitor = base::Overloaded(
// Legacy code path
[&](ash::InSessionAuthDialogController::Reason reason) {
ash::InSessionAuthDialogController::Get()->ShowAuthDialog(
reason, prompt,
base::BindOnce(&InSessionAuth::OnAuthComplete,
weak_factory_.GetWeakPtr(), std::move(callback)));
},
// New Code path
[&](ash::AuthRequest::Reason reason) {
ash::ActiveSessionAuthController::Get()->ShowAuthDialog(
AuthRequestFromReason(reason, std::move(callback)));
});
std::visit(visitor, ToAshReason(reason));
}
void InSessionAuth::CheckToken(chromeos::auth::mojom::Reason reason,
const std::string& token,
CheckTokenCallback callback) {
bool token_valid;
token_valid = ash::AuthSessionStorage::Get()->IsValid(token);
std::move(callback).Run(token_valid);
}
void InSessionAuth::InvalidateToken(const std::string& token) {
ash::AuthSessionStorage::Get()->Invalidate(token, base::DoNothing());
}
void InSessionAuth::RequestLegacyWebAuthn(
const std::string& rp_id,
const std::string& window_id,
RequestLegacyWebAuthnCallback callback) {
if (ash::features::IsWebAuthNAuthDialogMergeEnabled()) {
auto webauthn_auth_request =
std::make_unique<ash::WebAuthNAuthRequest>(rp_id, std::move(callback));
ash::ActiveSessionAuthController::Get()->ShowAuthDialog(
std::move(webauthn_auth_request));
return;
}
ash::InSessionAuthDialogController::Get()->ShowLegacyWebAuthnDialog(
rp_id, window_id, std::move(callback));
}
void InSessionAuth::OnAuthComplete(RequestTokenCallback callback,
bool success,
const ash::AuthProofToken& token,
base::TimeDelta timeout) {
std::move(callback).Run(
success ? chromeos::auth::mojom::RequestTokenReply::New(token, timeout)
: nullptr);
}
} // namespace chromeos::auth