Bug 1526023 - Web Authentication - add isExternalCTAP2SecurityKeySupported r=qdot,keeler a=lizzard
authorJ.C. Jones <jjones@mozilla.com>
Thu, 14 Feb 2019 20:11:34 +0000
changeset 516220 ff2c3fd26b15d1e10df6e42aab71ee461e18196e
parent 516219 a57747b9852b8f6990ce49a26680c723a708560b
child 516221 e91e23e30d4b131d66e55ed6f92a91cd011f3804
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersqdot, keeler, lizzard
bugs1526023
milestone66.0
Bug 1526023 - Web Authentication - add isExternalCTAP2SecurityKeySupported r=qdot,keeler a=lizzard 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"]