[WebAuthn] Customize a bit more on the macOS LocalAuthentication prompt
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Mar 2020 00:03:19 +0000 (00:03 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Mar 2020 00:03:19 +0000 (00:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=208703
<rdar://problem/60136974>

Reviewed by Brent Fulgham.

Part 2.

This patch adds a different LocalAuthentication prompt title for getAssertion.
It also polishes the text used for makeCredential.

Besides that, it also enhances the iOS title strings.

Source/WebCore:

* en.lproj/Localizable.strings:
* platform/LocalizedStrings.cpp:
(WebCore::getAssertionTouchIDPromptTitle):
* platform/LocalizedStrings.h:

Source/WebKit:

* UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
(WebKit::LocalAuthenticator::continueMakeCredentialAfterDecidePolicy):
(WebKit::LocalAuthenticator::continueGetAssertionAfterResponseSelected):
* UIProcess/WebAuthentication/Cocoa/LocalConnection.h:
* UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
(WebKit::LocalConnection::verifyUser const):
* UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
* UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
(WebKit::MockLocalConnection::verifyUser const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@258961 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/en.lproj/Localizable.strings
Source/WebCore/platform/LocalizedStrings.cpp
Source/WebCore/platform/LocalizedStrings.h
Source/WebKit/ChangeLog
Source/WebKit/Sources.txt
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.h
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm
Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm
Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h

index 0f26670..88a3f56 100644 (file)
@@ -1,3 +1,23 @@
+2020-03-24  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthn] Customize a bit more on the macOS LocalAuthentication prompt
+        https://bugs.webkit.org/show_bug.cgi?id=208703
+        <rdar://problem/60136974>
+
+        Reviewed by Brent Fulgham.
+
+        Part 2.
+
+        This patch adds a different LocalAuthentication prompt title for getAssertion.
+        It also polishes the text used for makeCredential.
+
+        Besides that, it also enhances the iOS title strings.
+
+        * en.lproj/Localizable.strings:
+        * platform/LocalizedStrings.cpp:
+        (WebCore::getAssertionTouchIDPromptTitle):
+        * platform/LocalizedStrings.h:
+
 2020-03-24  Chris Dumez  <cdumez@apple.com>
 
         Function passed to addEventListener may get garbage collected before the event listener is even added
index b875205..4c90a54 100644 (file)
@@ -1,3 +1,9 @@
+/* Allow the specified bundle to use Touch ID to sign in to the specified website on this device */
+"“%@” would like to use Touch ID for “%@”." = "“%@” would like to use Touch ID for “%@”.";
+
+/* "Allow the specified bundle to sign in to the specified website */
+"“%@” would like to sign in to “%@”." = "“%@” would like to sign in to “%@”.";
+
 /* accessibility help text for media controller time value >= 1 day */
 "%1$d days %2$d hours %3$d minutes %4$d seconds" = "%1$d days %2$d hours %3$d minutes %4$d seconds";
 
 /* Video Enter Full Screen context menu item */
 "Enter Full Screen" = "Enter Full Screen";
 
-/* Use passcode as a fallback to sign into this website */
-"Enter passcode to sign into this website." = "Enter passcode to sign into this website.";
-
 /* menu item */
 "Enter Picture in Picture" = "Enter Picture in Picture";
 
 /* Unwanted software warning */
 "This website may try to trick you into installing software that harms your browsing experience, like changing your settings without your permission or showing you unwanted ads. Once installed, it may be difficult to remove." = "This website may try to trick you into installing software that harms your browsing experience, like changing your settings without your permission or showing you unwanted ads. Once installed, it may be difficult to remove.";
 
+/* This website would like to use Touch ID */
+"This website would like to use Touch ID." = "This website would like to use Touch ID.";
+
 /* Informative text for requesting cross-site cookie and website data access. */
 "This will allow “%@” to track your activity." = "This will allow “%@” to track your activity.";
 
 /* prompt string in authentication panel */
 "To view this page, you must log in to this area on %@:" = "To view this page, you must log in to this area on %@:";
 
-/* Use Touch ID to sign into this website */
-"Touch ID to sign into this website." = "Touch ID to sign into this website.";
-
-/* Allow using Touch ID to sign into the specified website on this device */
-"Touch ID to allow signing into “%@” with Touch ID." = "Touch ID to allow signing into “%@” with Touch ID.";
+/* Use Touch ID to sign in to this website */
+"Touch ID to sign in to this website." = "Touch ID to sign in to this website.";
 
 /* Transformations context sub-menu item */
 "Transformations" = "Transformations";
index 4bbfa13..a90f882 100644 (file)
@@ -1208,20 +1208,29 @@ String unacceptableTLSCertificate()
 #endif
 
 #if ENABLE(WEB_AUTHN)
-String genericTouchIDPromptTitle()
+// On macOS, Touch ID prompt is not guaranteed to show on top of the UI client, and therefore additional
+// information is provided to help users to make decisions.
+#if PLATFORM(MAC)
+String makeCredentialTouchIDPromptTitle(const String& bundleName, const String& domain)
 {
-    return WEB_UI_STRING("Touch ID to sign into this website.", "Use Touch ID to sign into this website");
+    return formatLocalizedString(WEB_UI_CFSTRING("“%@” would like to use Touch ID for “%@”.", "Allow the specified bundle to use Touch ID to sign in to the specified website on this device"), bundleName.createCFString().get(), domain.createCFString().get());
 }
 
-String makeCredentialTouchIDPromptTitle(const String& domain)
+String getAssertionTouchIDPromptTitle(const String& bundleName, const String& domain)
 {
-    return formatLocalizedString(WEB_UI_CFSTRING("Touch ID to allow signing into “%@” with Touch ID.", "Allow using Touch ID to sign into the specified website on this device"), domain.createCFString().get());
+    return formatLocalizedString(WEB_UI_CFSTRING("“%@” would like to sign in to “%@”.", "Allow the specified bundle to sign in to the specified website"), bundleName.createCFString().get(), domain.createCFString().get());
+}
+#else
+String makeCredentialTouchIDPromptTitle(const String&, const String&)
+{
+    return WEB_UI_STRING("This website would like to use Touch ID.", "This website would like to use Touch ID");
 }
 
-String biometricFallbackPromptTitle()
+String getAssertionTouchIDPromptTitle(const String&, const String&)
 {
-    return WEB_UI_STRING("Enter passcode to sign into this website.", "Use passcode as a fallback to sign into this website");
+    return WEB_UI_STRING("Touch ID to sign in to this website.", "Use Touch ID to sign in to this website");
 }
-#endif
+#endif // PLATFORM(MAC)
+#endif // ENABLE(WEB_AUTHN)
 
 } // namespace WebCore
index 93bc8d5..71600c1 100644 (file)
@@ -340,9 +340,8 @@ namespace WebCore {
 #endif
 
 #if ENABLE(WEB_AUTHN)
-    WEBCORE_EXPORT String genericTouchIDPromptTitle();
-    WEBCORE_EXPORT String makeCredentialTouchIDPromptTitle(const String& domain);
-    WEBCORE_EXPORT String biometricFallbackPromptTitle();
+    WEBCORE_EXPORT String makeCredentialTouchIDPromptTitle(const String& bundleName, const String& domain);
+    WEBCORE_EXPORT String getAssertionTouchIDPromptTitle(const String& bundleName, const String& domain);
 #endif
 
 #if USE(GLIB) && defined(GETTEXT_PACKAGE)
index 6f6be18..f158657 100644 (file)
@@ -1,3 +1,28 @@
+2020-03-24  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthn] Customize a bit more on the macOS LocalAuthentication prompt
+        https://bugs.webkit.org/show_bug.cgi?id=208703
+        <rdar://problem/60136974>
+
+        Reviewed by Brent Fulgham.
+
+        Part 2.
+
+        This patch adds a different LocalAuthentication prompt title for getAssertion.
+        It also polishes the text used for makeCredential.
+
+        Besides that, it also enhances the iOS title strings.
+
+        * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
+        (WebKit::LocalAuthenticator::continueMakeCredentialAfterDecidePolicy):
+        (WebKit::LocalAuthenticator::continueGetAssertionAfterResponseSelected):
+        * UIProcess/WebAuthentication/Cocoa/LocalConnection.h:
+        * UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
+        (WebKit::LocalConnection::verifyUser const):
+        * UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
+        * UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
+        (WebKit::MockLocalConnection::verifyUser const):
+
 2020-03-24  Kate Cheney  <katherine_cheney@apple.com>
 
         Ignore in-app browser privacy checks for apps with com.apple.private.applemediaservices entitlement
index 1ad7b3b..f1d7509 100644 (file)
@@ -469,6 +469,7 @@ UIProcess/WebAuthentication/AuthenticatorManager.cpp
 UIProcess/WebAuthentication/AuthenticatorTransportService.cpp
 UIProcess/WebAuthentication/Authenticator.cpp
 UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp
+UIProcess/WebAuthentication/WebAuthenticationRequestData.cpp
 
 UIProcess/WebsiteData/WebDeviceOrientationAndMotionAccessController.cpp
 UIProcess/WebsiteData/WebsiteDataRecord.cpp
index 9778375..f233361 100644 (file)
@@ -143,13 +143,6 @@ static String getRpId(const Variant<PublicKeyCredentialCreationOptions, PublicKe
     return WTF::get<PublicKeyCredentialRequestOptions>(options).rpId;
 }
 
-static ClientDataType getClientDataType(const Variant<PublicKeyCredentialCreationOptions, PublicKeyCredentialRequestOptions>& options)
-{
-    if (WTF::holds_alternative<PublicKeyCredentialCreationOptions>(options))
-        return ClientDataType::Create;
-    return ClientDataType::Get;
-}
-
 } // namespace
 
 const size_t AuthenticatorManager::maxTransportNumber = 3;
index 9a38762..60d27c8 100644 (file)
@@ -263,7 +263,7 @@ void LocalAuthenticator::continueMakeCredentialAfterDecidePolicy(LocalAuthentica
 
         weakThis->continueMakeCredentialAfterUserVerification(accessControl.get(), verification, context);
     };
-    m_connection->verifyUser(creationOptions.rp.id, accessControlRef, WTFMove(callback));
+    m_connection->verifyUser(creationOptions.rp.id, getClientDataType(requestData().options), accessControlRef, WTFMove(callback));
 }
 
 void LocalAuthenticator::continueMakeCredentialAfterUserVerification(SecAccessControlRef accessControlRef, LocalConnection::UserVerification verification, LAContext *context)
@@ -491,7 +491,7 @@ void LocalAuthenticator::continueGetAssertionAfterResponseSelected(Ref<WebCore::
 
         weakThis->continueGetAssertionAfterUserVerification(WTFMove(response), verification, context);
     };
-    m_connection->verifyUser(requestOptions.rpId, accessControlRef, WTFMove(callback));
+    m_connection->verifyUser(requestOptions.rpId, getClientDataType(requestData().options), accessControlRef, WTFMove(callback));
 }
 
 void LocalAuthenticator::continueGetAssertionAfterUserVerification(Ref<WebCore::AuthenticatorAssertionResponse>&& response, LocalConnection::UserVerification verification, LAContext *context)
