From 6bd8e23cd7a92e9c5e92fc130b31b4351bfa19b7 Mon Sep 17 00:00:00 2001 From: J Pascoe Date: Tue, 16 Aug 2022 18:23:46 -0700 Subject: [PATCH] [WebAuthn] Disable platform authenticator for disallowed rps https://bugs.webkit.org/show_bug.cgi?id=243844 Reviewed by Brent Fulgham. In some circumstances it may be useful to quirk off the platform authenticator for given rps. This patch hooks up some new internal SPI for that purpose. * Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp: (WebCore::AuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable const): * Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h: * Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h: * Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp: (WebCore::PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable): * Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h: * Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm: * Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp: (WebKit::WebAuthenticatorCoordinatorProxy::isUserVerifyingPlatformAuthenticatorAvailable): * Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h: * Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in: * Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp: (WebKit::WebAuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable): * Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h: Canonical link: https://commits.webkit.org/253497@main --- Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp | 5 +++-- Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h | 2 +- .../Modules/webauthn/AuthenticatorCoordinatorClient.h | 2 +- Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp | 2 +- .../Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h | 1 + .../Cocoa/WebAuthenticatorCoordinatorProxy.mm | 4 ++-- .../WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp | 2 +- .../WebAuthentication/WebAuthenticatorCoordinatorProxy.h | 2 +- .../WebAuthenticatorCoordinatorProxy.messages.in | 2 +- .../WebAuthentication/WebAuthenticatorCoordinator.cpp | 4 ++-- .../WebAuthentication/WebAuthenticatorCoordinator.h | 2 +- 11 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp index 8901fed953d0..e9d067a0e2ca 100644 --- a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp +++ b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp @@ -265,7 +265,7 @@ void AuthenticatorCoordinator::discoverFromExternalSource(const Document& docume m_client->getAssertion(*frame, callerOrigin, clientDataJsonHash, options, requestOptions.mediation, scopeAndCrossOriginParent, WTFMove(callback)); } -void AuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred&& promise) const +void AuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable(const Document& document, DOMPromiseDeferred&& promise) const { // The following implements https://www.w3.org/TR/webauthn/#isUserVerifyingPlatformAuthenticatorAvailable // as of 5 December 2017. @@ -279,8 +279,9 @@ void AuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable(DOM auto completionHandler = [promise = WTFMove(promise)] (bool result) mutable { promise.resolve(result); }; + // Async operation are dispatched and handled in the messenger. - m_client->isUserVerifyingPlatformAuthenticatorAvailable(WTFMove(completionHandler)); + m_client->isUserVerifyingPlatformAuthenticatorAvailable(document.securityOrigin(), WTFMove(completionHandler)); } diff --git a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h index 70563568d92a..0f064b6b5144 100644 --- a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h +++ b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.h @@ -62,7 +62,7 @@ class AuthenticatorCoordinator final { // The following methods implement static methods of PublicKeyCredential. void create(const Document&, const PublicKeyCredentialCreationOptions&, WebAuthn::Scope, RefPtr&&, CredentialPromise&&) const; void discoverFromExternalSource(const Document&, CredentialRequestOptions&&, const ScopeAndCrossOriginParent&, CredentialPromise&&) const; - void isUserVerifyingPlatformAuthenticatorAvailable(DOMPromiseDeferred&&) const; + void isUserVerifyingPlatformAuthenticatorAvailable(const Document&, DOMPromiseDeferred&&) const; void isConditionalMediationAvailable(DOMPromiseDeferred&&) const; void resetUserGestureRequirement(); diff --git a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h index 6652e8e2a4be..993b71f98915 100644 --- a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h +++ b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h @@ -63,7 +63,7 @@ class AuthenticatorCoordinatorClient : public CanMakeWeakPtr&, const PublicKeyCredentialCreationOptions&, RequestCompletionHandler&&) = 0; virtual void getAssertion(const Frame&, const SecurityOrigin&, const Vector&, const PublicKeyCredentialRequestOptions&, MediationRequirement, const ScopeAndCrossOriginParent&, RequestCompletionHandler&&) = 0; virtual void isConditionalMediationAvailable(QueryCompletionHandler&&) = 0; - virtual void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&) = 0; + virtual void isUserVerifyingPlatformAuthenticatorAvailable(const SecurityOrigin&, QueryCompletionHandler&&) = 0; virtual void resetUserGestureRequirement() { } }; diff --git a/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp b/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp index 3b26858380a3..44e287ccdb85 100644 --- a/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp +++ b/Source/WebCore/Modules/webauthn/PublicKeyCredential.cpp @@ -67,7 +67,7 @@ PublicKeyCredential::PublicKeyCredential(Ref&& response) void PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable(Document& document, DOMPromiseDeferred&& promise) { if (auto* page = document.page()) - page->authenticatorCoordinator().isUserVerifyingPlatformAuthenticatorAvailable(WTFMove(promise)); + page->authenticatorCoordinator().isUserVerifyingPlatformAuthenticatorAvailable(document, WTFMove(promise)); } } // namespace WebCore diff --git a/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h b/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h index 9438b62fa8e4..7b35226c5146 100644 --- a/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h +++ b/Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h @@ -32,6 +32,7 @@ #else @interface ASCWebKitSPISupport : NSObject @property (class, nonatomic) BOOL shouldUseAlternateCredentialStore; ++ (BOOL)arePasskeysDisallowedForRelyingParty:(nonnull NSString *)relyingParty; @end #endif diff --git a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm b/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm index 0490fe14301c..98e8eb021f01 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm +++ b/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticatorCoordinatorProxy.mm @@ -517,10 +517,10 @@ static inline void continueAfterRequest(RetainPtr> cr handler([getASCWebKitSPISupportClass() shouldUseAlternateCredentialStore]); } -void WebAuthenticatorCoordinatorProxy::isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&& handler) +void WebAuthenticatorCoordinatorProxy::isUserVerifyingPlatformAuthenticatorAvailable(const SecurityOriginData& data, QueryCompletionHandler&& handler) { if ([getASCWebKitSPISupportClass() shouldUseAlternateCredentialStore]) { - handler(true); + handler(![getASCWebKitSPISupportClass() arePasskeysDisallowedForRelyingParty:data.securityOrigin()->domain()]); return; } diff --git a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp index 78f5a2d3fc4e..9501743485bf 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp +++ b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.cpp @@ -114,7 +114,7 @@ void WebAuthenticatorCoordinatorProxy::handleRequest(WebAuthenticationRequestDat } #if !HAVE(UNIFIED_ASC_AUTH_UI) -void WebAuthenticatorCoordinatorProxy::isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&& handler) +void WebAuthenticatorCoordinatorProxy::isUserVerifyingPlatformAuthenticatorAvailable(const SecurityOriginData&, QueryCompletionHandler&& handler) { handler(LocalService::isAvailable()); } diff --git a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h index 3c347b2da7f4..fbbe225dde4f 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h +++ b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.h @@ -73,7 +73,7 @@ class WebAuthenticatorCoordinatorProxy : public IPC::MessageReceiver { // Receivers. void makeCredential(WebCore::FrameIdentifier, FrameInfoData&&, Vector&& hash, WebCore::PublicKeyCredentialCreationOptions&&, bool processingUserGesture, RequestCompletionHandler&&); void getAssertion(WebCore::FrameIdentifier, FrameInfoData&&, Vector&& hash, WebCore::PublicKeyCredentialRequestOptions&&, WebCore::CredentialRequestOptions::MediationRequirement, std::optional, bool processingUserGesture, RequestCompletionHandler&&); - void isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&&); + void isUserVerifyingPlatformAuthenticatorAvailable(const WebCore::SecurityOriginData&, QueryCompletionHandler&&); void isConditionalMediationAvailable(QueryCompletionHandler&&); void handleRequest(WebAuthenticationRequestData&&, RequestCompletionHandler&&); diff --git a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in index d3fa65d518c1..28a853146d02 100644 --- a/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in +++ b/Source/WebKit/UIProcess/WebAuthentication/WebAuthenticatorCoordinatorProxy.messages.in @@ -29,7 +29,7 @@ messages -> WebAuthenticatorCoordinatorProxy NotRefCounted { MakeCredential(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, Vector hash, struct WebCore::PublicKeyCredentialCreationOptions options, bool processingUserGesture) -> (struct WebCore::AuthenticatorResponseData data, enum:int WebCore::AuthenticatorAttachment attachment, struct WebCore::ExceptionData exception) GetAssertion(WebCore::FrameIdentifier frameID, struct WebKit::FrameInfoData frameInfo, Vector hash, struct WebCore::PublicKeyCredentialRequestOptions options, enum:uint8_t WebCore::CredentialRequestOptions::MediationRequirement mediation, std::optional parentOrigin, bool processingUserGesture) -> (struct WebCore::AuthenticatorResponseData data, enum:int WebCore::AuthenticatorAttachment attachment, struct WebCore::ExceptionData exception) isConditionalMediationAvailable() -> (bool result) - IsUserVerifyingPlatformAuthenticatorAvailable() -> (bool result) + IsUserVerifyingPlatformAuthenticatorAvailable(struct WebCore::SecurityOriginData origin) -> (bool result) } #endif diff --git a/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp b/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp index 28d5fef59c7a..e2d929aedec3 100644 --- a/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp +++ b/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.cpp @@ -91,9 +91,9 @@ void WebAuthenticatorCoordinator::isConditionalMediationAvailable(QueryCompletio m_webPage.sendWithAsyncReply(Messages::WebAuthenticatorCoordinatorProxy::isConditionalMediationAvailable(), WTFMove(handler)); }; -void WebAuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable(QueryCompletionHandler&& handler) +void WebAuthenticatorCoordinator::isUserVerifyingPlatformAuthenticatorAvailable(const SecurityOrigin& origin, QueryCompletionHandler&& handler) { - m_webPage.sendWithAsyncReply(Messages::WebAuthenticatorCoordinatorProxy::IsUserVerifyingPlatformAuthenticatorAvailable(), WTFMove(handler)); + m_webPage.sendWithAsyncReply(Messages::WebAuthenticatorCoordinatorProxy::IsUserVerifyingPlatformAuthenticatorAvailable(origin.data()), WTFMove(handler)); } bool WebAuthenticatorCoordinator::processingUserGesture(const Frame& frame, const FrameIdentifier& frameID) diff --git a/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h b/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h index 0ed3e752a703..68a2885e07db 100644 --- a/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h +++ b/Source/WebKit/WebProcess/WebAuthentication/WebAuthenticatorCoordinator.h @@ -43,7 +43,7 @@ class WebAuthenticatorCoordinator final : public WebCore::AuthenticatorCoordinat void makeCredential(const WebCore::Frame&, const WebCore::SecurityOrigin&, const Vector&, const WebCore::PublicKeyCredentialCreationOptions&, WebCore::RequestCompletionHandler&&) final; void getAssertion(const WebCore::Frame&, const WebCore::SecurityOrigin&, const Vector& hash, const WebCore::PublicKeyCredentialRequestOptions&, WebCore::MediationRequirement, const std::pair>&, WebCore::RequestCompletionHandler&&) final; void isConditionalMediationAvailable(WebCore::QueryCompletionHandler&&) final; - void isUserVerifyingPlatformAuthenticatorAvailable(WebCore::QueryCompletionHandler&&) final; + void isUserVerifyingPlatformAuthenticatorAvailable(const WebCore::SecurityOrigin&, WebCore::QueryCompletionHandler&&) final; void resetUserGestureRequirement() final { m_requireUserGesture = false; } bool processingUserGesture(const WebCore::Frame&, const WebCore::FrameIdentifier&);