Title: [272184] trunk
Revision
272184
Author
[email protected]
Date
2021-02-01 18:49:59 -0800 (Mon, 01 Feb 2021)

Log Message

[WebAuthn] Optimize _WKWebAuthenticationPanelDelegate for native API
https://bugs.webkit.org/show_bug.cgi?id=221125
<rdar://problem/71509141>

Reviewed by Brent Fulgham.

Source/WebKit:

This patch mainly does the following few things:
1. It connects the new SPI with the existing mock testing infrastructure such that we can mock test it.
2. It adds a new mode in AuthenticatorManager to connect it to the new _WKWebAuthenticationPanelDelegate object.
3. It adss a new SPI to _WKWebAuthenticationPanelDelegate: -[panel:requestLAContextForUserVerificationWithCompletionHandler:],
and adds a new method within _WKWebAuthenticationAssertionResponse to accept an LAContext from the caller to unlock
the keychain.
4. It enables -[_WKWebAuthenticationPanel cancel] to use the new cancel method.

Covered by API tests.

* UIProcess/API/APIWebAuthenticationAssertionResponse.h:
Accepts a LAContext object.

* UIProcess/API/APIWebAuthenticationPanel.cpp:
(API::WebAuthenticationPanel::WebAuthenticationPanel):
(API::WebAuthenticationPanel::handleRequest):
(API::WebAuthenticationPanel::cancel const):
(API::WebAuthenticationPanel::setMockConfiguration):
* UIProcess/API/APIWebAuthenticationPanel.h:
* UIProcess/API/APIWebAuthenticationPanelClient.h:
(API::WebAuthenticationPanelClient::requestLAContextForUserVerification const):
Adds new SPI and mocking.

* UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h:
* UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm:
(-[_WKWebAuthenticationAssertionResponse setLAContext:]):
Accepts a LAContext object.

* UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
* UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
(-[_WKWebAuthenticationPanel setMockConfiguration:]):
* UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h:
Adds new SPI and mocking.

* UIProcess/WebAuthentication/AuthenticatorManager.cpp:
(WebKit::AuthenticatorManager::handleRequest):
(WebKit::AuthenticatorManager::enableModernWebAuthentication):
(WebKit::AuthenticatorManager::enableNativeSupport):
(WebKit::AuthenticatorManager::authenticatorAdded):
(WebKit::AuthenticatorManager::requestLAContextForUserVerification):
(WebKit::AuthenticatorManager::runPresenter):
(WebKit::AuthenticatorManager::dispatchPanelClientCall const):
* UIProcess/WebAuthentication/AuthenticatorManager.h:
Adds a new mode to power the native API.

* UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h:
* UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:
(WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
(WebKit::WebAuthenticationPanelClient::requestLAContextForUserVerification const):
Accepts a LAContext object.

* UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
* UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
(WebKit::MockLocalConnection::verifyUser):
Adds new mocking functions.

* UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
Adds the new weak panel.

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
(-[TestWebAuthenticationPanelDelegate panel:selectAssertionResponse:source:completionHandler:]):
(-[TestWebAuthenticationPanelDelegate panel:requestLAContextForUserVerificationWithCompletionHandler:]):
(TestWebKitAPI::WebCore::reset):
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (272183 => 272184)


--- trunk/Source/WebKit/ChangeLog	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/ChangeLog	2021-02-02 02:49:59 UTC (rev 272184)
@@ -1,3 +1,70 @@
+2021-02-01  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Optimize _WKWebAuthenticationPanelDelegate for native API
+        https://bugs.webkit.org/show_bug.cgi?id=221125
+        <rdar://problem/71509141>
+
+        Reviewed by Brent Fulgham.
+
+        This patch mainly does the following few things:
+        1. It connects the new SPI with the existing mock testing infrastructure such that we can mock test it.
+        2. It adds a new mode in AuthenticatorManager to connect it to the new _WKWebAuthenticationPanelDelegate object.
+        3. It adss a new SPI to _WKWebAuthenticationPanelDelegate: -[panel:requestLAContextForUserVerificationWithCompletionHandler:],
+        and adds a new method within _WKWebAuthenticationAssertionResponse to accept an LAContext from the caller to unlock
+        the keychain.
+        4. It enables -[_WKWebAuthenticationPanel cancel] to use the new cancel method.
+
+        Covered by API tests.
+
+        * UIProcess/API/APIWebAuthenticationAssertionResponse.h:
+        Accepts a LAContext object.
+
+        * UIProcess/API/APIWebAuthenticationPanel.cpp:
+        (API::WebAuthenticationPanel::WebAuthenticationPanel):
+        (API::WebAuthenticationPanel::handleRequest):
+        (API::WebAuthenticationPanel::cancel const):
+        (API::WebAuthenticationPanel::setMockConfiguration):
+        * UIProcess/API/APIWebAuthenticationPanel.h:
+        * UIProcess/API/APIWebAuthenticationPanelClient.h:
+        (API::WebAuthenticationPanelClient::requestLAContextForUserVerification const):
+        Adds new SPI and mocking.
+
+        * UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h:
+        * UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm:
+        (-[_WKWebAuthenticationAssertionResponse setLAContext:]):
+        Accepts a LAContext object.
+
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h:
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm:
+        (-[_WKWebAuthenticationPanel setMockConfiguration:]):
+        * UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h:
+        Adds new SPI and mocking.
+
+        * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+        (WebKit::AuthenticatorManager::handleRequest):
+        (WebKit::AuthenticatorManager::enableModernWebAuthentication):
+        (WebKit::AuthenticatorManager::enableNativeSupport):
+        (WebKit::AuthenticatorManager::authenticatorAdded):
+        (WebKit::AuthenticatorManager::requestLAContextForUserVerification):
+        (WebKit::AuthenticatorManager::runPresenter):
+        (WebKit::AuthenticatorManager::dispatchPanelClientCall const):
+        * UIProcess/WebAuthentication/AuthenticatorManager.h:
+        Adds a new mode to power the native API.
+
+        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h:
+        * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm:
+        (WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient):
+        (WebKit::WebAuthenticationPanelClient::requestLAContextForUserVerification const):
+        Accepts a LAContext object.
+
+        * UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
+        * UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
+        (WebKit::MockLocalConnection::verifyUser):
+        Adds new mocking functions.
+
+        * UIProcess/WebAuthentication/WebAuthenticationRequestData.h:
+        Adds the new weak panel.
+
 2021-02-01  Michael Catanzaro  <[email protected]>
 
         [WPE][GTK] flatpak-spawn subsandbox clears environment variables, breaks EphyPermissionsManager

Modified: trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationAssertionResponse.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationAssertionResponse.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationAssertionResponse.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -43,6 +43,8 @@
     const WTF::String& displayName() const { return m_response->displayName(); }
     RefPtr<Data> userHandle() const;
 
+    void setLAContext(LAContext *context) { m_response->setLAContext(context); }
+
     WebCore::AuthenticatorAssertionResponse* response() { return m_response.ptr(); }
 
 private:

Modified: trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp	2021-02-02 02:49:59 UTC (rev 272184)
@@ -30,6 +30,7 @@
 
 #include "APIWebAuthenticationPanelClient.h"
 #include "AuthenticatorManager.h"
+#include "MockAuthenticatorManager.h"
 #include <WebCore/WebAuthenticationConstants.h>
 
 namespace API {
@@ -45,6 +46,7 @@
     : m_manager(makeUnique<AuthenticatorManager>())
     , m_client(makeUniqueRef<WebAuthenticationPanelClient>())
 {
+    m_manager->enableNativeSupport();
 }
 
 WebAuthenticationPanel::WebAuthenticationPanel(const AuthenticatorManager& manager, const WTF::String& rpId, const TransportSet& transports, ClientDataType type)
@@ -68,15 +70,32 @@
 void WebAuthenticationPanel::handleRequest(WebAuthenticationRequestData&& request, Callback&& callback)
 {
     ASSERT(m_manager);
+    request.weakPanel = makeWeakPtr(*this);
     m_manager->handleRequest(WTFMove(request), WTFMove(callback));
 }
 
 void WebAuthenticationPanel::cancel() const
 {
-    if (m_weakManager)
+    if (m_weakManager) {
         m_weakManager->cancelRequest(*this);
+        return;
+    }
+
+    m_manager->cancel();
 }
 
+void WebAuthenticationPanel::setMockConfiguration(WebCore::MockWebAuthenticationConfiguration&& configuration)
+{
+    ASSERT(m_manager);
+
+    if (!m_manager->isMock()) {
+        m_manager = makeUnique<MockAuthenticatorManager>(WTFMove(configuration));
+        m_manager->enableNativeSupport();
+        return;
+    }
+    static_cast<MockAuthenticatorManager*>(m_manager.get())->setTestConfiguration(WTFMove(configuration));
+}
+
 void WebAuthenticationPanel::setClient(UniqueRef<WebAuthenticationPanelClient>&& client)
 {
     m_client = WTFMove(client);

Modified: trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -39,6 +39,7 @@
 class AuthenticatorResponse;
 
 struct ExceptionData;
+struct MockWebAuthenticationConfiguration;
 }
 
 namespace WebKit {
@@ -61,6 +62,7 @@
 
     void handleRequest(WebKit::WebAuthenticationRequestData&&, Callback&&);
     void cancel() const;
+    void setMockConfiguration(WebCore::MockWebAuthenticationConfiguration&&);
 
     const WebAuthenticationPanelClient& client() const { return m_client.get(); }
     void setClient(UniqueRef<WebAuthenticationPanelClient>&&);

Modified: trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -52,6 +52,7 @@
     virtual void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&& completionHandler) const { completionHandler(WTF::String()); }
     virtual void selectAssertionResponse(Vector<Ref<WebCore::AuthenticatorAssertionResponse>>&&, WebKit::WebAuthenticationSource, CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)>&& completionHandler) const { completionHandler(nullptr); }
     virtual void decidePolicyForLocalAuthenticator(CompletionHandler<void(WebKit::LocalAuthenticatorPolicy)>&& completionHandler) const { completionHandler(WebKit::LocalAuthenticatorPolicy::Disallow); }
+    virtual void requestLAContextForUserVerification(CompletionHandler<void(LAContext *)>&& completionHandler) const { completionHandler(nullptr); }
 };
 
 } // namespace API

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -28,6 +28,8 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+@class LAContext;
+
 WK_CLASS_AVAILABLE(macos(11.0), ios(14.0))
 @interface _WKWebAuthenticationAssertionResponse : NSObject
 
