Commit 9ca4677a authored by Adam Langley's avatar Adam Langley Committed by Chromium LUCI CQ

webauthn: add UI for enterprise attestation.

With CTAP 2.1 it's possible for a security key to have an RP ID
hardcoded into it which can receive enterprise attestation on request.
If the RP ID is listed in the enterprise policy then this is permitted
automatically. Otherwise, we need to alert the user that this is
happening.

This change adds an attestation permission step to the WebAuthn UI which
acts the same as the current one, but with different wording to reflect
the greater impact of enterprise attestations.

Change-Id: I27fb9f7978b112910a51424f48c8e2567b146719
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2616736
Auto-Submit: Adam Langley <agl@chromium.org>
Reviewed-by: default avatarMartin Kreichgauer <martinkr@google.com>
Commit-Queue: Adam Langley <agl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844280}
parent 06708f13
......@@ -10828,6 +10828,12 @@ Please help our engineers fix this problem. Tell us what happened right before y
<message name="IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC" desc="The description on a dialog informing the user that the website wants to see information that identifies the user's Security Key, such as make and model number. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key.">
<ph name="WEBSITE"><ex>accounts.google.com</ex>$1</ph> wants to see the make and model of your security key
</message>
<message name="IDS_WEBAUTHN_REQUEST_ENTERPRISE_ATTESTATION_PERMISSION_TITLE" desc="Title of a dialog informing the user that the website wants to read the serial number of the user's security key. A security key is a physical device used for authentication.">
Allow this site to identify your security key?
</message>
<message name="IDS_WEBAUTHN_REQUEST_ENTERPRISE_ATTESTATION_PERMISSION_DESC" desc="The description on a dialog informing the user that the website wants to wants to read the serial number of the user's security key. A security key is a physical device used for authentication. The word 'issued' here means that the company linked to the website had the security key specially manufactured and, typically, the user is an employee of that company who received the security key as part of their employment.">
<ph name="WEBSITE"><ex>accounts.google.com</ex>$1</ph> issued your security key and wants to learn its ID number. The site will know exactly which security key you're using.
</message>
<message name="IDS_WEBAUTHN_ALLOW_ATTESTATION" desc="Label on button to allow a website to see information that identifies the user's Security Key, such as make and model number. The 'make' of a device is the brand name of the manufacturer, e.g. Yubikey is a make of Security Key. The 'model' of a device is the specific product, e.g. Yubikey Neo is a model of Security Key.">
Allow
</message>
......
......@@ -178,6 +178,11 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
std::make_unique<AttestationPermissionRequestSheetModel>(
dialog_model));
break;
case Step::kEnterpriseAttestationPermissionRequest:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
std::make_unique<EnterpriseAttestationPermissionRequestSheetModel>(
dialog_model));
break;
case Step::kNotStarted:
case Step::kClosed:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
......
......@@ -219,7 +219,9 @@ class AuthenticatorDialogTest : public DialogBrowserTest {
std::move(responses),
base::BindOnce([](device::AuthenticatorGetAssertionResponse) {}));
} else if (name == "request_attestation_permission") {
model->RequestAttestationPermission(base::DoNothing());
model->RequestAttestationPermission(false, base::DoNothing());
} else if (name == "request_enterprise_attestation_permission") {
model->RequestAttestationPermission(true, base::DoNothing());
}
ShowAuthenticatorRequestDialog(
......@@ -385,3 +387,8 @@ IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
InvokeUi_request_attestation_permission) {
ShowAndVerifyUi();
}
IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest,
InvokeUi_request_enterprise_attestation_permission) {
ShowAndVerifyUi();
}
......@@ -1149,6 +1149,26 @@ base::string16 AttestationPermissionRequestSheetModel::GetCancelButtonLabel()
return l10n_util::GetStringUTF16(IDS_PERMISSION_DENY);
}
// EnterpriseAttestationPermissionRequestSheetModel ---------------------------
EnterpriseAttestationPermissionRequestSheetModel::
EnterpriseAttestationPermissionRequestSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AttestationPermissionRequestSheetModel(dialog_model) {}
base::string16 EnterpriseAttestationPermissionRequestSheetModel::GetStepTitle()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_REQUEST_ENTERPRISE_ATTESTATION_PERMISSION_TITLE);
}
base::string16
EnterpriseAttestationPermissionRequestSheetModel::GetStepDescription() const {
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_REQUEST_ENTERPRISE_ATTESTATION_PERMISSION_DESC,
GetRelyingPartyIdString(dialog_model()));
}
// AuthenticatorQRSheetModel --------------------------------------------------
AuthenticatorQRSheetModel::AuthenticatorQRSheetModel(
......
......@@ -499,6 +499,18 @@ class AttestationPermissionRequestSheetModel
base::string16 GetCancelButtonLabel() const override;
};
class EnterpriseAttestationPermissionRequestSheetModel
: public AttestationPermissionRequestSheetModel {
public:
explicit EnterpriseAttestationPermissionRequestSheetModel(
AuthenticatorRequestDialogModel* dialog_model);
private:
// AuthenticatorSheetModelBase:
base::string16 GetStepTitle() const override;
base::string16 GetStepDescription() const override;
};
class AuthenticatorQRSheetModel : public AuthenticatorSheetModelBase {
public:
explicit AuthenticatorQRSheetModel(
......
......@@ -587,10 +587,13 @@ void AuthenticatorRequestDialogModel::OnBioEnrollmentDone() {
}
void AuthenticatorRequestDialogModel::RequestAttestationPermission(
bool is_enterprise_attestation,
base::OnceCallback<void(bool)> callback) {
DCHECK(current_step_ != Step::kClosed);
attestation_callback_ = std::move(callback);
SetCurrentStep(Step::kAttestationPermissionRequest);
SetCurrentStep(is_enterprise_attestation
? Step::kEnterpriseAttestationPermissionRequest
: Step::kAttestationPermissionRequest);
}
void AuthenticatorRequestDialogModel::set_cable_transport_info(
......
......@@ -102,8 +102,9 @@ class AuthenticatorRequestDialogModel {
// Account selection,
kSelectAccount,
// Attestation permission request.
// Attestation permission requests.
kAttestationPermissionRequest,
kEnterpriseAttestationPermissionRequest,
};
// Implemented by the dialog to observe this model and show the UI panels
......@@ -384,7 +385,8 @@ class AuthenticatorRequestDialogModel {
base::Optional<int> uv_attempts() const { return uv_attempts_; }
void RequestAttestationPermission(base::OnceCallback<void(bool)> callback);
void RequestAttestationPermission(bool is_enterprise_attestation,
base::OnceCallback<void(bool)> callback);
const std::vector<device::AuthenticatorGetAssertionResponse>& responses() {
return ephemeral_state_.responses_;
......
......@@ -333,13 +333,6 @@ void ChromeAuthenticatorRequestDelegate::ShouldReturnAttestation(
return;
}
if (is_enterprise_attestation) {
// This will require additional UI that is not yet ready. Therefore, at this
// stage, it is always rejected.
std::move(callback).Run(false);
return;
}
// Cryptotoken displays its own attestation consent prompt.
// AuthenticatorCommon does not invoke ShouldReturnAttestation() for those
// requests.
......@@ -359,7 +352,8 @@ void ChromeAuthenticatorRequestDelegate::ShouldReturnAttestation(
}
#endif // defined(OS_WIN)
weak_dialog_model_->RequestAttestationPermission(std::move(callback));
weak_dialog_model_->RequestAttestationPermission(is_enterprise_attestation,
std::move(callback));
}
bool ChromeAuthenticatorRequestDelegate::SupportsResidentKeys() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment