Bug 1247124 - Limit FIDO U2F to Secure Contexts r?ttaubert r?smaug draft
authorJ.C. Jones <jjones@mozilla.com>
Wed, 13 Dec 2017 17:02:38 -0600
changeset 712046 7ff7a963bd2e7ab26971a345495bc57c776f4b7c
parent 711692 8062887ff0d9382ea84177f2c21f62dc0e613d9e
child 743959 bef6d1c1f71c615eb6f2a8ef7a408d13353878b0
push id93234
push userbmo:jjones@mozilla.com
push dateFri, 15 Dec 2017 15:33:26 +0000
reviewersttaubert, smaug
bugs1247124
milestone59.0a1
Bug 1247124 - Limit FIDO U2F to Secure Contexts r?ttaubert r?smaug Use the [SecureContext] webidl notation to hide the powerful "window.u2f" feature and its interface when not loaded in a secure context. MozReview-Commit-ID: 7en8b5ieI85
dom/u2f/tests/frame_appid_facet_insecure.html
dom/webidl/U2F.webidl
--- a/dom/u2f/tests/frame_appid_facet_insecure.html
+++ b/dom/u2f/tests/frame_appid_facet_insecure.html
@@ -12,50 +12,45 @@
 local_setParentOrigin("http://mochi.test:8888");
 
 async function doTests() {
   var version = "U2F_V2";
   var challenge = new Uint8Array(16);
 
   local_is(window.location.origin, "http://test2.example.com", "Is loaded correctly");
 
-  await promiseU2FRegister(null, [{
-    version: version,
-    challenge: bytesToBase64UrlSafe(challenge),
-  }], [], function(res){
-    local_isnot(res.errorCode, 0, "Insecure origin disallowed for null AppID");
-  });
+  local_is('u2f' in window, false, "window.u2f must be undefined when accessed from an insecure origin");
+  local_is('U2F' in window, false, "window.U2F must be undefined when accessed from an insecure origin");
 
-  await promiseU2FRegister("", [{
-    version: version,
-    challenge: bytesToBase64UrlSafe(challenge),
-  }], [], function(res){
-    local_isnot(res.errorCode, 0, "Insecure origin disallowed for empty AppID");
-  });
+  try {
+    u2f.register(null, [], [], function(res) {
+      local_ok(false, "Callbacks should not be called.");
+    });
+  } catch (err) {
+    local_ok(err == "ReferenceError: u2f is not defined", "calling u2f should have thrown from an insecure origin");
+  }
 
-  await promiseU2FRegister("http://example.com/appId", [{
-    version: version,
-    challenge: bytesToBase64UrlSafe(challenge),
-  }], [], function(res){
-    local_isnot(res.errorCode, 0, "Insecure origin disallowed for HTTP AppID");
-  });
+  try {
+    window.u2f.register(null, [], [], function(res) {
+      local_ok(false, "Callbacks should not be called.");
+    });
+  } catch (err) {
+    local_ok(err == "TypeError: window.u2f is undefined", "accessing window.u2f should have thrown from an insecure origin");
+  }
 
-  await promiseU2FRegister("https://example.com/appId", [{
-    version: version,
-    challenge: bytesToBase64UrlSafe(challenge),
-  }], [], function(res){
-    local_isnot(res.errorCode, 0, "Insecure origin disallowed for HTTPS AppID from HTTP origin");
-  });
-
-  await promiseU2FRegister(window.location.origin + "/otherAppId", [{
-    version: version,
-    challenge: bytesToBase64UrlSafe(challenge),
-  }], [], function(res){
-    local_isnot(res.errorCode, 0, "Insecure origin disallowed for HTTP origin");
-  });
+  try {
+    await promiseU2FRegister(null, [{
+      version: version,
+      challenge: bytesToBase64UrlSafe(challenge),
+    }], [], function(res){
+      local_ok(false, "Shouldn't have gotten here on an insecure origin");
+    });
+  } catch (err) {
+    local_ok(err == "ReferenceError: u2f is not defined", "Should have thrown from an insecure origin");
+  }
 
   local_finished();
 };
 
 doTests();
 
 </script>
 </body>
--- a/dom/webidl/U2F.webidl
+++ b/dom/webidl/U2F.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is a combination of the FIDO U2F Raw Message Formats:
  * https://www.fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-message-formats-v1.1-id-20160915.html
  * and the U2F JavaScript API v1.1:
  * https://www.fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-javascript-api-v1.1-id-20160915.html
  */
 
 [NoInterfaceObject]
 interface GlobalU2F {
-  [Throws, Pref="security.webauth.u2f"]
+  [SecureContext, Throws, Pref="security.webauth.u2f"]
   readonly attribute U2F u2f;
 };
 
 typedef unsigned short ErrorCode;
 typedef sequence<Transport> Transports;
 
 enum Transport {
     "bt",
@@ -62,17 +62,17 @@ dictionary SignResponse {
     // From Error
     ErrorCode? errorCode;
     DOMString? errorMessage;
 };
 
 callback U2FRegisterCallback = void(RegisterResponse response);
 callback U2FSignCallback = void(SignResponse response);
 
-[Pref="security.webauth.u2f"]
+[SecureContext, Pref="security.webauth.u2f"]
 interface U2F {
   // These enumerations are defined in the FIDO U2F Javascript API under the
   // interface "ErrorCode" as constant integers, and also in the U2F.cpp file.
   // Any changes to these must occur in both locations.
   const unsigned short OK = 0;
   const unsigned short OTHER_ERROR = 1;
   const unsigned short BAD_REQUEST = 2;
   const unsigned short CONFIGURATION_UNSUPPORTED = 3;