@@ -35,6 +37,8 @@
 @property (nonatomic, readonly, copy) NSString *displayName;
 @property (nonatomic, readonly, copy) NSData *userHandle;
 
+- (void)setLAContext:(LAContext *)context WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 NS_ASSUME_NONNULL_END

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm	2021-02-02 02:49:59 UTC (rev 272184)
@@ -54,6 +54,16 @@
     return wrapper(_response->userHandle());
 }
 
+#endif // ENABLE(WEB_AUTHN)
+
+- (void)setLAContext:(LAContext *)context
+{
+#if ENABLE(WEB_AUTHN)
+    _response->setLAContext(context);
+#endif
+}
+
+#if ENABLE(WEB_AUTHN)
 #pragma mark WKObject protocol implementation
 
 - (API::Object&)_apiObject

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -34,6 +34,7 @@
 @class _WKPublicKeyCredentialRequestOptions;
 @class _WKWebAuthenticationAssertionResponse;
 @class _WKWebAuthenticationPanel;
+@class LAContext;
 
 typedef NS_ENUM(NSInteger, _WKWebAuthenticationPanelResult) {
     _WKWebAuthenticationPanelResultUnavailable,
@@ -78,17 +79,18 @@
     _WKWebAuthenticationSourceExternal,
 } WK_API_AVAILABLE(macos(11.0), ios(14.0));
 
-// FIXME: <rdar://problem/71509141> Optimize the delegate for the AuthenticationService.framework.
 @protocol _WKWebAuthenticationPanelDelegate <NSObject>
 
 @optional
 
-- (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
-- (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
-- (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:(NSUInteger)retries completionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
+- (void)panel:(_WKWebAuthenticationPanel *)panel updateWebAuthenticationPanel:(_WKWebAuthenticationPanelUpdate)update WK_API_AVAILABLE(macos(11.0), ios(14.0));
+- (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:(NSUInteger)retries completionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
 - (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponse:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses source:(_WKWebAuthenticationSource)source completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
+- (void)panel:(_WKWebAuthenticationPanel *)panel requestLAContextForUserVerificationWithCompletionHandler:(void (^)(LAContext *context))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
+// FIXME: <rdar://problem/71509848> Deprecate the following delegates.
 - (void)panel:(_WKWebAuthenticationPanel *)panel decidePolicyForLocalAuthenticatorWithCompletionHandler:(void (^)(_WKLocalAuthenticatorPolicy policy))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
-
+- (void)panel:(_WKWebAuthenticationPanel *)panel dismissWebAuthenticationPanelWithResult:(_WKWebAuthenticationResult)result WK_API_AVAILABLE(macos(11.0), ios(14.0));
 @end
 
 WK_CLASS_AVAILABLE(macos(10.15.4), ios(13.4))

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm	2021-02-02 02:49:59 UTC (rev 272184)
@@ -44,6 +44,7 @@
 #import "_WKPublicKeyCredentialUserEntity.h"
 #import <WebCore/AuthenticatorResponse.h>
 #import <WebCore/AuthenticatorResponseData.h>
+#import <WebCore/MockWebAuthenticationConfiguration.h>
 #import <WebCore/PublicKeyCredentialCreationOptions.h>
 #import <WebCore/PublicKeyCredentialRequestOptions.h>
 #import <WebCore/WebAuthenticationConstants.h>
@@ -347,7 +348,7 @@
             handler(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:nil]);
         });
     };
-    _panel->handleRequest({ vectorFromNSData(hash), [_WKWebAuthenticationPanel convertToCoreCreationOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, true, String() }, WTFMove(callback));
+    _panel->handleRequest({ vectorFromNSData(hash), [_WKWebAuthenticationPanel convertToCoreCreationOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, true, String(), nullptr }, WTFMove(callback));
 #endif
 }
 
@@ -394,7 +395,7 @@
             handler(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:nil]);
         });
     };
-    _panel->handleRequest({ vectorFromNSData(hash), [_WKWebAuthenticationPanel convertToCoreRequestOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, true, String() }, WTFMove(callback));
+    _panel->handleRequest({ vectorFromNSData(hash), [_WKWebAuthenticationPanel convertToCoreRequestOptionsWithOptions:options], nullptr, WebKit::WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, true, String(), nullptr }, WTFMove(callback));
 #endif
 }
 