index 65840be..a4a2f94 100644 (file)
@@ -37,6 +37,7 @@ OBJC_CLASS LAContext;
 
 namespace WebCore {
 class AuthenticatorAssertionResponse;
+enum class ClientDataType : bool;
 }
 
 namespace WebKit {
@@ -59,10 +60,11 @@ public:
     using UserVerificationCallback = CompletionHandler<void(UserVerification, LAContext *)>;
 
     LocalConnection() = default;
+    // FIXME(183534): Invalidate the LAContext.
     virtual ~LocalConnection() = default;
 
     // Overrided by MockLocalConnection.
-    virtual void verifyUser(const String& rpId, SecAccessControlRef, UserVerificationCallback&&) const;
+    virtual void verifyUser(const String& rpId, WebCore::ClientDataType, SecAccessControlRef, UserVerificationCallback&&) const;
     virtual RetainPtr<SecKeyRef> createCredentialPrivateKey(LAContext *, SecAccessControlRef, const String& secAttrLabel, NSData *secAttrApplicationTag) const;
     virtual void getAttestation(SecKeyRef, NSData *authData, NSData *hash, AttestationCallback&&) const;
     virtual void filterResponses(HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&) const { };
index a1555c6..83bdaf1 100644 (file)
 #import "LocalAuthenticationSoftLink.h"
 
 namespace WebKit {
+using namespace WebCore;
 
-void LocalConnection::verifyUser(const String& rpId, SecAccessControlRef accessControl, UserVerificationCallback&& completionHandler) const
+namespace {
+static String bundleName()
 {
+    String bundleName;
+
+#if PLATFORM(MAC)
+    bundleName = [[NSRunningApplication currentApplication] localizedName];
+#endif
+
+    return bundleName;
+}
+} // namespace
+
+void LocalConnection::verifyUser(const String& rpId, ClientDataType type, SecAccessControlRef accessControl, UserVerificationCallback&& completionHandler) const
+{
+    String title;
+    switch (type) {
+    case ClientDataType::Create:
+        title = makeCredentialTouchIDPromptTitle(bundleName(), rpId);
+        break;
+    case ClientDataType::Get:
+        title = getAssertionTouchIDPromptTitle(bundleName(), rpId);
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
     auto context = adoptNS([allocLAContextInstance() init]);
 
     auto options = adoptNS([[NSMutableDictionary alloc] init]);
     if ([context biometryType] == LABiometryTypeTouchID) {
-#if PLATFORM(IOS)
-        [options setObject:WebCore::genericTouchIDPromptTitle() forKey:@(LAOptionAuthenticationTitle)];
-        ASSERT_UNUSED(rpId, rpId);
-#else
-        [options setObject:WebCore::makeCredentialTouchIDPromptTitle(rpId) forKey:@(LAOptionAuthenticationTitle)];
-#endif
+        [options setObject:title forKey:@(LAOptionAuthenticationTitle)];
         [options setObject:@NO forKey:@(LAOptionFallbackVisible)];
     }
-#if PLATFORM(IOS)
-    [options setObject:WebCore::biometricFallbackPromptTitle() forKey:@(LAOptionPasscodeTitle)];
-#endif
 
     auto reply = makeBlockPtr([context, completionHandler = WTFMove(completionHandler)] (NSDictionary *, NSError *error) mutable {
         ASSERT(!RunLoop::isMain());
index 012edb9..047c632 100644 (file)
@@ -37,7 +37,7 @@ public:
     explicit MockLocalConnection(const WebCore::MockWebAuthenticationConfiguration&);
 
 private:
-    void verifyUser(const String&, SecAccessControlRef, UserVerificationCallback&&) const final;
+    void verifyUser(const String&, WebCore::ClientDataType, SecAccessControlRef, UserVerificationCallback&&) const final;
     RetainPtr<SecKeyRef> createCredentialPrivateKey(LAContext *, SecAccessControlRef, const String& secAttrLabel, NSData *secAttrApplicationTag) const final;
     void getAttestation(SecKeyRef, NSData *authData, NSData *hash, AttestationCallback&&) const final;
     void filterResponses(HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&) const final;
index 3d5d401..74887f1 100644 (file)
@@ -44,7 +44,7 @@ MockLocalConnection::MockLocalConnection(const WebCore::MockWebAuthenticationCon
 {
 }
 
-void MockLocalConnection::verifyUser(const String&, SecAccessControlRef, UserVerificationCallback&& callback) const
+void MockLocalConnection::verifyUser(const String&, WebCore::ClientDataType, SecAccessControlRef, UserVerificationCallback&& callback) const
 {
     // Mock async operations.
     RunLoop::main().dispatch([configuration = m_configuration, callback = WTFMove(callback)]() mutable {
diff --git a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.cpp b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.cpp
new file mode 100644 (file)
index 0000000..70e9371
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebAuthenticationRequestData.h"
+
+#if ENABLE(WEB_AUTHN)
+
+namespace WebKit {
+using namespace WebCore;
+
+ClientDataType getClientDataType(const Variant<PublicKeyCredentialCreationOptions, PublicKeyCredentialRequestOptions>& options)
+{
+    if (WTF::holds_alternative<PublicKeyCredentialCreationOptions>(options))
+        return ClientDataType::Create;
+    return ClientDataType::Get;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(WEB_AUTHN)
index 8edb39c..2f61345 100644 (file)
@@ -33,6 +33,7 @@
 #include <WebCore/GlobalFrameIdentifier.h>
 #include <WebCore/PublicKeyCredentialCreationOptions.h>
 #include <WebCore/PublicKeyCredentialRequestOptions.h>
+#include <WebCore/WebAuthenticationConstants.h>
 #include <wtf/Variant.h>
 #include <wtf/Vector.h>
 #include <wtf/WeakPtr.h>
@@ -51,6 +52,8 @@ struct WebAuthenticationRequestData {
     WebKit::FrameInfoData frameInfo;
 };
 
+WebCore::ClientDataType getClientDataType(const Variant<WebCore::PublicKeyCredentialCreationOptions, WebCore::PublicKeyCredentialRequestOptions>&);
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)