Diff
Modified: trunk/LayoutTests/ChangeLog (259679 => 259680)
--- trunk/LayoutTests/ChangeLog 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/ChangeLog 2020-04-07 23:01:20 UTC (rev 259680)
@@ -1,3 +1,21 @@
+2020-04-07 Jiewen Tan <[email protected]>
+
+ [WebAuthn] Cancel WebAuthn requests when users cancel LocalAuthentication prompts
+ https://bugs.webkit.org/show_bug.cgi?id=209923
+ <rdar://problem/61223713>
+
+ Reviewed by Brent Fulgham.
+
+ Adds a new test for the change and modifies existing tests to accommodate changes in MockWebAuthenticationConfiguration.idl.
+
+ * http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html:
+ * http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-create-failure-local.https.html:
+ * http/wpt/webauthn/public-key-credential-create-success-local.https.html:
+ * http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html:
+ * http/wpt/webauthn/public-key-credential-get-failure-local.https.html:
+ * http/wpt/webauthn/public-key-credential-get-success-local.https.html:
+
2020-04-07 Jacob Uphoff <[email protected]>
[ macOS debug ] REGRESSION (r259463): http/tests/media/clearkey/collect-webkit-media-session.html is failing
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local-silent.https.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -6,7 +6,7 @@
<script>
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { userVerification: "no", acceptAttestation: false } });
promise_test(t => {
const options = {
@@ -126,7 +126,7 @@
}
};
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { acceptAuthentication: true, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { userVerification: "yes", acceptAttestation: false } });
return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.");
}, "PublicKeyCredential's [[create]] without private keys in a mock local authenticator.");
@@ -152,7 +152,7 @@
}
};
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { acceptAuthentication: true, acceptAttestation: false, privateKeyBase64: privateKeyBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { userVerification: "yes", acceptAttestation: false, privateKeyBase64: privateKeyBase64 } });
return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.").then(() => {
if (window.testRunner)
testRunner.cleanUpKeychain(testRpId, credentialIDBase64);
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https-expected.txt 2020-04-07 23:01:20 UTC (rev 259680)
@@ -7,4 +7,5 @@
PASS PublicKeyCredential's [[create]] without attestation in a mock local authenticator.
PASS PublicKeyCredential's [[create]] not deleting old credential in a mock local authenticator.
PASS PublicKeyCredential's [[create]] with timeout in a mock local authenticator.
+PASS PublicKeyCredential's [[create]] with user cancel in a mock local authenticator.
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-local.https.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -6,7 +6,7 @@
<script>
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false } });
promise_test(t => {
const options = {
@@ -121,7 +121,7 @@
}
};
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "yes", acceptAttestation: false } });
return promiseRejects(t, "UnknownError", navigator.credentials.create(options), "Couldn't create private key.");
}, "PublicKeyCredential's [[create]] without private keys in a mock local authenticator.");
@@ -146,7 +146,7 @@
}
};
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false, privateKeyBase64: privateKeyBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "yes", acceptAttestation: false, privateKeyBase64: privateKeyBase64 } });
return promiseRejects(t, "UnknownError", navigator.credentials.create(options), "Couldn't attest: The operation couldn't complete.").then(() => {
if (window.testRunner)
testRunner.cleanUpKeychain(testRpId, credentialIDBase64);
@@ -173,7 +173,7 @@
}
};
if (window.internals) {
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "yes", acceptAttestation: false } });
testRunner.addTestKeyToKeychain(privateKeyBase64, testRpId, testUserEntityBundleBase64);
}
return promiseRejects(t, "UnknownError", navigator.credentials.create(options), "Couldn't create private key.").then(() => {
@@ -202,7 +202,29 @@
};
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false } });
return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "Operation timed out.");
}, "PublicKeyCredential's [[create]] with timeout in a mock local authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "example.com"
+ },
+ user: {
+ name: "John Appleseed",
+ id: asciiToUint8Array("123456"),
+ displayName: "John",
+ },
+ challenge: asciiToUint8Array("123456"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ }
+ };
+
+ if (window.internals)
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "cancel", acceptAttestation: false } });
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.create(options), "This request has been cancelled by the user.");
+ }, "PublicKeyCredential's [[create]] with user cancel in a mock local authenticator.");
+
</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-local.https.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -52,7 +52,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: false,
privateKeyBase64: privateKeyBase64,
}
@@ -85,7 +85,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: false,
privateKeyBase64: privateKeyBase64,
}
@@ -119,7 +119,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: false,
privateKeyBase64: privateKeyBase64,
}
@@ -163,7 +163,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: false,
privateKeyBase64: privateKeyBase64,
}
@@ -197,7 +197,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: true,
privateKeyBase64: privateKeyBase64,
userCertificateBase64: testAttestationCertificateBase64,
@@ -233,7 +233,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: true,
privateKeyBase64: privateKeyBase64,
userCertificateBase64: testAttestationCertificateBase64,
@@ -269,7 +269,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: false,
privateKeyBase64: privateKeyBase64,
}
@@ -308,7 +308,7 @@
if (window.internals)
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: true,
privateKeyBase64: privateKeyBase64,
userCertificateBase64: testAttestationCertificateBase64,
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local-silent.https.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -6,7 +6,7 @@
<script>
promise_test(t => {
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { userVerification: "no", acceptAttestation: false } });
const options = {
publicKey: {
@@ -30,7 +30,7 @@
const credentialIDBase64 = btoa(String.fromCharCode.apply(0, credentialID));
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { acceptAuthentication: false, acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { userVerification: "no", acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
const options = {
publicKey: {
@@ -56,7 +56,7 @@
const credentialIDBase64 = btoa(String.fromCharCode.apply(0, credentialID));
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { acceptAuthentication: false, acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ silentFailure: true, local: { userVerification: "no", acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
const options = {
publicKey: {
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-local.https.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -6,7 +6,7 @@
<script>
promise_test(t => {
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false } });
const options = {
publicKey: {
@@ -29,7 +29,7 @@
const credentialIDBase64 = btoa(String.fromCharCode.apply(0, credentialID));
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
const options = {
publicKey: {
@@ -54,7 +54,7 @@
const credentialIDBase64 = btoa(String.fromCharCode.apply(0, credentialID));
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
const options = {
publicKey: {
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html (259679 => 259680)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-local.https.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -41,7 +41,7 @@
const credentialIDBase64 = base64encode(credentialID);
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "yes", acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
const options = {
publicKey: {
@@ -62,7 +62,7 @@
const credentialIDBase64 = base64encode(credentialID);
// Default mock configuration. Tests need to override if they need different configuration.
if (window.internals)
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "yes", acceptAttestation: false, preferredCredentialIdBase64: credentialIDBase64 } });
const options = {
publicKey: {
Modified: trunk/Source/WebCore/ChangeLog (259679 => 259680)
--- trunk/Source/WebCore/ChangeLog 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebCore/ChangeLog 2020-04-07 23:01:20 UTC (rev 259680)
@@ -1,3 +1,19 @@
+2020-04-07 Jiewen Tan <[email protected]>
+
+ [WebAuthn] Cancel WebAuthn requests when users cancel LocalAuthentication prompts
+ https://bugs.webkit.org/show_bug.cgi?id=209923
+ <rdar://problem/61223713>
+
+ Reviewed by Brent Fulgham.
+
+ Covered by new tests within existing test files.
+
+ * testing/MockWebAuthenticationConfiguration.h:
+ (WebCore::MockWebAuthenticationConfiguration::LocalConfiguration::encode const):
+ (WebCore::MockWebAuthenticationConfiguration::LocalConfiguration::decode):
+ * testing/MockWebAuthenticationConfiguration.idl:
+ Adds a new parameter to reflect user cancellations on LocalAuthentication UI.
+
2020-04-07 Tadeu Zagallo <[email protected]>
Not using strict mode within ClassDeclaration statement
Modified: trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h (259679 => 259680)
--- trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h 2020-04-07 23:01:20 UTC (rev 259680)
@@ -61,8 +61,14 @@
MaliciousPayload
};
+ enum class UserVerification : uint8_t {
+ No,
+ Yes,
+ Cancel
+ };
+
struct LocalConfiguration {
- bool acceptAuthentication { false };
+ UserVerification userVerification { UserVerification::No };
bool acceptAttestation { false };
String privateKeyBase64;
String userCertificateBase64;
@@ -112,7 +118,7 @@
template<class Encoder>
void MockWebAuthenticationConfiguration::LocalConfiguration::encode(Encoder& encoder) const
{
- encoder << acceptAuthentication << acceptAttestation << privateKeyBase64 << userCertificateBase64 << intermediateCACertificateBase64 << preferredCredentialIdBase64;
+ encoder << userVerification << acceptAttestation << privateKeyBase64 << userCertificateBase64 << intermediateCACertificateBase64 << preferredCredentialIdBase64;
}
template<class Decoder>
@@ -120,11 +126,11 @@
{
MockWebAuthenticationConfiguration::LocalConfiguration result;
- Optional<bool> acceptAuthentication;
- decoder >> acceptAuthentication;
- if (!acceptAuthentication)
+ Optional<UserVerification> userVerification;
+ decoder >> userVerification;
+ if (!userVerification)
return WTF::nullopt;
- result.acceptAuthentication = *acceptAuthentication;
+ result.userVerification = *userVerification;
Optional<bool> acceptAttestation;
decoder >> acceptAttestation;
@@ -297,6 +303,15 @@
>;
};
+template<> struct EnumTraits<WebCore::MockWebAuthenticationConfiguration::UserVerification> {
+ using values = EnumValues<
+ WebCore::MockWebAuthenticationConfiguration::UserVerification,
+ WebCore::MockWebAuthenticationConfiguration::UserVerification::No,
+ WebCore::MockWebAuthenticationConfiguration::UserVerification::Yes,
+ WebCore::MockWebAuthenticationConfiguration::UserVerification::Cancel
+ >;
+};
+
} // namespace WTF
#endif // ENABLE(WEB_AUTHN)
Modified: trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl (259679 => 259680)
--- trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl 2020-04-07 23:01:20 UTC (rev 259680)
@@ -61,6 +61,14 @@
[
Conditional=WEB_AUTHN,
+] enum UserVerification {
+ "no",
+ "yes",
+ "cancel"
+};
+
+[
+ Conditional=WEB_AUTHN,
] dictionary MockWebAuthenticationConfiguration {
boolean silentFailure = false;
MockLocalConfiguration local;
@@ -71,7 +79,7 @@
[
Conditional=WEB_AUTHN,
] dictionary MockLocalConfiguration {
- boolean acceptAuthentication = false;
+ UserVerification userVerification = "no";
boolean acceptAttestation = false;
DOMString privateKeyBase64;
DOMString userCertificateBase64;
Modified: trunk/Source/WebKit/ChangeLog (259679 => 259680)
--- trunk/Source/WebKit/ChangeLog 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/ChangeLog 2020-04-07 23:01:20 UTC (rev 259680)
@@ -1,3 +1,32 @@
+2020-04-07 Jiewen Tan <[email protected]>
+
+ [WebAuthn] Cancel WebAuthn requests when users cancel LocalAuthentication prompts
+ https://bugs.webkit.org/show_bug.cgi?id=209923
+ <rdar://problem/61223713>
+
+ Reviewed by Brent Fulgham.
+
+ This patch intents to streamline WebAuthn local authenticator UX a bit more. Here, we should treat user
+ cancellation of the LocalAuthentication UI as if it were being done on the UI Client's WebAuthn UI.
+
+ * UIProcess/WebAuthentication/Authenticator.h:
+ * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+ (WebKit::AuthenticatorManager::cancelRequest):
+ * UIProcess/WebAuthentication/AuthenticatorManager.h:
+ * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h:
+ * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
+ (WebKit::LocalAuthenticator::continueMakeCredentialAfterUserVerification):
+ (WebKit::LocalAuthenticator::continueGetAssertionAfterUserVerification):
+ (WebKit::LocalAuthenticator::validateUserVerification const):
+ * UIProcess/WebAuthentication/Cocoa/LocalConnection.h:
+ * UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
+ (WebKit::LocalConnection::verifyUser const):
+ * UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
+ (WebKit::MockLocalConnection::MockLocalConnection):
+ (WebKit::MockLocalConnection::verifyUser const):
+ (WebKit::MockLocalConnection::filterResponses const):
+ * WebKit.xcodeproj/project.pbxproj:
+
2020-04-07 Sihui Liu <[email protected]>
[ macOS ] Update sandbox rules for storage
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h 2020-04-07 23:01:20 UTC (rev 259680)
@@ -57,6 +57,7 @@
virtual void requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&&) = 0;
virtual void selectAssertionResponse(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, WebAuthenticationSource, CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)>&&) = 0;
virtual void decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&&) = 0;
+ virtual void cancelRequest() = 0;
};
virtual ~Authenticator() = default;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2020-04-07 23:01:20 UTC (rev 259680)
@@ -179,9 +179,7 @@
if (frameID && frameID != pendingFrameID->frameID)
return;
}
- invokePendingCompletionHandler(ExceptionData { NotAllowedError, "Operation timed out."_s });
- clearState();
- m_requestTimeOutTimer.stop();
+ cancelRequest();
}
// The following implements part of Step 20. of https://www.w3.org/TR/webauthn/#createCredential
@@ -192,9 +190,7 @@
RELEASE_ASSERT(RunLoop::isMain());
if (!m_pendingCompletionHandler || m_pendingRequestData.panel.get() != &panel)
return;
- invokePendingCompletionHandler(ExceptionData { NotAllowedError, "This request has been cancelled by the user."_s });
- clearState();
- m_requestTimeOutTimer.stop();
+ cancelRequest();
}
void AuthenticatorManager::clearStateAsync()
@@ -295,6 +291,13 @@
});
}
+void AuthenticatorManager::cancelRequest()
+{
+ invokePendingCompletionHandler(ExceptionData { NotAllowedError, "This request has been cancelled by the user."_s });
+ clearState();
+ m_requestTimeOutTimer.stop();
+}
+
UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService(AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const
{
return AuthenticatorTransportService::create(transport, observer);
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h 2020-04-07 23:01:20 UTC (rev 259680)
@@ -84,6 +84,7 @@
void requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&&) final;
void selectAssertionResponse(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, WebAuthenticationSource, CompletionHandler<void(WebCore::AuthenticatorAssertionResponse*)>&&) final;
void decidePolicyForLocalAuthenticator(CompletionHandler<void(LocalAuthenticatorPolicy)>&&) final;
+ void cancelRequest() final;
// Overriden by MockAuthenticatorManager.
virtual UniqueRef<AuthenticatorTransportService> createService(WebCore::AuthenticatorTransport, AuthenticatorTransportService::Observer&) const;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.h 2020-04-07 23:01:20 UTC (rev 259680)
@@ -68,6 +68,7 @@
void receiveException(WebCore::ExceptionData&&, WebAuthenticationStatus = WebAuthenticationStatus::LAError) const;
void deleteDuplicateCredential() const;
+ bool validateUserVerification(LocalConnection::UserVerification) const;
State m_state { State::Init };
UniqueRef<LocalConnection> m_connection;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm 2020-04-07 23:01:20 UTC (rev 259680)
@@ -274,10 +274,8 @@
m_state = State::UserVerified;
auto& creationOptions = WTF::get<PublicKeyCredentialCreationOptions>(requestData().options);
- if (verification == LocalConnection::UserVerification::No) {
- receiveException({ NotAllowedError, "Couldn't verify user."_s });
+ if (!validateUserVerification(verification))
return;
- }
// Here is the keychain schema.
// kSecAttrLabel: RP ID
@@ -500,10 +498,8 @@
ASSERT(m_state == State::ResponseSelected);
m_state = State::UserVerified;
- if (verification == LocalConnection::UserVerification::No) {
- receiveException({ NotAllowedError, "Couldn't verify user."_s });
+ if (!validateUserVerification(verification))
return;
- }
// Step 10.
auto authData = buildAuthData(WTF::get<PublicKeyCredentialRequestOptions>(requestData().options).rpId, getAssertionFlags, counter, { });
@@ -588,6 +584,22 @@
});
}
+bool LocalAuthenticator::validateUserVerification(LocalConnection::UserVerification verification) const
+{
+ if (verification == LocalConnection::UserVerification::Cancel) {
+ if (auto* observer = this->observer())
+ observer->cancelRequest();
+ return false;
+ }
+
+ if (verification == LocalConnection::UserVerification::No) {
+ receiveException({ NotAllowedError, "Couldn't verify user."_s });
+ return false;
+ }
+
+ return true;
+}
+
} // namespace WebKit
#endif // ENABLE(WEB_AUTHN)
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.h (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.h 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.h 2020-04-07 23:01:20 UTC (rev 259680)
@@ -51,9 +51,10 @@
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(LocalConnection);
public:
- enum class UserVerification : bool {
+ enum class UserVerification : uint8_t {
No,
- Yes
+ Yes,
+ Cancel
};
using AttestationCallback = CompletionHandler<void(NSArray *, NSError *)>;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm 2020-04-07 23:01:20 UTC (rev 259680)
@@ -83,6 +83,8 @@
if (error) {
LOG_ERROR("Couldn't authenticate with biometrics: %@", error);
verification = UserVerification::No;
+ if (error.code == LAErrorUserCancel)
+ verification = UserVerification::Cancel;
}
RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler), verification, context = WTFMove(context)] () mutable {
completionHandler(verification, context.get());
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm (259679 => 259680)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm 2020-04-07 23:01:20 UTC (rev 259680)
@@ -38,22 +38,31 @@
#import "LocalAuthenticationSoftLink.h"
namespace WebKit {
+using namespace WebCore;
-MockLocalConnection::MockLocalConnection(const WebCore::MockWebAuthenticationConfiguration& configuration)
+MockLocalConnection::MockLocalConnection(const MockWebAuthenticationConfiguration& configuration)
: m_configuration(configuration)
{
}
-void MockLocalConnection::verifyUser(const String&, WebCore::ClientDataType, SecAccessControlRef, UserVerificationCallback&& callback) const
+void MockLocalConnection::verifyUser(const String&, ClientDataType, SecAccessControlRef, UserVerificationCallback&& callback) const
{
// Mock async operations.
RunLoop::main().dispatch([configuration = m_configuration, callback = WTFMove(callback)]() mutable {
ASSERT(configuration.local);
- if (!configuration.local->acceptAuthentication) {
- callback(UserVerification::No, nil);
- return;
+
+ 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::Yes, adoptNS([allocLAContextInstance() init]).get());
+
+ callback(userVerification, adoptNS([allocLAContextInstance() init]).get());
});
}
@@ -113,7 +122,7 @@
});
}
-void MockLocalConnection::filterResponses(HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>& responses) const
+void MockLocalConnection::filterResponses(HashSet<Ref<AuthenticatorAssertionResponse>>& responses) const
{
const auto& preferredCredentialIdBase64 = m_configuration.local->preferredCredentialIdBase64;
if (preferredCredentialIdBase64.isEmpty())
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (259679 => 259680)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2020-04-07 23:01:20 UTC (rev 259680)
@@ -3902,6 +3902,7 @@
57B8E3D52355864A00D5C5D1 /* FidoAuthenticator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FidoAuthenticator.h; sourceTree = "<group>"; };
57B8E3D62355864A00D5C5D1 /* FidoAuthenticator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FidoAuthenticator.cpp; sourceTree = "<group>"; };
57BBEA6C22BC0BFE00273995 /* SOAuthorizationLoadPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SOAuthorizationLoadPolicy.h; sourceTree = "<group>"; };
+ 57C3E8AC242490D5001E2209 /* WebAuthenticationRequestData.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WebAuthenticationRequestData.cpp; sourceTree = "<group>"; };
57C6244A234679A400383FE7 /* WebAuthenticationFlags.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebAuthenticationFlags.h; sourceTree = "<group>"; };
57DCED6A2142EAE20016B847 /* WebAuthenticatorCoordinatorMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAuthenticatorCoordinatorMessages.h; path = DerivedSources/WebKit2/WebAuthenticatorCoordinatorMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
57DCED6B2142EAE20016B847 /* WebAuthenticatorCoordinatorMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAuthenticatorCoordinatorMessageReceiver.cpp; path = DerivedSources/WebKit2/WebAuthenticatorCoordinatorMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -8065,6 +8066,7 @@
57DCED9921489F4D0016B847 /* AuthenticatorTransportService.cpp */,
57DCED8A214853130016B847 /* AuthenticatorTransportService.h */,
57C6244A234679A400383FE7 /* WebAuthenticationFlags.h */,
+ 57C3E8AC242490D5001E2209 /* WebAuthenticationRequestData.cpp */,
57DCEDA62149F9DA0016B847 /* WebAuthenticationRequestData.h */,
57608296202BD8BA00116678 /* WebAuthenticatorCoordinatorProxy.cpp */,
57608295202BD8BA00116678 /* WebAuthenticatorCoordinatorProxy.h */,
Modified: trunk/Tools/ChangeLog (259679 => 259680)
--- trunk/Tools/ChangeLog 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Tools/ChangeLog 2020-04-07 23:01:20 UTC (rev 259680)
@@ -1,3 +1,18 @@
+2020-04-07 Jiewen Tan <[email protected]>
+
+ [WebAuthn] Cancel WebAuthn requests when users cancel LocalAuthentication prompts
+ https://bugs.webkit.org/show_bug.cgi?id=209923
+ <rdar://problem/61223713>
+
+ Reviewed by Brent Fulgham.
+
+ Modifies existing tests to accommodate changes in MockWebAuthenticationConfiguration.idl.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-la.html:
+ * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-duplicate-credential.html:
+ * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-error.html:
+ * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la.html:
+
2020-04-07 Ryan Haddad <[email protected]>
Unreviewed, reverting r259655.
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-la.html (259679 => 259680)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-la.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-la.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -1,7 +1,7 @@
<input type="text" id="input">
<script>
if (window.internals) {
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: true, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "yes", acceptAttestation: false } });
internals.withUserGesture(() => { input.focus(); });
}
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-duplicate-credential.html (259679 => 259680)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-duplicate-credential.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-duplicate-credential.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -18,7 +18,7 @@
}
if (window.internals) {
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false } });
internals.withUserGesture(() => { input.focus(); });
}
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-error.html (259679 => 259680)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-error.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la-error.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -1,7 +1,7 @@
<input type="text" id="input">
<script>
if (window.internals) {
- internals.setMockWebAuthenticationConfiguration({ local: { acceptAuthentication: false, acceptAttestation: false } });
+ internals.setMockWebAuthenticationConfiguration({ local: { userVerification: "no", acceptAttestation: false } });
internals.withUserGesture(() => { input.focus(); });
}
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la.html (259679 => 259680)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la.html 2020-04-07 22:50:50 UTC (rev 259679)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-la.html 2020-04-07 23:01:20 UTC (rev 259680)
@@ -32,7 +32,7 @@
if (window.internals) {
internals.setMockWebAuthenticationConfiguration({
local: {
- acceptAuthentication: true,
+ userVerification: "yes",
acceptAttestation: true,
privateKeyBase64: testES256PrivateKeyBase64,
userCertificateBase64: testAttestationCertificateBase64,