@@ -407,7 +408,22 @@
 #endif
 }
 
+- (void)setMockConfiguration:(NSDictionary *)configuration
+{
 #if ENABLE(WEB_AUTHN)
+    WebCore::MockWebAuthenticationConfiguration::LocalConfiguration localConfiguration;
+    localConfiguration.userVerification = WebCore::MockWebAuthenticationConfiguration::UserVerification::Yes;
+    if (configuration[@"privateKeyBase64"])
+        localConfiguration.privateKeyBase64 = configuration[@"privateKeyBase64"];
+
+    WebCore::MockWebAuthenticationConfiguration mockConfiguration;
+    mockConfiguration.local = WTFMove(localConfiguration);
+
+    _panel->setMockConfiguration(WTFMove(mockConfiguration));
+#endif
+}
+
+#if ENABLE(WEB_AUTHN)
 #pragma mark WKObject protocol implementation
 
 - (API::Object&)_apiObject

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKWebAuthenticationPanelForTesting.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -35,8 +35,10 @@
 WK_CLASS_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA))
 @interface _WKWebAuthenticationPanel (WKTesting)
 
-// FIXME: <rdar://problem/71509714> Introduces mock testing.
 + (WebCore::PublicKeyCredentialCreationOptions)convertToCoreCreationOptionsWithOptions:(_WKPublicKeyCredentialCreationOptions *)options WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 + (WebCore::PublicKeyCredentialRequestOptions)convertToCoreRequestOptionsWithOptions:(_WKPublicKeyCredentialRequestOptions *)options WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+// For details of configuration, refer to MockWebAuthenticationConfiguration.h.
+@property (nonatomic, copy) NSDictionary *mockConfiguration;
+
 @end

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp	2021-02-02 02:49:59 UTC (rev 272184)
@@ -165,10 +165,9 @@
     // 2. Ask clients to show appropriate UI if any and then start the request.
     initTimeOutTimer();
 
-    // FIXME<rdar://problem/70822834>: The m_webAuthenticationModernEnabled is used to determine
-    // whether or not we are in the UIProcess.
+    // FIXME<rdar://problem/70822834>: The m_mode is used to determine whether or not we are in the UIProcess.
     // If so, continue to the old route. Otherwise, use the modern WebAuthn process way.
-    if (!m_webAuthenticationModernEnabled) {
+    if (m_mode == Mode::Compatible) {
         runPanel();
         return;
     }
@@ -209,9 +208,14 @@
 
 void AuthenticatorManager::enableModernWebAuthentication()
 {
-    m_webAuthenticationModernEnabled = true;
+    m_mode = Mode::Modern;
 }
 
+void AuthenticatorManager::enableNativeSupport()
+{
+    m_mode = Mode::Native;
+}
+
 void AuthenticatorManager::clearStateAsync()
 {
     RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
@@ -236,7 +240,7 @@
     ASSERT(RunLoop::isMain());
     authenticator->setObserver(*this);
     authenticator->handleRequest(m_pendingRequestData);
-    authenticator->setWebAuthenticationModernEnabled(m_webAuthenticationModernEnabled);
+    authenticator->setWebAuthenticationModernEnabled(m_mode != Mode::Compatible);
     auto addResult = m_authenticators.add(WTFMove(authenticator));
     ASSERT_UNUSED(addResult, addResult.isNewEntry);
 }
@@ -354,12 +358,14 @@
 
 void AuthenticatorManager::requestLAContextForUserVerification(CompletionHandler<void(LAContext *)>&& completionHandler)
 {
-    if (!m_presenter) {
-        completionHandler(nullptr);
+    if (m_presenter) {
+        m_presenter->requestLAContextForUserVerification(WTFMove(completionHandler));
         return;
     }
 
-    m_presenter->requestLAContextForUserVerification(WTFMove(completionHandler));
+    dispatchPanelClientCall([completionHandler = WTFMove(completionHandler)] (const API::WebAuthenticationPanel& panel) mutable {
+        panel.client().requestLAContextForUserVerification(WTFMove(completionHandler));
+    });
 }
 
 void AuthenticatorManager::cancelRequest()
@@ -444,10 +450,14 @@
 void AuthenticatorManager::runPresenter()
 {
     // Get available transports and start discovering authenticators on them.
-    auto& options = m_pendingRequestData.options;
     auto transports = getTransports();
     startDiscovery(transports);
 
+    // For native API support, we skip the UI part. The native API will handle that.
+    if (m_mode == Mode::Native)
+        return;
+
+    auto& options = m_pendingRequestData.options;
     m_presenter = makeUnique<AuthenticatorPresenterCoordinator>(*this, getRpId(options), transports, getClientDataType(options));
 }
 
@@ -488,15 +498,19 @@
 
 void AuthenticatorManager::dispatchPanelClientCall(Function<void(const API::WebAuthenticationPanel&)>&& call) const
 {
-    if (auto* panel = m_pendingRequestData.panel.get()) {
-        // Call delegates in the next run loop to prevent clients' reentrance that would potentially modify the state
-        // of the current run loop in unexpected ways.
-        RunLoop::main().dispatch([weakPanel = makeWeakPtr(*panel), call = WTFMove(call)] () {
-            if (!weakPanel)
-                return;
-            call(*weakPanel);
-        });
-    }
+    auto weakPanel = m_pendingRequestData.weakPanel;
+    if (!weakPanel)
+        weakPanel = makeWeakPtr(*m_pendingRequestData.panel.get());
+    if (!weakPanel)
+        return;
+
+    // Call delegates in the next run loop to prevent clients' reentrance that would potentially modify the state
+    // of the current run loop in unexpected ways.
+    RunLoop::main().dispatch([weakPanel = WTFMove(weakPanel), call = WTFMove(call)] () {
+        if (!weakPanel)
+            return;
+        call(*weakPanel);
+    });
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -71,6 +71,7 @@
     virtual bool isMock() const { return false; }
 
     void enableModernWebAuthentication();
+    void enableNativeSupport();
 
 protected:
     RunLoop::Timer<AuthenticatorManager>& requestTimeOutTimer() { return m_requestTimeOutTimer; }
@@ -79,6 +80,12 @@
     void invokePendingCompletionHandler(Respond&&);
 
 private:
+    enum class Mode {
+        Compatible,
+        Modern,
+        Native,
+    };
+
     // AuthenticatorTransportService::Observer
     void authenticatorAdded(Ref<Authenticator>&&) final;
     void serviceStatusUpdated(WebAuthenticationStatus) final;
@@ -117,7 +124,7 @@
     Vector<UniqueRef<AuthenticatorTransportService>> m_services;
     HashSet<Ref<Authenticator>> m_authenticators;
 
-    bool m_webAuthenticationModernEnabled { false };
+    Mode m_mode { Mode::Compatible };
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -52,6 +52,7 @@
     void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&&) const final;
     void selectAssertionResponse(Vector<Ref<WebCore::AuthenticatorAssertionResponse>>&&, WebAuthenticationSource, CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)>&&) const final;
     void decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&&) const final;
