Support googleLegacyAppidSupport extension
https://bugs.webkit.org/show_bug.cgi?id=202427
<rdar://problem/55887473>
Reviewed by Brent Fulgham.
Source/WebCore:
This patch adds support for googleLegacyAppidSupport extension, when set:
1) user agent should only use the U2F transport protocol,
2) should only communicate with roaming authenticators, and
3) should use a hard-coded appID of https://www.gstatic.com/securitykey/origins.json.
To be noticed as the name implies, this extension is exclusively for RP ID = google.com.
Implementation wise, all operations are captured in methods with name processGoogleLegacyAppIdSupportExtension.
1) AuthenticatorCoordinator takes care of setting the value.
2) U2fCommandConstructor takes care of hard coding the AppID.
3) AuthenticatorManager takes care of removing AuthenticatorTransport::Internal from TransportSet, so startDiscovery
will not poke platform authenticators.
4) CtapAuthenticator takes care of downgrading to U2fAuthenticator.
5) U2fAuthenticator takes care of setting the AppID in the response.
Partially covered by new test cases in existing tests, and remaining will be covered by manual tests.
* Modules/webauthn/AuthenticationExtensionsClientInputs.h:
(WebCore::AuthenticationExtensionsClientInputs::encode const):
(WebCore::AuthenticationExtensionsClientInputs::decode):
* Modules/webauthn/AuthenticationExtensionsClientInputs.idl:
* Modules/webauthn/AuthenticatorCoordinator.cpp:
(WebCore::AuthenticatorCoordinatorInternal::processGoogleLegacyAppIdSupportExtension):
(WebCore::AuthenticatorCoordinator::create const):
* Modules/webauthn/PublicKeyCredentialCreationOptions.h:
(WebCore::PublicKeyCredentialCreationOptions::encode const):
(WebCore::PublicKeyCredentialCreationOptions::decode):
* Modules/webauthn/fido/U2fCommandConstructor.cpp:
(fido::convertToU2fRegisterCommand):
(fido::processGoogleLegacyAppIdSupportExtension):
* Modules/webauthn/fido/U2fCommandConstructor.h:
Source/WebKit:
* UIProcess/WebAuthentication/AuthenticatorManager.cpp:
(WebKit::AuthenticatorManagerInternal::collectTransports):
(WebKit::AuthenticatorManagerInternal::processGoogleLegacyAppIdSupportExtension):
(WebKit::AuthenticatorManager::handleRequest):
* UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:
(WebKit::CtapAuthenticator::makeCredential):
(WebKit::CtapAuthenticator::processGoogleLegacyAppIdSupportExtension):
* UIProcess/WebAuthentication/fido/CtapAuthenticator.h:
* UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:
(WebKit::U2fAuthenticator::continueRegisterCommandAfterResponseReceived):
Tools:
Adds an API test for googleLegacyAppidSupport extension.
* TestWebKitAPI/Tests/WebCore/FidoTestData.h:
* TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp:
(TestWebKitAPI::constructMakeCredentialRequest):
(TestWebKitAPI::constructMakeCredentialRequestWithGoogleLegacyAppidSupport):
(TestWebKitAPI::TEST):
LayoutTests:
Add tests to confirm the googleLegacyAppidSupport extension is ignored for RP ID != google.com.
* http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
* http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@250659 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 953e9aa..83374fd 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2019-10-03 Jiewen Tan <jiewen_tan@apple.com>
+
+ Support googleLegacyAppidSupport extension
+ https://bugs.webkit.org/show_bug.cgi?id=202427
+ <rdar://problem/55887473>
+
+ Reviewed by Brent Fulgham.
+
+ Add tests to confirm the googleLegacyAppidSupport extension is ignored for RP ID != google.com.
+
+ * http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-create-success-hid.https.html:
+
2019-10-03 Yury Semikhatsky <yurys@chromium.org>
Web Inspector: tests under LayoutTests/inspector/debugger are flaky
diff --git a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt b/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt
index 807251f..80afb1b 100644
--- a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt
+++ b/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt
@@ -9,4 +9,6 @@
PASS PublicKeyCredential's [[create]] with none attestation in a mock hid authenticator.
PASS PublicKeyCredential's [[create]] with direct attestation in a mock hid authenticator.
PASS PublicKeyCredential's [[create]] with indirect attestation in a mock hid authenticator.
+PASS PublicKeyCredential's [[create]] with googleLegacyAppidSupport extension in a mock hid authenticator.
+PASS PublicKeyCredential's [[create]] with googleLegacyAppidSupport and appid extensions in a mock hid authenticator.
diff --git a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html b/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html
index f529687..6a8c358 100644
--- a/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html
+++ b/LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html
@@ -237,4 +237,51 @@
checkCtapMakeCredentialResult(credential, false);
});
}, "PublicKeyCredential's [[create]] with indirect attestation in a mock hid authenticator.");
+
+ // When RP ID is not google.com, googleLegacyAppidSupport should not have any effects.
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "localhost",
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "Appleseed",
+ },
+ challenge: Base64URL.parse("MTIzNDU2"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ extensions: { googleLegacyAppidSupport: true },
+ timeout: 100
+ }
+ };
+
+ return navigator.credentials.create(options).then(credential => {
+ checkCtapMakeCredentialResult(credential);
+ });
+ }, "PublicKeyCredential's [[create]] with googleLegacyAppidSupport extension in a mock hid authenticator.");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ rp: {
+ name: "localhost",
+ },
+ user: {
+ name: "John Appleseed",
+ id: Base64URL.parse(testUserhandleBase64),
+ displayName: "Appleseed",
+ },
+ challenge: Base64URL.parse("MTIzNDU2"),
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
+ extensions: { googleLegacyAppidSupport: true, appid: "" },
+ timeout: 100
+ }
+ };
+
+ return navigator.credentials.create(options).then(credential => {
+ checkCtapMakeCredentialResult(credential);
+ });
+ }, "PublicKeyCredential's [[create]] with googleLegacyAppidSupport and appid extensions in a mock hid authenticator.");
</script>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index e849b4c..2beb6e0 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,42 @@
+2019-10-03 Jiewen Tan <jiewen_tan@apple.com>
+
+ Support googleLegacyAppidSupport extension
+ https://bugs.webkit.org/show_bug.cgi?id=202427
+ <rdar://problem/55887473>
+
+ Reviewed by Brent Fulgham.
+
+ This patch adds support for googleLegacyAppidSupport extension, when set:
+ 1) user agent should only use the U2F transport protocol,
+ 2) should only communicate with roaming authenticators, and
+ 3) should use a hard-coded appID of https://www.gstatic.com/securitykey/origins.json.
+ To be noticed as the name implies, this extension is exclusively for RP ID = google.com.
+
+ Implementation wise, all operations are captured in methods with name processGoogleLegacyAppIdSupportExtension.
+ 1) AuthenticatorCoordinator takes care of setting the value.
+ 2) U2fCommandConstructor takes care of hard coding the AppID.
+ 3) AuthenticatorManager takes care of removing AuthenticatorTransport::Internal from TransportSet, so startDiscovery
+ will not poke platform authenticators.
+ 4) CtapAuthenticator takes care of downgrading to U2fAuthenticator.
+ 5) U2fAuthenticator takes care of setting the AppID in the response.
+
+ Partially covered by new test cases in existing tests, and remaining will be covered by manual tests.
+
+ * Modules/webauthn/AuthenticationExtensionsClientInputs.h:
+ (WebCore::AuthenticationExtensionsClientInputs::encode const):
+ (WebCore::AuthenticationExtensionsClientInputs::decode):
+ * Modules/webauthn/AuthenticationExtensionsClientInputs.idl:
+ * Modules/webauthn/AuthenticatorCoordinator.cpp:
+ (WebCore::AuthenticatorCoordinatorInternal::processGoogleLegacyAppIdSupportExtension):
+ (WebCore::AuthenticatorCoordinator::create const):
+ * Modules/webauthn/PublicKeyCredentialCreationOptions.h:
+ (WebCore::PublicKeyCredentialCreationOptions::encode const):
+ (WebCore::PublicKeyCredentialCreationOptions::decode):
+ * Modules/webauthn/fido/U2fCommandConstructor.cpp:
+ (fido::convertToU2fRegisterCommand):
+ (fido::processGoogleLegacyAppIdSupportExtension):
+ * Modules/webauthn/fido/U2fCommandConstructor.h:
+
2019-10-03 Yury Semikhatsky <yurys@chromium.org>
Web Inspector: tests under LayoutTests/inspector/debugger are flaky
diff --git a/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.h b/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.h
index 8e2d847..dbbee33 100644
--- a/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.h
+++ b/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.h
@@ -33,6 +33,7 @@
struct AuthenticationExtensionsClientInputs {
String appid;
+ bool googleLegacyAppidSupport;
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static Optional<AuthenticationExtensionsClientInputs> decode(Decoder&);
@@ -41,7 +42,7 @@
template<class Encoder>
void AuthenticationExtensionsClientInputs::encode(Encoder& encoder) const
{
- encoder << appid;
+ encoder << appid << googleLegacyAppidSupport;
}
template<class Decoder>
@@ -55,6 +56,12 @@
return WTF::nullopt;
result.appid = WTFMove(*appid);
+ Optional<bool> googleLegacyAppidSupport;
+ decoder >> googleLegacyAppidSupport;
+ if (!googleLegacyAppidSupport)
+ return WTF::nullopt;
+ result.googleLegacyAppidSupport = WTFMove(*googleLegacyAppidSupport);
+
return result;
}
diff --git a/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.idl b/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.idl
index 7e9e97b..971bc1a 100644
--- a/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.idl
+++ b/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientInputs.idl
@@ -27,4 +27,6 @@
Conditional=WEB_AUTHN,
] dictionary AuthenticationExtensionsClientInputs {
USVString appid;
+ // For Google to turn off the legacy AppID support.
+ boolean googleLegacyAppidSupport = true;
};
diff --git a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp
index 747aab3..91934e8 100644
--- a/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp
+++ b/Source/WebCore/Modules/webauthn/AuthenticatorCoordinator.cpp
@@ -54,7 +54,7 @@
Get
};
-// FIXME(181948): Add token binding ID and extensions.
+// FIXME(181948): Add token binding ID.
static Ref<ArrayBuffer> produceClientDataJson(ClientDataType type, const BufferSource& challenge, const SecurityOrigin& origin)
{
auto object = JSON::Object::create();
@@ -112,6 +112,16 @@
return appId;
}
+// The default behaviour for google.com is to always turn on the legacy AppID support.
+static bool processGoogleLegacyAppIdSupportExtension(const Optional<AuthenticationExtensionsClientInputs>& extensions, const String& rpId)
+{
+ if (rpId != "google.com"_s)
+ return false;
+ if (!extensions)
+ return true;
+ return extensions->googleLegacyAppidSupport;
+}
+
} // namespace AuthenticatorCoordinatorInternal
AuthenticatorCoordinator::AuthenticatorCoordinator(std::unique_ptr<AuthenticatorCoordinatorClient>&& client)
@@ -129,7 +139,6 @@
using namespace AuthenticatorCoordinatorInternal;
// The following implements https://www.w3.org/TR/webauthn/#createCredential as of 5 December 2017.
- // Extensions are not supported. Skip Step 11-12.
// Step 1, 3, 16 are handled by the caller.
// Step 2.
if (!sameOriginWithAncestors) {
@@ -161,6 +170,10 @@
return;
}
+ // Step 11-12.
+ // Only Google Legacy AppID Support Extension is supported.
+ options.extensions = AuthenticationExtensionsClientInputs { String(), processGoogleLegacyAppIdSupportExtension(options.extensions, options.rp.id) };
+
// Step 13-15.
auto clientDataJson = produceClientDataJson(ClientDataType::Create, options.challenge, callerOrigin);
auto clientDataJsonHash = produceClientDataJsonHash(clientDataJson);
diff --git a/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h b/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h
index d548aad..372df1b 100644
--- a/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h
+++ b/Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h
@@ -86,7 +86,7 @@
Vector<PublicKeyCredentialDescriptor> excludeCredentials;
Optional<AuthenticatorSelectionCriteria> authenticatorSelection;
AttestationConveyancePreference attestation;
- Optional<AuthenticationExtensionsClientInputs> extensions; // A place holder, but never used.
+ mutable Optional<AuthenticationExtensionsClientInputs> extensions;
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static Optional<PublicKeyCredentialCreationOptions> decode(Decoder&);
@@ -144,7 +144,7 @@
encoder << rp.id << rp.name << rp.icon;
encoder << static_cast<uint64_t>(user.id.length());
encoder.encodeFixedLengthData(user.id.data(), user.id.length(), 1);
- encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection << attestation;
+ encoder << user.displayName << user.name << user.icon << pubKeyCredParams << timeout << excludeCredentials << authenticatorSelection << attestation << extensions;
}
template<class Decoder>
@@ -189,29 +189,18 @@
return WTF::nullopt;
result.attestation = WTFMove(*attestation);
+ Optional<Optional<AuthenticationExtensionsClientInputs>> extensions;
+ decoder >> extensions;
+ if (!extensions)
+ return WTF::nullopt;
+ result.extensions = WTFMove(*extensions);
+
return result;
}
} // namespace WebCore
namespace WTF {
-// Not every member is copied.
-template<> struct CrossThreadCopierBase<false, false, WebCore::PublicKeyCredentialCreationOptions> {
- typedef WebCore::PublicKeyCredentialCreationOptions Type;
- static Type copy(const Type& source)
- {
- Type result;
- result.rp.name = source.rp.name.isolatedCopy();
- result.rp.icon = source.rp.icon.isolatedCopy();
- result.rp.id = source.rp.id.isolatedCopy();
-
- result.user.name = source.user.name.isolatedCopy();
- result.user.icon = source.user.icon.isolatedCopy();
- result.user.displayName = source.user.displayName.isolatedCopy();
- result.user.idVector = source.user.idVector;
- return result;
- }
-};
template<> struct EnumTraits<WebCore::PublicKeyCredentialCreationOptions::AuthenticatorAttachment> {
using values = EnumValues<
diff --git a/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.cpp b/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.cpp
index 6165b88..f2f9dc3 100644
--- a/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.cpp
+++ b/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.cpp
@@ -103,7 +103,8 @@
if (!isConvertibleToU2fRegisterCommand(request))
return WTF::nullopt;
- return constructU2fRegisterCommand(produceRpIdHash(request.rp.id), clientDataHash);
+ auto appId = processGoogleLegacyAppIdSupportExtension(request.extensions);
+ return constructU2fRegisterCommand(produceRpIdHash(!appId ? request.rp.id : appId), clientDataHash);
}
Optional<Vector<uint8_t>> convertToU2fCheckOnlySignCommand(const Vector<uint8_t>& clientDataHash, const PublicKeyCredentialCreationOptions& request, const PublicKeyCredentialDescriptor& keyHandle)
@@ -130,6 +131,15 @@
return constructU2fRegisterCommand(convertBytesToVector(kBogusAppParam, sizeof(kBogusAppParam)), convertBytesToVector(kBogusChallenge, sizeof(kBogusChallenge)));
}
+String processGoogleLegacyAppIdSupportExtension(const Optional<AuthenticationExtensionsClientInputs>& extensions)
+{
+ // AuthenticatorCoordinator::create should always set it.
+ ASSERT(!!extensions);
+ if (!extensions->googleLegacyAppidSupport)
+ return String();
+ return "https://www.gstatic.com/securitykey/origins.json"_s;
+}
+
} // namespace fido
#endif // ENABLE(WEB_AUTHN)
diff --git a/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.h b/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.h
index eebe292..2842762 100644
--- a/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.h
+++ b/Source/WebCore/Modules/webauthn/fido/U2fCommandConstructor.h
@@ -34,6 +34,7 @@
#include <wtf/Forward.h>
namespace WebCore {
+struct AuthenticationExtensionsClientInputs;
struct PublicKeyCredentialCreationOptions;
struct PublicKeyCredentialDescriptor;
struct PublicKeyCredentialRequestOptions;
@@ -66,6 +67,9 @@
WEBCORE_EXPORT Vector<uint8_t> constructBogusU2fRegistrationCommand();
+// Returns "https://www.gstatic.com/securitykey/origins.json" as an AppID when googleLegacyAppidSupport is true.
+WEBCORE_EXPORT String processGoogleLegacyAppIdSupportExtension(const Optional<WebCore::AuthenticationExtensionsClientInputs>&);
+
} // namespace fido
#endif // ENABLE(WEB_AUTHN)
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 2410396..e892199 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,5 +1,24 @@
2019-10-03 Jiewen Tan <jiewen_tan@apple.com>
+ Support googleLegacyAppidSupport extension
+ https://bugs.webkit.org/show_bug.cgi?id=202427
+ <rdar://problem/55887473>
+
+ Reviewed by Brent Fulgham.
+
+ * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+ (WebKit::AuthenticatorManagerInternal::collectTransports):
+ (WebKit::AuthenticatorManagerInternal::processGoogleLegacyAppIdSupportExtension):
+ (WebKit::AuthenticatorManager::handleRequest):
+ * UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp:
+ (WebKit::CtapAuthenticator::makeCredential):
+ (WebKit::CtapAuthenticator::processGoogleLegacyAppIdSupportExtension):
+ * UIProcess/WebAuthentication/fido/CtapAuthenticator.h:
+ * UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp:
+ (WebKit::U2fAuthenticator::continueRegisterCommandAfterResponseReceived):
+
+2019-10-03 Jiewen Tan <jiewen_tan@apple.com>
+
[WebAuthn] Implement dummy _WKWebAuthenticationPanel SPI
https://bugs.webkit.org/show_bug.cgi?id=202507
<rdar://problem/55918793>
diff --git a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
index 930441e..9a2b348 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
+++ b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
@@ -74,7 +74,7 @@
return result;
}
-// FIXME(188624, 188625): Support NFC and BLE authenticators.
+// FIXME(188625): Support BLE authenticators.
// The goal is to find a union of different transports from allowCredentials.
// If it is not specified or any of its credentials doesn't specify its own. We should discover all.
// This is a variant of Step. 18.*.4 from https://www.w3.org/TR/webauthn/#discover-from-external-source
@@ -99,20 +99,30 @@
result.add(AuthenticatorTransport::Nfc);
return result;
}
- if (!result.contains(AuthenticatorTransport::Internal) && allowCredential.transports.contains(AuthenticatorTransport::Internal))
- result.add(AuthenticatorTransport::Internal);
- if (!result.contains(AuthenticatorTransport::Usb) && allowCredential.transports.contains(AuthenticatorTransport::Usb))
- result.add(AuthenticatorTransport::Usb);
- if (!result.contains(AuthenticatorTransport::Nfc) && allowCredential.transports.contains(AuthenticatorTransport::Nfc))
- result.add(AuthenticatorTransport::Nfc);
- if (result.size() >= maxTransportNumber)
- return result;
+
+ for (const auto& transport : allowCredential.transports) {
+ if (transport == AuthenticatorTransport::Ble)
+ continue;
+ result.add(transport);
+ if (result.size() >= maxTransportNumber)
+ return result;
+ }
}
ASSERT(result.size() < maxTransportNumber);
return result;
}
+// Only roaming authenticators are supported for Google legacy AppID support.
+static void processGoogleLegacyAppIdSupportExtension(const Optional<AuthenticationExtensionsClientInputs>& extensions, AuthenticatorManager::TransportSet& transports)
+{
+ // AuthenticatorCoordinator::create should always set it.
+ ASSERT(!!extensions);
+ if (!extensions->googleLegacyAppidSupport)
+ return;
+ transports.remove(AuthenticatorTransport::Internal);
+}
+
} // namespace AuthenticatorManagerInternal
AuthenticatorManager::AuthenticatorManager()
@@ -137,7 +147,10 @@
// 2. Get available transports and start discovering authenticators on them.
WTF::switchOn(m_pendingRequestData.options, [&](const PublicKeyCredentialCreationOptions& options) {
initTimeOutTimer(options.timeout);
- startDiscovery(collectTransports(options.authenticatorSelection));
+
+ auto transports = collectTransports(options.authenticatorSelection);
+ processGoogleLegacyAppIdSupportExtension(options.extensions, transports);
+ startDiscovery(WTFMove(transports));
}, [&](const PublicKeyCredentialRequestOptions& options) {
initTimeOutTimer(options.timeout);
startDiscovery(collectTransports(options.allowCredentials));
diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp
index 743ca28..8eda11b 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp
+++ b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp
@@ -52,6 +52,8 @@
void CtapAuthenticator::makeCredential()
{
ASSERT(!m_isDowngraded);
+ if (processGoogleLegacyAppIdSupportExtension())
+ return;
auto cborCmd = encodeMakeCredenitalRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialCreationOptions>(requestData().options), m_info.options().userVerificationAvailability());
m_driver->transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) {
ASSERT(RunLoop::isMain());
@@ -113,6 +115,17 @@
return true;
}
+// Only U2F protocol is supported for Google legacy AppID support.
+bool CtapAuthenticator::processGoogleLegacyAppIdSupportExtension()
+{
+ // AuthenticatorCoordinator::create should always set it.
+ auto& extensions = WTF::get<PublicKeyCredentialCreationOptions>(requestData().options).extensions;
+ ASSERT(!!extensions);
+ if (extensions->googleLegacyAppidSupport)
+ tryDowngrade();
+ return extensions->googleLegacyAppidSupport;
+}
+
} // namespace WebKit
#endif // ENABLE(WEB_AUTHN)
diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h
index a18df04..8054198 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h
+++ b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h
@@ -50,6 +50,7 @@
void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&);
bool tryDowngrade();
+ bool processGoogleLegacyAppIdSupportExtension();
std::unique_ptr<CtapDriver> m_driver;
fido::AuthenticatorGetInfoResponse m_info;
diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp
index 31b2490..bd42459 100644
--- a/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp
+++ b/Source/WebKit/UIProcess/WebAuthentication/fido/U2fAuthenticator.cpp
@@ -155,7 +155,9 @@
{
switch (apduResponse.status()) {
case ApduResponse::Status::SW_NO_ERROR: {
- auto response = readU2fRegisterResponse(WTF::get<PublicKeyCredentialCreationOptions>(requestData().options).rp.id, apduResponse.data(), WTF::get<PublicKeyCredentialCreationOptions>(requestData().options).attestation);
+ auto& options = WTF::get<PublicKeyCredentialCreationOptions>(requestData().options);
+ auto appId = processGoogleLegacyAppIdSupportExtension(options.extensions);
+ auto response = readU2fRegisterResponse(!appId ? options.rp.id : appId, apduResponse.data(), options.attestation);
if (!response) {
receiveRespond(ExceptionData { UnknownError, "Couldn't parse the U2F register response."_s });
return;
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 430565b..d53194c 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,19 @@
+2019-10-03 Jiewen Tan <jiewen_tan@apple.com>
+
+ Support googleLegacyAppidSupport extension
+ https://bugs.webkit.org/show_bug.cgi?id=202427
+ <rdar://problem/55887473>
+
+ Reviewed by Brent Fulgham.
+
+ Adds an API test for googleLegacyAppidSupport extension.
+
+ * TestWebKitAPI/Tests/WebCore/FidoTestData.h:
+ * TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp:
+ (TestWebKitAPI::constructMakeCredentialRequest):
+ (TestWebKitAPI::constructMakeCredentialRequestWithGoogleLegacyAppidSupport):
+ (TestWebKitAPI::TEST):
+
2019-10-03 Thibault Saunier <tsaunier@igalia.com>
REGRESSION(r249428): [GStreamer] VP9 video rendered green
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h b/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h
index 0086e6e..d8fdd0f 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h
+++ b/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h
@@ -66,6 +66,23 @@
0x00, 0x00,
};
+constexpr uint8_t kU2fRegisterCommandApduWithGoogleLegacyAppidSupport[] = {
+ // CLA, INS, P1, P2 APDU instructions
+ 0x00, 0x01, 0x03, 0x00,
+ // Data length in 3 bytes in big endian order.
+ 0x00, 0x00, 0x40,
+ // Challenge parameter -- see kClientDataHash
+ 0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42,
+ 0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
+ 0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41,
+ // Application parameter
+ 0xA5, 0x46, 0x72, 0xB2, 0x22, 0xC4, 0xCF, 0x95, 0xE1, 0x51, 0xED,
+ 0x8D, 0x4D, 0x3C, 0x76, 0x7A, 0x6C, 0xC3, 0x49, 0x43, 0x59, 0x43,
+ 0x79, 0x4E, 0x88, 0x4F, 0x3D, 0x02, 0x3A, 0x82, 0x29, 0xFD,
+ // Max response length
+ 0x00, 0x00,
+};
+
// Sample U2F sign request parameters used in example 7 of the CTAP spec.
// https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#using-the-ctap2-authenticatormakecredential-command-with-ctap1-u2f-authenticators
constexpr uint8_t kU2fSignKeyHandle[] = {
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp b/Tools/TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp
index 646044622..2b8b96b 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/U2fCommandConstructorTest.cpp
@@ -59,14 +59,25 @@
params.type = PublicKeyCredentialType::PublicKey;
params.alg = COSE::ES256;
+ AuthenticationExtensionsClientInputs extensions;
+ extensions.googleLegacyAppidSupport = false;
+
PublicKeyCredentialCreationOptions options;
options.rp = WTFMove(rp);
options.user = WTFMove(user);
options.pubKeyCredParams.append(WTFMove(params));
+ options.extensions = WTFMove(extensions);
return options;
}
+PublicKeyCredentialCreationOptions constructMakeCredentialRequestWithGoogleLegacyAppidSupport()
+{
+ auto options = constructMakeCredentialRequest();
+ options.extensions->googleLegacyAppidSupport = true;
+ return options;
+}
+
PublicKeyCredentialRequestOptions constructGetAssertionRequest()
{
PublicKeyCredentialRequestOptions options;
@@ -85,6 +96,17 @@
EXPECT_EQ(*u2fRegisterCommand, convertBytesToVector(TestData::kU2fRegisterCommandApdu, sizeof(TestData::kU2fRegisterCommandApdu)));
}
+TEST(U2fCommandConstructorTest, TestConvertCtapMakeCredentialToU2fRegisterWithGoogleLegacyAppidSupport)
+{
+ const auto makeCredentialParam = constructMakeCredentialRequestWithGoogleLegacyAppidSupport();
+
+ EXPECT_TRUE(isConvertibleToU2fRegisterCommand(makeCredentialParam));
+
+ const auto u2fRegisterCommand = convertToU2fRegisterCommand(convertBytesToVector(TestData::kClientDataHash, sizeof(TestData::kClientDataHash)), makeCredentialParam);
+ ASSERT_TRUE(u2fRegisterCommand);
+ EXPECT_EQ(*u2fRegisterCommand, convertBytesToVector(TestData::kU2fRegisterCommandApduWithGoogleLegacyAppidSupport, sizeof(TestData::kU2fRegisterCommandApduWithGoogleLegacyAppidSupport)));
+}
+
TEST(U2fCommandConstructorTest, TestConvertCtapMakeCredentialToU2fCheckOnlySign)
{
auto makeCredentialParam = constructMakeCredentialRequest();