Bug 1526023 - Web Authentication - add isExternalCTAP2SecurityKeySupported r=qdot,keeler
authorJ.C. Jones <jjones@mozilla.com>
Thu, 14 Feb 2019 20:11:34 +0000
changeset 459189 d805110bf63188253cb39fee57c300678e145ab5
parent 459188 5f65d978f17ffe5f536be033e100a821d7d81d30
child 459190 3f8f4dd57d090bf0d49a23180b63cb590633a52d
push id35556
push userdvarga@mozilla.com
push dateFri, 15 Feb 2019 01:38:24 +0000
treeherdermozilla-central@b29c87add05f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot, keeler
bugs1526023
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1526023 - Web Authentication - add isExternalCTAP2SecurityKeySupported r=qdot,keeler We support CTAP2 devices on one specific platform, making it hard for RPs to decide whether or not Firefox will support the tokens they're asking for. This adds a non-standard method to divine that information while Firefox moves toward CTAP2 support. Differential Revision: https://phabricator.services.mozilla.com/D19826
dom/webauthn/PublicKeyCredential.cpp
dom/webauthn/PublicKeyCredential.h
dom/webauthn/tests/mochitest.ini
dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html
dom/webidl/WebAuthentication.webidl
--- a/dom/webauthn/PublicKeyCredential.cpp
+++ b/dom/webauthn/PublicKeyCredential.cpp
@@ -107,16 +107,41 @@ PublicKeyCredential::IsUserVerifyingPlat
     promise->MaybeResolve(true);
   }
 
 #endif
 
   return promise.forget();
 }
 
+/* static */ already_AddRefed<Promise>
+PublicKeyCredential::IsExternalCTAP2SecurityKeySupported(
+    GlobalObject& aGlobal) {
+  nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aGlobal.Context());
+  if (NS_WARN_IF(!globalObject)) {
+    return nullptr;
+  }
+
+  ErrorResult rv;
+  RefPtr<Promise> promise = Promise::Create(globalObject, rv);
+  if (rv.Failed()) {
+    return nullptr;
+  }
+
+#ifdef OS_WIN
+  if (WinWebAuthnManager::AreWebAuthNApisAvailable()) {
+    promise->MaybeResolve(true);
+    return promise.forget();
+  }
+#endif
+
+  promise->MaybeResolve(false);
+  return promise.forget();
+}
+
 void PublicKeyCredential::GetClientExtensionResults(
     AuthenticationExtensionsClientOutputs& aResult) {
   aResult = mClientExtensionOutputs;
 }
 
 void PublicKeyCredential::SetClientExtensionResultAppId(bool aResult) {
   mClientExtensionOutputs.mAppid.Construct();
   mClientExtensionOutputs.mAppid.Value() = aResult;
--- a/dom/webauthn/PublicKeyCredential.h
+++ b/dom/webauthn/PublicKeyCredential.h
@@ -39,16 +39,19 @@ class PublicKeyCredential final : public
 
   nsresult SetRawId(CryptoBuffer& aBuffer);
 
   void SetResponse(RefPtr<AuthenticatorResponse>);
 
   static already_AddRefed<Promise>
   IsUserVerifyingPlatformAuthenticatorAvailable(GlobalObject& aGlobal);
 
+  static already_AddRefed<Promise> IsExternalCTAP2SecurityKeySupported(
+      GlobalObject& aGlobal);
+
   void GetClientExtensionResults(
       AuthenticationExtensionsClientOutputs& aResult);
 
   void SetClientExtensionResultAppId(bool aResult);
 
  private:
   CryptoBuffer mRawId;
   JS::Heap<JSObject*> mRawIdCachedObj;
--- a/dom/webauthn/tests/mochitest.ini
+++ b/dom/webauthn/tests/mochitest.ini
@@ -15,8 +15,9 @@ scheme = https
 [test_webauthn_no_token.html]
 [test_webauthn_make_credential.html]
 [test_webauthn_get_assertion.html]
 [test_webauthn_get_assertion_dead_object.html]
 [test_webauthn_override_request.html]
 [test_webauthn_store_credential.html]
 [test_webauthn_sameorigin.html]
 [test_webauthn_isplatformauthenticatoravailable.html]
+[test_webauthn_isexternalctap2securitykeysupported.html]
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/tests/test_webauthn_isexternalctap2securitykeysupported.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<head>
+  <title>Test for W3C Web Authentication isExternalCTAP2SecurityKeySupported</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="u2futil.js"></script>
+  <script type="text/javascript" src="pkijs/common.js"></script>
+  <script type="text/javascript" src="pkijs/asn1.js"></script>
+  <script type="text/javascript" src="pkijs/x509_schema.js"></script>
+  <script type="text/javascript" src="pkijs/x509_simpl.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<h1>Test for W3C Web Authentication isExternalCTAP2SecurityKeySupported</h1>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1526023">Mozilla Bug 1526023</a>
+
+<script class="testbody" type="text/javascript">
+"use strict";
+
+// Execute the full-scope test
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
+                                   ["security.webauth.webauthn_enable_softtoken", true],
+                                   ["security.webauth.webauthn_enable_usbtoken", false]]},
+function() {
+  PublicKeyCredential.isExternalCTAP2SecurityKeySupported()
+  .then(aResult => ok(true, `Should always return either true or false: ${aResult}`))
+  .catch(aProblem => ok(false, `We shouldn't get here: ${aProblem}`))
+  .then(() => SimpleTest.finish());
+});
+
+</script>
+
+</body>
+</html>
--- a/dom/webidl/WebAuthentication.webidl
+++ b/dom/webidl/WebAuthentication.webidl
@@ -14,16 +14,18 @@ interface PublicKeyCredential : Credenti
     [SameObject] readonly attribute ArrayBuffer              rawId;
     [SameObject] readonly attribute AuthenticatorResponse    response;
     AuthenticationExtensionsClientOutputs getClientExtensionResults();
 };
 
 [SecureContext]
 partial interface PublicKeyCredential {
     static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable();
+    // isExternalCTAP2SecurityKeySupported is non-standard; see Bug 1526023
+    static Promise<boolean> isExternalCTAP2SecurityKeySupported();
 };
 
 [SecureContext, Pref="security.webauth.webauthn"]
 interface AuthenticatorResponse {
     [SameObject] readonly attribute ArrayBuffer clientDataJSON;
 };
 
 [SecureContext, Pref="security.webauth.webauthn"]