+    void requestLAContextForUserVerification(CompletionHandler<void(LAContext *)>&&) const final;
 
     _WKWebAuthenticationPanel *m_panel;
     WeakObjCPtr<id <_WKWebAuthenticationPanelDelegate> > m_delegate;
@@ -62,6 +63,7 @@
         bool panelRequestPinWithRemainingRetriesCompletionHandler : 1;
         bool panelSelectAssertionResponseSourceCompletionHandler : 1;
         bool panelDecidePolicyForLocalAuthenticatorCompletionHandler : 1;
+        bool panelRequestLAContextForUserVerificationCompletionHandler : 1;
     } m_delegateMethods;
 };
 

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm	2021-02-02 02:49:59 UTC (rev 272184)
@@ -50,6 +50,7 @@
     m_delegateMethods.panelRequestPinWithRemainingRetriesCompletionHandler = [delegate respondsToSelector:@selector(panel:requestPINWithRemainingRetries:completionHandler:)];
     m_delegateMethods.panelSelectAssertionResponseSourceCompletionHandler = [delegate respondsToSelector:@selector(panel:selectAssertionResponse:source:completionHandler:)];
     m_delegateMethods.panelDecidePolicyForLocalAuthenticatorCompletionHandler = [delegate respondsToSelector:@selector(panel:decidePolicyForLocalAuthenticatorWithCompletionHandler:)];
+    m_delegateMethods.panelRequestLAContextForUserVerificationCompletionHandler = [delegate respondsToSelector:@selector(panel:requestLAContextForUserVerificationWithCompletionHandler:)];
 }
 
 RetainPtr<id <_WKWebAuthenticationPanelDelegate> > WebAuthenticationPanelClient::delegate()
@@ -217,6 +218,28 @@
     }).get()];
 }
 
+void WebAuthenticationPanelClient::requestLAContextForUserVerification(CompletionHandler<void(LAContext *)>&& completionHandler) const
+{
+    if (!m_delegateMethods.panelRequestLAContextForUserVerificationCompletionHandler) {
+        completionHandler(nullptr);
+        return;
+    }
+
+    auto delegate = m_delegate.get();
+    if (!delegate) {
+        completionHandler(nullptr);
+        return;
+    }
+
+    auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(panel:requestLAContextForUserVerificationWithCompletionHandler:));
+    [delegate panel:m_panel requestLAContextForUserVerificationWithCompletionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](LAContext *context) mutable {
+        if (checker->completionHandlerHasBeenCalled())
+            return;
+        checker->didCallCompletionHandler();
+        completionHandler(context);
+    }).get()];
+}
+
 } // namespace WebKit
 
 #endif // ENABLE(WEB_AUTHN)

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -38,6 +38,7 @@
 
 private:
     void verifyUser(const String&, WebCore::ClientDataType, SecAccessControlRef, UserVerificationCallback&&) final;
