[webauthn] Use provider name for MacOS passkeys
Use ASAuthorizationWebBrowserPlatformPublicKeyCredential's providerName to identify the provider of a passkey sourced from a third-party passkey provider on MacOS. Fixed: 392837090 Change-Id: I0a6747c451c813768065cd4f70d13f96a89e2541 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6213993 Reviewed-by: Mohamed Amir Yosef <mamir@chromium.org> Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org> Auto-Submit: Nina Satragno <nsatragno@chromium.org> Reviewed-by: Adem Derinel <derinel@google.com> Cr-Commit-Position: refs/heads/main@{#1419889}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
a3c55198aa
commit
dffa0e82f4
chrome/browser
password_manager
ui
webauthn
webui
webauthn
content/browser/webauth
device/fido
@ -71,21 +71,24 @@ const device::DiscoverableCredentialMetadata user1{
|
|||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
device::fido_parsing_utils::Materialize(kUserId),
|
device::fido_parsing_utils::Materialize(kUserId),
|
||||||
kUserName1,
|
kUserName1,
|
||||||
/*display_name=*/std::nullopt)};
|
/*display_name=*/std::nullopt),
|
||||||
|
/*provider_name=*/std::nullopt};
|
||||||
const device::DiscoverableCredentialMetadata user2{
|
const device::DiscoverableCredentialMetadata user2{
|
||||||
device::AuthenticatorType::kOther, kRpId,
|
device::AuthenticatorType::kOther, kRpId,
|
||||||
device::fido_parsing_utils::Materialize(kCredId2),
|
device::fido_parsing_utils::Materialize(kCredId2),
|
||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
device::fido_parsing_utils::Materialize(kUserId),
|
device::fido_parsing_utils::Materialize(kUserId),
|
||||||
kUserName2,
|
kUserName2,
|
||||||
/*display_name=*/std::nullopt)};
|
/*display_name=*/std::nullopt),
|
||||||
|
/*provider_name=*/std::nullopt};
|
||||||
const device::DiscoverableCredentialMetadata userGpm{
|
const device::DiscoverableCredentialMetadata userGpm{
|
||||||
device::AuthenticatorType::kEnclave, kRpId,
|
device::AuthenticatorType::kEnclave, kRpId,
|
||||||
device::fido_parsing_utils::Materialize(kCredIdGpm),
|
device::fido_parsing_utils::Materialize(kCredIdGpm),
|
||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
device::fido_parsing_utils::Materialize(kUserId),
|
device::fido_parsing_utils::Materialize(kUserId),
|
||||||
kUserName1,
|
kUserName1,
|
||||||
/*display_name=*/std::nullopt)};
|
/*display_name=*/std::nullopt),
|
||||||
|
/*provider_name=*/std::nullopt};
|
||||||
|
|
||||||
PasskeyCredential CreatePasskey(std::vector<uint8_t> cred_id,
|
PasskeyCredential CreatePasskey(std::vector<uint8_t> cred_id,
|
||||||
std::string username,
|
std::string username,
|
||||||
|
@ -39,7 +39,7 @@ AccountHoverListModel::AccountHoverListModel(
|
|||||||
items_.emplace_back(
|
items_.emplace_back(
|
||||||
NameTokenForDisplay(cred.user.name.value_or("")),
|
NameTokenForDisplay(cred.user.name.value_or("")),
|
||||||
AuthenticatorRequestDialogModel::GetMechanismDescription(
|
AuthenticatorRequestDialogModel::GetMechanismDescription(
|
||||||
cred.source, dialog_model->priority_phone_name),
|
cred, dialog_model->priority_phone_name),
|
||||||
ui::ImageModel::FromVectorIcon(vector_icons::kPasskeyIcon,
|
ui::ImageModel::FromVectorIcon(vector_icons::kPasskeyIcon,
|
||||||
dialog_model->ui_disabled_
|
dialog_model->ui_disabled_
|
||||||
? ui::kColorIconDisabled
|
? ui::kColorIconDisabled
|
||||||
|
@ -664,23 +664,38 @@ class GPMPasskeysAuthenticatorDialogTest : public DialogBrowserTest {
|
|||||||
device::DiscoverableCredentialMetadata gpm_cred(
|
device::DiscoverableCredentialMetadata gpm_cred(
|
||||||
device::AuthenticatorType::kEnclave, "example.com", {1},
|
device::AuthenticatorType::kEnclave, "example.com", {1},
|
||||||
device::PublicKeyCredentialUserEntity({1}, "elisa.g.beckett@gmail.com",
|
device::PublicKeyCredentialUserEntity({1}, "elisa.g.beckett@gmail.com",
|
||||||
"Elisa Beckett"));
|
"Elisa Beckett"),
|
||||||
|
std::nullopt);
|
||||||
device::DiscoverableCredentialMetadata local_cred1(
|
device::DiscoverableCredentialMetadata local_cred1(
|
||||||
device::AuthenticatorType::kTouchID, "example.com", {1},
|
device::AuthenticatorType::kTouchID, "example.com", {1},
|
||||||
device::PublicKeyCredentialUserEntity({1}, "elisa.g.beckett@gmail.com",
|
device::PublicKeyCredentialUserEntity({1}, "elisa.g.beckett@gmail.com",
|
||||||
"Elisa Beckett"));
|
"Elisa Beckett"),
|
||||||
|
std::nullopt);
|
||||||
device::DiscoverableCredentialMetadata local_cred2(
|
device::DiscoverableCredentialMetadata local_cred2(
|
||||||
device::AuthenticatorType::kTouchID, "example.com", {2},
|
device::AuthenticatorType::kTouchID, "example.com", {2},
|
||||||
device::PublicKeyCredentialUserEntity({2}, "elisa.beckett@ink-42.com",
|
device::PublicKeyCredentialUserEntity({2}, "elisa.beckett@ink-42.com",
|
||||||
"Elisa Beckett"));
|
"Elisa Beckett"),
|
||||||
|
std::nullopt);
|
||||||
device::DiscoverableCredentialMetadata phone_cred1(
|
device::DiscoverableCredentialMetadata phone_cred1(
|
||||||
device::AuthenticatorType::kPhone, "example.com", {3},
|
device::AuthenticatorType::kPhone, "example.com", {3},
|
||||||
device::PublicKeyCredentialUserEntity({1}, "elisa.g.beckett@gmail.com",
|
device::PublicKeyCredentialUserEntity({1}, "elisa.g.beckett@gmail.com",
|
||||||
"Elisa Beckett"));
|
"Elisa Beckett"),
|
||||||
|
std::nullopt);
|
||||||
device::DiscoverableCredentialMetadata phone_cred2(
|
device::DiscoverableCredentialMetadata phone_cred2(
|
||||||
device::AuthenticatorType::kPhone, "example.com", {4},
|
device::AuthenticatorType::kPhone, "example.com", {4},
|
||||||
device::PublicKeyCredentialUserEntity({2}, "elisa.beckett@ink-42.com",
|
device::PublicKeyCredentialUserEntity({2}, "elisa.beckett@ink-42.com",
|
||||||
"Elisa Beckett"));
|
"Elisa Beckett"),
|
||||||
|
std::nullopt);
|
||||||
|
device::DiscoverableCredentialMetadata ick_cred1(
|
||||||
|
device::AuthenticatorType::kICloudKeychain, "example.com", {5},
|
||||||
|
device::PublicKeyCredentialUserEntity({1}, "elisa.beckett@gmail.com",
|
||||||
|
"Elisa Beckett"),
|
||||||
|
"Example Passkey Provider");
|
||||||
|
device::DiscoverableCredentialMetadata ick_cred2(
|
||||||
|
device::AuthenticatorType::kICloudKeychain, "example.com", {6},
|
||||||
|
device::PublicKeyCredentialUserEntity({2}, "elisa.beckett@ink-42.com",
|
||||||
|
"Elisa Beckett"),
|
||||||
|
"Another Example Passkey Provider");
|
||||||
model_->user_entity = local_cred1.user;
|
model_->user_entity = local_cred1.user;
|
||||||
|
|
||||||
// Configure a phone from sync.
|
// Configure a phone from sync.
|
||||||
@ -822,6 +837,13 @@ class GPMPasskeysAuthenticatorDialogTest : public DialogBrowserTest {
|
|||||||
} else if (name == "gpm_locked_pin") {
|
} else if (name == "gpm_locked_pin") {
|
||||||
controller_->SetCurrentStepForTesting(
|
controller_->SetCurrentStepForTesting(
|
||||||
AuthenticatorRequestDialogModel::Step::kGPMLockedPin);
|
AuthenticatorRequestDialogModel::Step::kGPMLockedPin);
|
||||||
|
} else if (name == "icloud_keychain_cred") {
|
||||||
|
transport_availability.has_empty_allow_list = true;
|
||||||
|
controller_->set_allow_icloud_keychain(true);
|
||||||
|
transport_availability.recognized_credentials = {
|
||||||
|
std::move(ick_cred1),
|
||||||
|
std::move(ick_cred2),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
}
|
}
|
||||||
@ -973,6 +995,11 @@ IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest,
|
|||||||
ShowAndVerifyUi();
|
ShowAndVerifyUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest,
|
||||||
|
InvokeUi_icloud_keychain_cred) {
|
||||||
|
ShowAndVerifyUi();
|
||||||
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest, InvokeUi_touchid) {
|
IN_PROC_BROWSER_TEST_F(GPMPasskeysAuthenticatorDialogTest, InvokeUi_touchid) {
|
||||||
if (__builtin_available(macos 12, *)) {
|
if (__builtin_available(macos 12, *)) {
|
||||||
|
@ -441,7 +441,8 @@ TEST_F(PasskeysHandlerTest, TestHandleEdit) {
|
|||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
{0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
|
{0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa,
|
||||||
0xa, 0xa, 0xa, 0xa},
|
0xa, 0xa, 0xa, 0xa},
|
||||||
"new-username", "new-username")}};
|
"new-username", "new-username"),
|
||||||
|
/*provider_name=*/std::nullopt}};
|
||||||
std::move(callback).Run(std::move(credential_metadata));
|
std::move(callback).Run(std::move(credential_metadata));
|
||||||
base::RunLoop().RunUntilIdle();
|
base::RunLoop().RunUntilIdle();
|
||||||
});
|
});
|
||||||
|
@ -1412,7 +1412,8 @@ void AuthenticatorRequestDialogController::SelectAccount(
|
|||||||
for (const auto& response : ephemeral_state_.responses_) {
|
for (const auto& response : ephemeral_state_.responses_) {
|
||||||
model_->creds.emplace_back(AuthenticatorType::kOther,
|
model_->creds.emplace_back(AuthenticatorType::kOther,
|
||||||
model_->relying_party_id,
|
model_->relying_party_id,
|
||||||
response.credential->id, *response.user_entity);
|
response.credential->id, *response.user_entity,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
}
|
}
|
||||||
selection_callback_ = std::move(callback);
|
selection_callback_ = std::move(callback);
|
||||||
SetCurrentStep(Step::kSelectAccount);
|
SetCurrentStep(Step::kSelectAccount);
|
||||||
@ -2145,7 +2146,7 @@ void AuthenticatorRequestDialogController::PopulateMechanisms() {
|
|||||||
base::Unretained(this), cred.cred_id));
|
base::Unretained(this), cred.cred_id));
|
||||||
mechanism.description =
|
mechanism.description =
|
||||||
AuthenticatorRequestDialogModel::GetMechanismDescription(
|
AuthenticatorRequestDialogModel::GetMechanismDescription(
|
||||||
cred.source, model_->priority_phone_name);
|
cred, model_->priority_phone_name);
|
||||||
}
|
}
|
||||||
for (const auto& password : passwords_) {
|
for (const auto& password : passwords_) {
|
||||||
Mechanism mechanism(
|
Mechanism mechanism(
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "content/public/browser/global_routing_id.h"
|
#include "content/public/browser/global_routing_id.h"
|
||||||
#include "content/public/browser/render_frame_host.h"
|
#include "content/public/browser/render_frame_host.h"
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "device/fido/discoverable_credential_metadata.h"
|
||||||
#include "device/fido/features.h"
|
#include "device/fido/features.h"
|
||||||
#include "device/fido/fido_types.h"
|
#include "device/fido/fido_types.h"
|
||||||
#include "ui/base/l10n/l10n_util.h"
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
@ -91,16 +92,22 @@ AUTHENTICATOR_EVENTS
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
std::u16string AuthenticatorRequestDialogModel::GetMechanismDescription(
|
std::u16string AuthenticatorRequestDialogModel::GetMechanismDescription(
|
||||||
device::AuthenticatorType type,
|
const device::DiscoverableCredentialMetadata& cred,
|
||||||
const std::optional<std::string>& phone_name) {
|
const std::optional<std::string>& phone_name) {
|
||||||
if (type == device::AuthenticatorType::kPhone) {
|
if (cred.source == device::AuthenticatorType::kPhone) {
|
||||||
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_SOURCE_PHONE,
|
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_SOURCE_PHONE,
|
||||||
base::UTF8ToUTF16(*phone_name));
|
base::UTF8ToUTF16(*phone_name));
|
||||||
}
|
}
|
||||||
int message;
|
|
||||||
const bool gpm_enabled =
|
const bool gpm_enabled =
|
||||||
base::FeatureList::IsEnabled(device::kWebAuthnEnclaveAuthenticator);
|
base::FeatureList::IsEnabled(device::kWebAuthnEnclaveAuthenticator);
|
||||||
switch (type) {
|
if (cred.provider_name) {
|
||||||
|
return gpm_enabled ? base::UTF8ToUTF16(*cred.provider_name)
|
||||||
|
: l10n_util::GetStringFUTF16(
|
||||||
|
IDS_WEBAUTHN_SOURCE_CUSTOM_VENDOR,
|
||||||
|
base::UTF8ToUTF16(*cred.provider_name));
|
||||||
|
}
|
||||||
|
int message;
|
||||||
|
switch (cred.source) {
|
||||||
case device::AuthenticatorType::kWinNative:
|
case device::AuthenticatorType::kWinNative:
|
||||||
message = gpm_enabled ? IDS_WEBAUTHN_SOURCE_WINDOWS_HELLO_NEW
|
message = gpm_enabled ? IDS_WEBAUTHN_SOURCE_WINDOWS_HELLO_NEW
|
||||||
: IDS_WEBAUTHN_SOURCE_WINDOWS_HELLO;
|
: IDS_WEBAUTHN_SOURCE_WINDOWS_HELLO;
|
||||||
@ -110,8 +117,6 @@ std::u16string AuthenticatorRequestDialogModel::GetMechanismDescription(
|
|||||||
: IDS_WEBAUTHN_SOURCE_CHROME_PROFILE;
|
: IDS_WEBAUTHN_SOURCE_CHROME_PROFILE;
|
||||||
break;
|
break;
|
||||||
case device::AuthenticatorType::kICloudKeychain:
|
case device::AuthenticatorType::kICloudKeychain:
|
||||||
// TODO(crbug.com/40265798): Use IDS_WEBAUTHN_SOURCE_CUSTOM_VENDOR for
|
|
||||||
// third party providers.
|
|
||||||
message = gpm_enabled ? IDS_WEBAUTHN_SOURCE_ICLOUD_KEYCHAIN_NEW
|
message = gpm_enabled ? IDS_WEBAUTHN_SOURCE_ICLOUD_KEYCHAIN_NEW
|
||||||
: IDS_WEBAUTHN_SOURCE_ICLOUD_KEYCHAIN;
|
: IDS_WEBAUTHN_SOURCE_ICLOUD_KEYCHAIN;
|
||||||
break;
|
break;
|
||||||
|
@ -379,7 +379,7 @@ struct AuthenticatorRequestDialogModel
|
|||||||
// Returns a user-friendly description for a |type|. If |type| is kPhone, a
|
// Returns a user-friendly description for a |type|. If |type| is kPhone, a
|
||||||
// |phone_name| must be passed.
|
// |phone_name| must be passed.
|
||||||
static std::u16string GetMechanismDescription(
|
static std::u16string GetMechanismDescription(
|
||||||
device::AuthenticatorType type,
|
const device::DiscoverableCredentialMetadata& cred,
|
||||||
const std::optional<std::string>& phone_name);
|
const std::optional<std::string>& phone_name);
|
||||||
|
|
||||||
explicit AuthenticatorRequestDialogModel(
|
explicit AuthenticatorRequestDialogModel(
|
||||||
|
@ -312,32 +312,66 @@ const device::PublicKeyCredentialUserEntity kPhoneUser2({3, 4, 5, 6},
|
|||||||
"D",
|
"D",
|
||||||
std::nullopt);
|
std::nullopt);
|
||||||
|
|
||||||
const device::DiscoverableCredentialMetadata
|
const device::DiscoverableCredentialMetadata kCred1(
|
||||||
kCred1(device::AuthenticatorType::kOther, "rp.com", {0}, kUser1);
|
device::AuthenticatorType::kOther,
|
||||||
|
"rp.com",
|
||||||
|
{0},
|
||||||
|
kUser1,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
const device::DiscoverableCredentialMetadata kCred1FromICloudKeychain(
|
const device::DiscoverableCredentialMetadata kCred1FromICloudKeychain(
|
||||||
device::AuthenticatorType::kICloudKeychain,
|
device::AuthenticatorType::kICloudKeychain,
|
||||||
"rp.com",
|
"rp.com",
|
||||||
{4},
|
{4},
|
||||||
kUser1);
|
kUser1,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
const device::DiscoverableCredentialMetadata kCred1FromChromeOS(
|
const device::DiscoverableCredentialMetadata kCred1FromChromeOS(
|
||||||
device::AuthenticatorType::kChromeOS,
|
device::AuthenticatorType::kChromeOS,
|
||||||
"rp.com",
|
"rp.com",
|
||||||
{4},
|
{4},
|
||||||
kUser1);
|
kUser1,
|
||||||
const device::DiscoverableCredentialMetadata
|
/*provider_name=*/std::nullopt);
|
||||||
kCred2(device::AuthenticatorType::kOther, "rp.com", {1}, kUser2);
|
const device::DiscoverableCredentialMetadata kCred2(
|
||||||
const device::DiscoverableCredentialMetadata
|
device::AuthenticatorType::kOther,
|
||||||
kPhoneCred1(device::AuthenticatorType::kPhone, "rp.com", {2}, kPhoneUser1);
|
"rp.com",
|
||||||
const device::DiscoverableCredentialMetadata
|
{1},
|
||||||
kPhoneCred2(device::AuthenticatorType::kPhone, "rp.com", {3}, kPhoneUser2);
|
kUser2,
|
||||||
const device::DiscoverableCredentialMetadata
|
/*provider_name=*/std::nullopt);
|
||||||
kWinCred1(device::AuthenticatorType::kWinNative, "rp.com", {0}, kUser1);
|
const device::DiscoverableCredentialMetadata kPhoneCred1(
|
||||||
const device::DiscoverableCredentialMetadata
|
device::AuthenticatorType::kPhone,
|
||||||
kWinCred2(device::AuthenticatorType::kWinNative, "rp.com", {1}, kUser2);
|
"rp.com",
|
||||||
const device::DiscoverableCredentialMetadata
|
{2},
|
||||||
kTouchIDCred1(device::AuthenticatorType::kTouchID, "rp.com", {4}, kUser1);
|
kPhoneUser1,
|
||||||
const device::DiscoverableCredentialMetadata
|
/*provider_name=*/std::nullopt);
|
||||||
kEnclaveCred1(device::AuthenticatorType::kEnclave, "rp.com", {1}, kUser1);
|
const device::DiscoverableCredentialMetadata kPhoneCred2(
|
||||||
|
device::AuthenticatorType::kPhone,
|
||||||
|
"rp.com",
|
||||||
|
{3},
|
||||||
|
kPhoneUser2,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
|
const device::DiscoverableCredentialMetadata kWinCred1(
|
||||||
|
device::AuthenticatorType::kWinNative,
|
||||||
|
"rp.com",
|
||||||
|
{0},
|
||||||
|
kUser1,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
|
const device::DiscoverableCredentialMetadata kWinCred2(
|
||||||
|
device::AuthenticatorType::kWinNative,
|
||||||
|
"rp.com",
|
||||||
|
{1},
|
||||||
|
kUser2,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
|
const device::DiscoverableCredentialMetadata kTouchIDCred1(
|
||||||
|
device::AuthenticatorType::kTouchID,
|
||||||
|
"rp.com",
|
||||||
|
{4},
|
||||||
|
kUser1,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
|
const device::DiscoverableCredentialMetadata kEnclaveCred1(
|
||||||
|
device::AuthenticatorType::kEnclave,
|
||||||
|
"rp.com",
|
||||||
|
{1},
|
||||||
|
kUser1,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
|
|
||||||
AuthenticatorRequestDialogModel::Mechanism::CredentialInfo CredentialInfoFrom(
|
AuthenticatorRequestDialogModel::Mechanism::CredentialInfo CredentialInfoFrom(
|
||||||
const device::DiscoverableCredentialMetadata& metadata) {
|
const device::DiscoverableCredentialMetadata& metadata) {
|
||||||
|
@ -1171,7 +1171,8 @@ void ChromeAuthenticatorRequestDelegate::GetPhoneContactableGpmPasskeysForRpId(
|
|||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
std::vector<uint8_t>(passkey.user_id().begin(),
|
std::vector<uint8_t>(passkey.user_id().begin(),
|
||||||
passkey.user_id().end()),
|
passkey.user_id().end()),
|
||||||
passkey.user_name(), passkey.user_display_name()));
|
passkey.user_name(), passkey.user_display_name()),
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,7 +651,8 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest, FilterGoogleComPasskeys) {
|
|||||||
device::AuthenticatorType::kOther, test.rp_id,
|
device::AuthenticatorType::kOther, test.rp_id,
|
||||||
std::vector<uint8_t>{0},
|
std::vector<uint8_t>{0},
|
||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
std::vector<uint8_t>(user_id.begin(), user_id.end())));
|
std::vector<uint8_t>(user_id.begin(), user_id.end())),
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
}
|
}
|
||||||
data.has_platform_authenticator_credential = test.recognized_credential;
|
data.has_platform_authenticator_credential = test.recognized_credential;
|
||||||
|
|
||||||
@ -659,7 +660,8 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest, FilterGoogleComPasskeys) {
|
|||||||
// affect setting the recognized credentials flag.
|
// affect setting the recognized credentials flag.
|
||||||
data.recognized_credentials.emplace_back(
|
data.recognized_credentials.emplace_back(
|
||||||
device::AuthenticatorType::kICloudKeychain, test.rp_id,
|
device::AuthenticatorType::kICloudKeychain, test.rp_id,
|
||||||
std::vector<uint8_t>{0}, device::PublicKeyCredentialUserEntity({1}));
|
std::vector<uint8_t>{0}, device::PublicKeyCredentialUserEntity({1}),
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
data.has_icloud_keychain_credential = device::FidoRequestHandlerBase::
|
data.has_icloud_keychain_credential = device::FidoRequestHandlerBase::
|
||||||
RecognizedCredential::kHasRecognizedCredential;
|
RecognizedCredential::kHasRecognizedCredential;
|
||||||
|
|
||||||
@ -708,7 +710,8 @@ TEST_F(ChromeAuthenticatorRequestDelegateTest,
|
|||||||
data.recognized_credentials.emplace_back(
|
data.recognized_credentials.emplace_back(
|
||||||
device::AuthenticatorType::kOther, kGoogleRpId, std::vector<uint8_t>{0},
|
device::AuthenticatorType::kOther, kGoogleRpId, std::vector<uint8_t>{0},
|
||||||
device::PublicKeyCredentialUserEntity(
|
device::PublicKeyCredentialUserEntity(
|
||||||
std::vector<uint8_t>(user_id.begin(), user_id.end())));
|
std::vector<uint8_t>(user_id.begin(), user_id.end())),
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
data.has_platform_authenticator_credential = device::FidoRequestHandlerBase::
|
data.has_platform_authenticator_credential = device::FidoRequestHandlerBase::
|
||||||
RecognizedCredential::kHasRecognizedCredential;
|
RecognizedCredential::kHasRecognizedCredential;
|
||||||
|
|
||||||
@ -1010,7 +1013,8 @@ TEST_F(ChromeAuthenticatorRequestDelegateWithPasswordsTest,
|
|||||||
transports_info.recognized_credentials = {
|
transports_info.recognized_credentials = {
|
||||||
device::DiscoverableCredentialMetadata(
|
device::DiscoverableCredentialMetadata(
|
||||||
device::AuthenticatorType::kEnclave, kRpId, {},
|
device::AuthenticatorType::kEnclave, kRpId, {},
|
||||||
device::PublicKeyCredentialUserEntity())};
|
device::PublicKeyCredentialUserEntity(),
|
||||||
|
/*provider_name=*/std::nullopt)};
|
||||||
|
|
||||||
// still waiting for passwords.
|
// still waiting for passwords.
|
||||||
EXPECT_CALL(mock_closure, Run).Times(0);
|
EXPECT_CALL(mock_closure, Run).Times(0);
|
||||||
|
@ -51,7 +51,8 @@ void LocalCredentialManagementMac::Enumerate(
|
|||||||
credential_metadata.emplace_back(
|
credential_metadata.emplace_back(
|
||||||
device::AuthenticatorType::kTouchID, credential.rp_id,
|
device::AuthenticatorType::kTouchID, credential.rp_id,
|
||||||
credential.credential_id,
|
credential.credential_id,
|
||||||
credential.metadata.ToPublicKeyCredentialUserEntity());
|
credential.metadata.ToPublicKeyCredentialUserEntity(),
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
}
|
}
|
||||||
std::sort(credential_metadata.begin(), credential_metadata.end(),
|
std::sort(credential_metadata.begin(), credential_metadata.end(),
|
||||||
CredentialComparator());
|
CredentialComparator());
|
||||||
|
@ -9485,7 +9485,8 @@ class ICloudKeychainAuthenticatorImplTest : public AuthenticatorImplTest {
|
|||||||
static std::vector<device::DiscoverableCredentialMetadata> GetCredentials() {
|
static std::vector<device::DiscoverableCredentialMetadata> GetCredentials() {
|
||||||
device::DiscoverableCredentialMetadata metadata(
|
device::DiscoverableCredentialMetadata metadata(
|
||||||
device::AuthenticatorType::kICloudKeychain, kTestRelyingPartyId,
|
device::AuthenticatorType::kICloudKeychain, kTestRelyingPartyId,
|
||||||
{1, 2, 3, 4}, {{5, 6, 7, 8}, "name", "displayName"});
|
{1, 2, 3, 4}, {{5, 6, 7, 8}, "name", "displayName"},
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
return {std::move(metadata)};
|
return {std::move(metadata)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,17 +4,21 @@
|
|||||||
|
|
||||||
#include "device/fido/discoverable_credential_metadata.h"
|
#include "device/fido/discoverable_credential_metadata.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace device {
|
namespace device {
|
||||||
|
|
||||||
DiscoverableCredentialMetadata::DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata::DiscoverableCredentialMetadata(
|
||||||
AuthenticatorType source_in,
|
AuthenticatorType source_in,
|
||||||
std::string rp_id_in,
|
std::string rp_id_in,
|
||||||
std::vector<uint8_t> cred_id_in,
|
std::vector<uint8_t> cred_id_in,
|
||||||
PublicKeyCredentialUserEntity user_in)
|
PublicKeyCredentialUserEntity user_in,
|
||||||
|
std::optional<std::string> provider_name_in)
|
||||||
: source(source_in),
|
: source(source_in),
|
||||||
rp_id(std::move(rp_id_in)),
|
rp_id(std::move(rp_id_in)),
|
||||||
cred_id(std::move(cred_id_in)),
|
cred_id(std::move(cred_id_in)),
|
||||||
user(std::move(user_in)) {}
|
user(std::move(user_in)),
|
||||||
|
provider_name(std::move(provider_name_in)) {}
|
||||||
|
|
||||||
DiscoverableCredentialMetadata::DiscoverableCredentialMetadata() = default;
|
DiscoverableCredentialMetadata::DiscoverableCredentialMetadata() = default;
|
||||||
DiscoverableCredentialMetadata::DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata::DiscoverableCredentialMetadata(
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#ifndef DEVICE_FIDO_DISCOVERABLE_CREDENTIAL_METADATA_H_
|
#ifndef DEVICE_FIDO_DISCOVERABLE_CREDENTIAL_METADATA_H_
|
||||||
#define DEVICE_FIDO_DISCOVERABLE_CREDENTIAL_METADATA_H_
|
#define DEVICE_FIDO_DISCOVERABLE_CREDENTIAL_METADATA_H_
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/component_export.h"
|
#include "base/component_export.h"
|
||||||
@ -21,7 +22,8 @@ class COMPONENT_EXPORT(DEVICE_FIDO) DiscoverableCredentialMetadata {
|
|||||||
DiscoverableCredentialMetadata(AuthenticatorType source,
|
DiscoverableCredentialMetadata(AuthenticatorType source,
|
||||||
std::string rp_id,
|
std::string rp_id,
|
||||||
std::vector<uint8_t> cred_id,
|
std::vector<uint8_t> cred_id,
|
||||||
PublicKeyCredentialUserEntity user);
|
PublicKeyCredentialUserEntity user,
|
||||||
|
std::optional<std::string> provider_name);
|
||||||
|
|
||||||
DiscoverableCredentialMetadata();
|
DiscoverableCredentialMetadata();
|
||||||
DiscoverableCredentialMetadata(const DiscoverableCredentialMetadata& other);
|
DiscoverableCredentialMetadata(const DiscoverableCredentialMetadata& other);
|
||||||
@ -41,6 +43,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) DiscoverableCredentialMetadata {
|
|||||||
// automatically by the system. This can happen on Windows where (at least) a
|
// automatically by the system. This can happen on Windows where (at least) a
|
||||||
// credential for login.microsoft.com can be auto-created for users.
|
// credential for login.microsoft.com can be auto-created for users.
|
||||||
bool system_created = false;
|
bool system_created = false;
|
||||||
|
|
||||||
|
// The name of the third-party provider the passkey is stored in. This is
|
||||||
|
// populated for credentials coming from the MacOS API.
|
||||||
|
std::optional<std::string> provider_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace device
|
} // namespace device
|
||||||
|
@ -76,7 +76,8 @@ void TouchIdAuthenticator::GetPlatformCredentialInfoForRequest(
|
|||||||
for (const auto& credential : *credentials) {
|
for (const auto& credential : *credentials) {
|
||||||
result.emplace_back(AuthenticatorType::kTouchID, request.rp_id,
|
result.emplace_back(AuthenticatorType::kTouchID, request.rp_id,
|
||||||
credential.credential_id,
|
credential.credential_id,
|
||||||
credential.metadata.ToPublicKeyCredentialUserEntity());
|
credential.metadata.ToPublicKeyCredentialUserEntity(),
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
}
|
}
|
||||||
std::move(callback).Run(
|
std::move(callback).Run(
|
||||||
std::move(result),
|
std::move(result),
|
||||||
|
@ -60,7 +60,7 @@ TEST_F(TouchIdAuthenticatorTest, GetPlatformCredentialInfoForRequest_RK) {
|
|||||||
->first;
|
->first;
|
||||||
DiscoverableCredentialMetadata credential_metadata(
|
DiscoverableCredentialMetadata credential_metadata(
|
||||||
AuthenticatorType::kTouchID, kRp1, credential.credential_id,
|
AuthenticatorType::kTouchID, kRp1, credential.credential_id,
|
||||||
std::move(user));
|
std::move(user), /*provider_name=*/std::nullopt);
|
||||||
|
|
||||||
// Inject a non resident credential for RP 2. This one should be ignored.
|
// Inject a non resident credential for RP 2. This one should be ignored.
|
||||||
PublicKeyCredentialUserEntity user2(kUserId2);
|
PublicKeyCredentialUserEntity user2(kUserId2);
|
||||||
@ -105,7 +105,7 @@ TEST_F(TouchIdAuthenticatorTest, GetPlatformCredentialInfoForRequest_NonRK) {
|
|||||||
->first;
|
->first;
|
||||||
DiscoverableCredentialMetadata credential_metadata(
|
DiscoverableCredentialMetadata credential_metadata(
|
||||||
AuthenticatorType::kTouchID, kRp1, credential.credential_id,
|
AuthenticatorType::kTouchID, kRp1, credential.credential_id,
|
||||||
std::move(user));
|
std::move(user), /*provider_name=*/std::nullopt);
|
||||||
|
|
||||||
{
|
{
|
||||||
// RP 1 should report the credential if it is in the allow list but not
|
// RP 1 should report the credential if it is in the allow list but not
|
||||||
|
@ -22,6 +22,7 @@ API_AVAILABLE(macos(13.3))
|
|||||||
@property(nonatomic, copy) NSString* name;
|
@property(nonatomic, copy) NSString* name;
|
||||||
@property(nonatomic, copy) NSString* relyingParty;
|
@property(nonatomic, copy) NSString* relyingParty;
|
||||||
@property(nonatomic, copy) NSData* userHandle;
|
@property(nonatomic, copy) NSData* userHandle;
|
||||||
|
@property(nonatomic, copy) NSString* providerName;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation FakeBrowserPlatformPublicKeyCredential
|
@implementation FakeBrowserPlatformPublicKeyCredential
|
||||||
@ -29,6 +30,7 @@ API_AVAILABLE(macos(13.3))
|
|||||||
@synthesize name = _name;
|
@synthesize name = _name;
|
||||||
@synthesize relyingParty = _relyingParty;
|
@synthesize relyingParty = _relyingParty;
|
||||||
@synthesize userHandle = _userHandle;
|
@synthesize userHandle = _userHandle;
|
||||||
|
@synthesize providerName = _providerName;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
API_AVAILABLE(macos(13.3))
|
API_AVAILABLE(macos(13.3))
|
||||||
@ -199,6 +201,8 @@ void FakeSystemInterface::GetPlatformCredentials(
|
|||||||
cred.relyingParty = base::SysUTF8ToNSString(rp_id);
|
cred.relyingParty = base::SysUTF8ToNSString(rp_id);
|
||||||
cred.name = base::SysUTF8ToNSString(cred_values.user.name.value_or(""));
|
cred.name = base::SysUTF8ToNSString(cred_values.user.name.value_or(""));
|
||||||
[ret addObject:cred];
|
[ret addObject:cred];
|
||||||
|
cred.providerName = base::SysUTF8ToNSString(
|
||||||
|
cred_values.provider_name.value_or("(Not provided)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
block(ret);
|
block(ret);
|
||||||
|
@ -255,7 +255,8 @@ class API_AVAILABLE(macos(13.3)) Authenticator : public FidoAuthenticator {
|
|||||||
ToVector(cred.userHandle), cred.name.UTF8String,
|
ToVector(cred.userHandle), cred.name.UTF8String,
|
||||||
/* iCloud Keychain does not store
|
/* iCloud Keychain does not store
|
||||||
a displayName for passkeys */
|
a displayName for passkeys */
|
||||||
std::nullopt));
|
std::nullopt),
|
||||||
|
cred.providerName.UTF8String);
|
||||||
}
|
}
|
||||||
const auto has_credentials =
|
const auto has_credentials =
|
||||||
ret.empty() ? FidoRequestHandlerBase::RecognizedCredential::
|
ret.empty() ? FidoRequestHandlerBase::RecognizedCredential::
|
||||||
|
@ -511,7 +511,8 @@ TEST_F(iCloudKeychainTest, FetchCredentialMetadata) {
|
|||||||
{AuthenticatorType::kICloudKeychain,
|
{AuthenticatorType::kICloudKeychain,
|
||||||
"example.com",
|
"example.com",
|
||||||
{1, 2, 3, 4},
|
{1, 2, 3, 4},
|
||||||
{{4, 3, 2, 1}, "name", std::nullopt}}};
|
{{4, 3, 2, 1}, "name", std::nullopt},
|
||||||
|
"Example provider"}};
|
||||||
fake_->SetCredentials(creds);
|
fake_->SetCredentials(creds);
|
||||||
base::test::TestFuture<std::vector<DiscoverableCredentialMetadata>,
|
base::test::TestFuture<std::vector<DiscoverableCredentialMetadata>,
|
||||||
FidoRequestHandlerBase::RecognizedCredential>
|
FidoRequestHandlerBase::RecognizedCredential>
|
||||||
@ -538,11 +539,13 @@ TEST_F(iCloudKeychainTest, FetchCredentialMetadataWithAllowlist) {
|
|||||||
{AuthenticatorType::kICloudKeychain,
|
{AuthenticatorType::kICloudKeychain,
|
||||||
"example.com",
|
"example.com",
|
||||||
{1, 2, 3, 4},
|
{1, 2, 3, 4},
|
||||||
{{4, 3, 2, 1}, "name", std::nullopt}},
|
{{4, 3, 2, 1}, "name", std::nullopt},
|
||||||
|
"Example provider"},
|
||||||
{AuthenticatorType::kICloudKeychain,
|
{AuthenticatorType::kICloudKeychain,
|
||||||
"example.com",
|
"example.com",
|
||||||
{1, 2, 3, 5},
|
{1, 2, 3, 5},
|
||||||
{{4, 3, 2, 2}, "name", std::nullopt}},
|
{{4, 3, 2, 2}, "name", std::nullopt},
|
||||||
|
"Example provider"},
|
||||||
};
|
};
|
||||||
fake_->SetCredentials(creds);
|
fake_->SetCredentials(creds);
|
||||||
base::test::TestFuture<std::vector<DiscoverableCredentialMetadata>,
|
base::test::TestFuture<std::vector<DiscoverableCredentialMetadata>,
|
||||||
|
@ -41,7 +41,8 @@ void VirtualFidoDeviceAuthenticator::GetPlatformCredentialInfoForRequest(
|
|||||||
}))) {
|
}))) {
|
||||||
credentials.emplace_back(
|
credentials.emplace_back(
|
||||||
AuthenticatorType::kOther, request.rp_id, registration.first,
|
AuthenticatorType::kOther, request.rp_id, registration.first,
|
||||||
registration.second.user.value_or(PublicKeyCredentialUserEntity()));
|
registration.second.user.value_or(PublicKeyCredentialUserEntity()),
|
||||||
|
std::nullopt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FidoRequestHandlerBase::RecognizedCredential has_credentials =
|
FidoRequestHandlerBase::RecognizedCredential has_credentials =
|
||||||
|
@ -125,7 +125,7 @@ TEST_F(VirtualFidoDeviceAuthenticatorTest,
|
|||||||
EXPECT_TRUE(future.Wait());
|
EXPECT_TRUE(future.Wait());
|
||||||
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
||||||
AuthenticatorType::kOther, kRpId, credential_id,
|
AuthenticatorType::kOther, kRpId, credential_id,
|
||||||
PublicKeyCredentialUserEntity());
|
PublicKeyCredentialUserEntity(), /*provider_name=*/std::nullopt);
|
||||||
EXPECT_THAT(std::get<0>(future.Get()),
|
EXPECT_THAT(std::get<0>(future.Get()),
|
||||||
testing::UnorderedElementsAre(expected));
|
testing::UnorderedElementsAre(expected));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -147,10 +147,12 @@ TEST_F(VirtualFidoDeviceAuthenticatorTest,
|
|||||||
authenticator_->GetPlatformCredentialInfoForRequest(
|
authenticator_->GetPlatformCredentialInfoForRequest(
|
||||||
request, CtapGetAssertionOptions(), future.GetCallback());
|
request, CtapGetAssertionOptions(), future.GetCallback());
|
||||||
EXPECT_TRUE(future.Wait());
|
EXPECT_TRUE(future.Wait());
|
||||||
DiscoverableCredentialMetadata expected1 = DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata expected1 =
|
||||||
AuthenticatorType::kOther, kRpId, id1, user1);
|
DiscoverableCredentialMetadata(AuthenticatorType::kOther, kRpId, id1,
|
||||||
DiscoverableCredentialMetadata expected2 = DiscoverableCredentialMetadata(
|
user1, /*provider_name=*/std::nullopt);
|
||||||
AuthenticatorType::kOther, kRpId, id2, user2);
|
DiscoverableCredentialMetadata expected2 =
|
||||||
|
DiscoverableCredentialMetadata(AuthenticatorType::kOther, kRpId, id2,
|
||||||
|
user2, /*provider_name=*/std::nullopt);
|
||||||
EXPECT_THAT(std::get<0>(future.Get()),
|
EXPECT_THAT(std::get<0>(future.Get()),
|
||||||
testing::UnorderedElementsAre(expected1, expected2));
|
testing::UnorderedElementsAre(expected1, expected2));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
|
@ -128,7 +128,8 @@ TEST_F(WinAuthenticatorTest,
|
|||||||
EXPECT_TRUE(future.Wait());
|
EXPECT_TRUE(future.Wait());
|
||||||
|
|
||||||
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
||||||
AuthenticatorType::kWinNative, kRpId, kCredentialId, user);
|
AuthenticatorType::kWinNative, kRpId, kCredentialId, user,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
EXPECT_EQ(std::get<0>(future.Get()),
|
EXPECT_EQ(std::get<0>(future.Get()),
|
||||||
std::vector<DiscoverableCredentialMetadata>{expected});
|
std::vector<DiscoverableCredentialMetadata>{expected});
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
@ -202,7 +203,8 @@ TEST_F(WinAuthenticatorTest, GetCredentialInformationForRequest_Unsupported) {
|
|||||||
EXPECT_TRUE(future.Wait());
|
EXPECT_TRUE(future.Wait());
|
||||||
|
|
||||||
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
||||||
AuthenticatorType::kWinNative, kRpId, kCredentialId, user);
|
AuthenticatorType::kWinNative, kRpId, kCredentialId, user,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
EXPECT_EQ(std::get<0>(future.Get()),
|
EXPECT_EQ(std::get<0>(future.Get()),
|
||||||
std::vector<DiscoverableCredentialMetadata>{});
|
std::vector<DiscoverableCredentialMetadata>{});
|
||||||
EXPECT_EQ(std::get<1>(future.Get()),
|
EXPECT_EQ(std::get<1>(future.Get()),
|
||||||
@ -230,7 +232,8 @@ TEST_F(WinAuthenticatorTest,
|
|||||||
EXPECT_TRUE(future.Wait());
|
EXPECT_TRUE(future.Wait());
|
||||||
|
|
||||||
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
DiscoverableCredentialMetadata expected = DiscoverableCredentialMetadata(
|
||||||
AuthenticatorType::kWinNative, kRpId, kCredentialId, user1);
|
AuthenticatorType::kWinNative, kRpId, kCredentialId, user1,
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
EXPECT_THAT(std::get<0>(future.Get()), testing::ElementsAre(expected));
|
EXPECT_THAT(std::get<0>(future.Get()), testing::ElementsAre(expected));
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
std::get<1>(future.Get()),
|
std::get<1>(future.Get()),
|
||||||
|
@ -374,7 +374,9 @@ WinCredentialDetailsListToCredentialMetadata(
|
|||||||
: std::nullopt,
|
: std::nullopt,
|
||||||
user->pwszDisplayName
|
user->pwszDisplayName
|
||||||
? std::make_optional(base::WideToUTF8(user->pwszDisplayName))
|
? std::make_optional(base::WideToUTF8(user->pwszDisplayName))
|
||||||
: std::nullopt));
|
: std::nullopt),
|
||||||
|
// TODO(nsatragno): integrate with pwszAuthenticatorName.
|
||||||
|
/*provider_name=*/std::nullopt);
|
||||||
metadata.system_created = !credential->bRemovable;
|
metadata.system_created = !credential->bRemovable;
|
||||||
result.push_back(std::move(metadata));
|
result.push_back(std::move(metadata));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user