+    void verifyUser(SecAccessControlRef, LAContext *, CompletionHandler<void(UserVerification)>&&) 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(Vector<Ref<WebCore::AuthenticatorAssertionResponse>>&) const final;

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm	2021-02-02 02:49:59 UTC (rev 272184)
@@ -67,6 +67,27 @@
     });
 }
 
+void MockLocalConnection::verifyUser(SecAccessControlRef, LAContext *, CompletionHandler<void(UserVerification)>&& callback)
+{
+    // Mock async operations.
+    RunLoop::main().dispatch([configuration = m_configuration, callback = WTFMove(callback)]() mutable {
+        ASSERT(configuration.local);
+
+        UserVerification userVerification = UserVerification::No;
+        switch (configuration.local->userVerification) {
+        case MockWebAuthenticationConfiguration::UserVerification::No:
+            break;
+        case MockWebAuthenticationConfiguration::UserVerification::Yes:
+            userVerification = UserVerification::Yes;
+            break;
+        case MockWebAuthenticationConfiguration::UserVerification::Cancel:
+            userVerification = UserVerification::Cancel;
+        }
+
+        callback(userVerification);
+    });
+}
+
 RetainPtr<SecKeyRef> MockLocalConnection::createCredentialPrivateKey(LAContext *, SecAccessControlRef, const String& secAttrLabel, NSData *secAttrApplicationTag) const
 {
     ASSERT(m_configuration.local);

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticationRequestData.h	2021-02-02 02:49:59 UTC (rev 272184)
@@ -55,6 +55,7 @@
 
     bool processingUserGesture;
     String cachedPin; // Only used to improve NFC Client PIN experience.
+    WeakPtr<API::WebAuthenticationPanel> weakPanel;
 };
 
 WebCore::ClientDataType getClientDataType(const Variant<WebCore::PublicKeyCredentialCreationOptions, WebCore::PublicKeyCredentialRequestOptions>&);

Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp (272183 => 272184)


--- trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp	2021-02-02 02:49:59 UTC (rev 272184)
@@ -57,12 +57,12 @@
 
 void WebAuthenticatorCoordinatorProxy::makeCredential(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialCreationOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
 {
-    handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String() }, WTFMove(handler));
+    handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String(), nullptr }, WTFMove(handler));
 }
 
 void WebAuthenticatorCoordinatorProxy::getAssertion(FrameIdentifier frameId, FrameInfoData&& frameInfo, Vector<uint8_t>&& hash, PublicKeyCredentialRequestOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
 {
-    handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String() }, WTFMove(handler));
+    handleRequest({ WTFMove(hash), WTFMove(options), makeWeakPtr(m_webPageProxy), WebAuthenticationPanelResult::Unavailable, nullptr, GlobalFrameIdentifier { m_webPageProxy.webPageID(), frameId }, WTFMove(frameInfo), processingUserGesture, String(), nullptr }, WTFMove(handler));
 }
 
 void WebAuthenticatorCoordinatorProxy::handleRequest(WebAuthenticationRequestData&& data, RequestCompletionHandler&& handler)

Modified: trunk/Source/WebKit/WebAuthnProcess/WebAuthnConnectionToWebProcess.cpp (272183 => 272184)


--- trunk/Source/WebKit/WebAuthnProcess/WebAuthnConnectionToWebProcess.cpp	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Source/WebKit/WebAuthnProcess/WebAuthnConnectionToWebProcess.cpp	2021-02-02 02:49:59 UTC (rev 272184)
@@ -69,12 +69,12 @@
 
 void WebAuthnConnectionToWebProcess::makeCredential(Vector<uint8_t>&& hash, PublicKeyCredentialCreationOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
 {
-    handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, processingUserGesture, String() }, WTFMove(handler));
+    handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, processingUserGesture, String(), nullptr }, WTFMove(handler));
 }
 
 void WebAuthnConnectionToWebProcess::getAssertion(Vector<uint8_t>&& hash, PublicKeyCredentialRequestOptions&& options, bool processingUserGesture, RequestCompletionHandler&& handler)
 {
-    handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, processingUserGesture, String() }, WTFMove(handler));
+    handleRequest({ WTFMove(hash), WTFMove(options), nullptr, WebAuthenticationPanelResult::Unavailable, nullptr, WTF::nullopt, { }, processingUserGesture, String(), nullptr }, WTFMove(handler));
 }
 
 void WebAuthnConnectionToWebProcess::handleRequest(WebAuthenticationRequestData&& data, RequestCompletionHandler&& handler)

Modified: trunk/Tools/ChangeLog (272183 => 272184)


--- trunk/Tools/ChangeLog	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Tools/ChangeLog	2021-02-02 02:49:59 UTC (rev 272184)
@@ -1,3 +1,17 @@
+2021-02-01  Jiewen Tan  <[email protected]>
+
+        [WebAuthn] Optimize _WKWebAuthenticationPanelDelegate for native API
+        https://bugs.webkit.org/show_bug.cgi?id=221125
+        <rdar://problem/71509141>
+
+        Reviewed by Brent Fulgham.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm:
+        (-[TestWebAuthenticationPanelDelegate panel:selectAssertionResponse:source:completionHandler:]):
+        (-[TestWebAuthenticationPanelDelegate panel:requestLAContextForUserVerificationWithCompletionHandler:]):
+        (TestWebKitAPI::WebCore::reset):
+        (TestWebKitAPI::TEST):
+
 2021-02-01  Don Olmstead  <[email protected]>
 
         [webkitscmpy] Use shutil to find scm executable paths

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm (272183 => 272184)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2021-02-02 02:14:23 UTC (rev 272183)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm	2021-02-02 02:49:59 UTC (rev 272184)
@@ -78,6 +78,7 @@
     "RQ==";
 static String testUserEntityBundleBase64 = "omJpZEoAAQIDBAUGBwgJZG5hbWVkSm9obg=="; // { "id": h'00010203040506070809', "name": "John" }
 static String webAuthenticationPanelSelectedCredentialName;
+static bool laContextRequested = false;
 
 @interface TestWebAuthenticationPanelDelegate : NSObject <_WKWebAuthenticationPanelDelegate>
 @end
@@ -150,7 +151,10 @@
 - (void)panel:(_WKWebAuthenticationPanel *)panel selectAssertionResponse:(NSArray < _WKWebAuthenticationAssertionResponse *> *)responses source:(_WKWebAuthenticationSource)source completionHandler:(void (^)(_WKWebAuthenticationAssertionResponse *))completionHandler
 {
     if (responses.count == 1) {
-        completionHandler(responses[0]);
+        auto laContext = adoptNS([[LAContext alloc] init]);
+        [responses.firstObject setLAContext:laContext.get()];
+
+        completionHandler(responses.firstObject);
         return;
     }
 
@@ -157,8 +161,13 @@
     // Responses returned from LocalAuthenticator is in the order of LRU. Therefore, we use the last item to populate it to
     // the first to test its correctness.
     if (source == _WKWebAuthenticationSourceLocal) {
-        webAuthenticationPanelSelectedCredentialName = responses.lastObject.name;
-        completionHandler(responses.lastObject);
+        auto *object = responses.lastObject;
+
+        auto laContext = adoptNS([[LAContext alloc] init]);
+        [object setLAContext:laContext.get()];
+
+        webAuthenticationPanelSelectedCredentialName = object.name;
+        completionHandler(object);
         return;
     }
 
@@ -180,6 +189,12 @@
     completionHandler(localAuthenticatorPolicy);
 }
 
+- (void)panel:(_WKWebAuthenticationPanel *)panel requestLAContextForUserVerificationWithCompletionHandler:(void (^)(LAContext *context))completionHandler
+{
+    laContextRequested = true;
+    completionHandler(nil);
+}
+
 @end
 
 @interface TestWebAuthenticationPanelFakeDelegate : NSObject <_WKWebAuthenticationPanelDelegate>
@@ -323,6 +338,7 @@
     webAuthenticationPanelNullUserHandle = NO;
     localAuthenticatorPolicy = _WKLocalAuthenticatorPolicyDisallow;
     webAuthenticationPanelSelectedCredentialName = emptyString();
+    laContextRequested = false;
 }
 
 static void checkPanel(_WKWebAuthenticationPanel *panel, NSString *relyingPartyID, NSArray *transports, _WKWebAuthenticationType type)
@@ -1760,7 +1776,7 @@
     auto user = adoptNS([[_WKPublicKeyCredentialUserEntity alloc] initWithName:@"[email protected]" identifier:nsIdentifier displayName:@"J Appleseed"]);
     NSArray<_WKPublicKeyCredentialParameters *> *publicKeyCredentialParamaters = @[ parameters.get() ];
     auto options = adoptNS([[_WKPublicKeyCredentialCreationOptions alloc] initWithRelyingParty:rp.get() user:user.get() publicKeyCredentialParamaters:publicKeyCredentialParamaters]);
-    [options setTimeout:@120];
+    [options setTimeout:@10];
 
     auto panel = adoptNS([[_WKWebAuthenticationPanel alloc] init]);
     [panel makeCredentialWithHash:nsHash options:options.get() completionHandler:^(_WKAuthenticatorAttestationResponse *response, NSError *error) {
@@ -1773,6 +1789,46 @@
     Util::run(&webAuthenticationPanelRan);
 }
 
+// For macOS, only internal builds can sign keychain entitlemnets
+// which are required to run local authenticator tests.
+#if USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
+TEST(WebAuthenticationPanel, MakeCredentialLA)
+{
+    reset();
+
+    uint8_t identifier[] = { 0x01, 0x02, 0x03, 0x04 };
+    uint8_t hash[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+    NSData *nsIdentifier = [NSData dataWithBytes:identifier length:sizeof(identifier)];
+    NSData *nsHash = [NSData dataWithBytes:hash length:sizeof(hash)];
+    auto parameters = adoptNS([[_WKPublicKeyCredentialParameters alloc] initWithAlgorithm:@-7]);
+
+    auto rp = adoptNS([[_WKPublicKeyCredentialRelyingPartyEntity alloc] initWithName:@"example.com"]);
+    [rp setIdentifier:@"example.com"];
+    auto user = adoptNS([[_WKPublicKeyCredentialUserEntity alloc] initWithName:@"[email protected]" identifier:nsIdentifier displayName:@"J Appleseed"]);
+    NSArray<_WKPublicKeyCredentialParameters *> *publicKeyCredentialParamaters = @[ parameters.get() ];
+    auto options = adoptNS([[_WKPublicKeyCredentialCreationOptions alloc] initWithRelyingParty:rp.get() user:user.get() publicKeyCredentialParamaters:publicKeyCredentialParamaters]);
+
+    auto panel = adoptNS([[_WKWebAuthenticationPanel alloc] init]);
+    [panel setMockConfiguration:@{ @"privateKeyBase64": testES256PrivateKeyBase64 }];
+    auto delegate = adoptNS([[TestWebAuthenticationPanelDelegate alloc] init]);
+    [panel setDelegate:delegate.get()];
+
+    [panel makeCredentialWithHash:nsHash options:options.get() completionHandler:^(_WKAuthenticatorAttestationResponse *response, NSError *error) {
+        webAuthenticationPanelRan = true;
+        cleanUpKeychain("example.com");
+
+        EXPECT_TRUE(laContextRequested);
+        EXPECT_NULL(error);
+
+        EXPECT_NOT_NULL(response);
+        EXPECT_WK_STREQ([response.rawId base64EncodedStringWithOptions:0], "SMSXHngF7hEOsElA73C3RY+8bR4=");
+        EXPECT_NULL(response.extensions);
+        EXPECT_WK_STREQ([response.attestationObject base64EncodedStringWithOptions:0], "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YViYo3mm9u6vuaVeN4wRgDTidR5oL6ufLTCrE9ISVYbOGUdFAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEjElx54Be4RDrBJQO9wt0WPvG0epQECAyYgASFYIDj/zxSkzKgaBuS3cdWDF558of8AaIpgFpsjF/Qm1749IlggVBJPgqUIwfhWHJ91nb7UPH76c0+WFOzZKslPyyFse4g=");
+    }];
+    Util::run(&webAuthenticationPanelRan);
+}
+#endif
+
 TEST(WebAuthenticationPanel, PublicKeyCredentialRequestOptionsMinimun)
 {
     auto options = adoptNS([[_WKPublicKeyCredentialRequestOptions alloc] init]);
@@ -1870,6 +1926,43 @@
     Util::run(&webAuthenticationPanelRan);
 }
 
+// For macOS, only internal builds can sign keychain entitlemnets
+// which are required to run local authenticator tests.
+#if USE(APPLE_INTERNAL_SDK) || PLATFORM(IOS)
+TEST(WebAuthenticationPanel, GetAssertionLA)
+{
+    reset();
+
+    ASSERT_TRUE(addKeyToKeychain(testES256PrivateKeyBase64, "", testUserEntityBundleBase64));
+
+    uint8_t hash[] = { 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04 };
+    NSData *nsHash = [NSData dataWithBytes:hash length:sizeof(hash)];
+
+    auto options = adoptNS([[_WKPublicKeyCredentialRequestOptions alloc] init]);
+    [options setRelyingPartyIdentifier:@""];
+
+    auto panel = adoptNS([[_WKWebAuthenticationPanel alloc] init]);
+    [panel setMockConfiguration:@{ }];
+    auto delegate = adoptNS([[TestWebAuthenticationPanelDelegate alloc] init]);
+    [panel setDelegate:delegate.get()];
+
+    [panel getAssertionWithHash:nsHash options:options.get() completionHandler:^(_WKAuthenticatorAssertionResponse *response, NSError *error) {
+        webAuthenticationPanelRan = true;
+        cleanUpKeychain("");
+
+        EXPECT_NULL(error);
+
+        EXPECT_NOT_NULL(response);
+        EXPECT_WK_STREQ([response.rawId base64EncodedStringWithOptions:0], "SMSXHngF7hEOsElA73C3RY+8bR4=");
+        EXPECT_NULL(response.extensions);
+        EXPECT_WK_STREQ([response.authenticatorData base64EncodedStringWithOptions:0], "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFUFAAAAAA==");
+        EXPECT_NOT_NULL(response.signature);
+        EXPECT_WK_STREQ([response.userHandle base64EncodedStringWithOptions:0], "AAECAwQFBgcICQ==");
+    }];
+    Util::run(&webAuthenticationPanelRan);
+}
+#endif
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(WEB_AUTHN)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to