Bug 1309284 - WebAuthn JS API [part 3]: Support origin relax algorithm r=keeler
authorJ.C. Jones <jjones@mozilla.com>
Mon, 09 Jan 2017 13:55:59 -0700
changeset 328785 482e54376042ed35d176c5499fd1cf725d16ee08
parent 328784 353ff937f3e0476d2d6a41db9e95566284cea796
child 328786 a271a9a042013cc1bbb5036f396159aee79df983
push id85546
push userkwierso@gmail.com
push dateWed, 11 Jan 2017 02:36:30 +0000
treeherdermozilla-inbound@c5bce4cd684a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1309284, 1329764
milestone53.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 1309284 - WebAuthn JS API [part 3]: Support origin relax algorithm r=keeler The WebAuthn specification calls for running the HTML5.1 algorithm that occurs when you modify document.domain from JS, and use that algorithm's output for the "Relying Party ID" through the rest of the WebAuthn algorithm. This code paves the way for that to be added in Bug 1329764, once the spec issues upstream are resolved. MozReview-Commit-ID: DNNcr3Gh1Be
dom/u2f/WebAuthentication.cpp
dom/u2f/WebAuthentication.h
--- a/dom/u2f/WebAuthentication.cpp
+++ b/dom/u2f/WebAuthentication.cpp
@@ -636,16 +636,31 @@ WebAuthentication::U2FAuthGetAssertion(c
     return;
   }
 
   // 4.1.2.9 Reject promise with a DOMException whose name is "NotAllowedError",
   // and terminate this algorithm.
   aRequest->SetFailure(NS_ERROR_DOM_NOT_ALLOWED_ERR);
 }
 
+nsresult
+WebAuthentication::RelaxSameOrigin(const nsAString& aInputRpId,
+                                   /* out */ nsACString& aRelaxedRpId)
+{
+  MOZ_ASSERT(mParent);
+  nsCOMPtr<nsIDocument> document = mParent->GetDoc();
+  if (!document || !document->IsHTMLDocument()) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // TODO: Bug 1329764: Invoke the Relax Algorithm, once properly defined
+  aRelaxedRpId.Assign(NS_ConvertUTF16toUTF8(aInputRpId));
+  return NS_OK;
+}
+
 already_AddRefed<Promise>
 WebAuthentication::MakeCredential(JSContext* aCx, const Account& aAccount,
                   const Sequence<ScopedCredentialParameters>& aCryptoParameters,
                   const ArrayBufferViewOrArrayBuffer& aChallenge,
                   const ScopedCredentialOptions& aOptions)
 {
   MOZ_ASSERT(mParent);
   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
@@ -697,19 +712,20 @@ WebAuthentication::MakeCredential(JSCont
     // 4.1.1.3.b If rpId is specified, then invoke the procedure used for
     // relaxing the same-origin restriction by setting the document.domain
     // attribute, using rpId as the given value but without changing the current
     // document’s domain. If no errors are thrown, set rpId to the value of host
     // as computed by this procedure, and rpIdHash to the SHA-256 hash of rpId.
     // Otherwise, reject promise with a DOMException whose name is
     // "SecurityError", and terminate this algorithm.
 
-    // TODO: relax the same-origin restriction
-
-    rpId.Assign(NS_ConvertUTF16toUTF8(aOptions.mRpId.Value()));
+    if (NS_FAILED(RelaxSameOrigin(aOptions.mRpId.Value(), rpId))) {
+      promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+      return promise.forget();
+    }
   }
 
   CryptoBuffer rpIdHash;
   if (!rpIdHash.SetLength(SHA256_LENGTH, fallible)) {
     promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
     return promise.forget();
   }
 
@@ -896,19 +912,20 @@ WebAuthentication::GetAssertion(const Ar
     // 4.1.2.3.b If rpId is specified, then invoke the procedure used for
     // relaxing the same-origin restriction by setting the document.domain
     // attribute, using rpId as the given value but without changing the current
     // document’s domain. If no errors are thrown, set rpId to the value of host
     // as computed by this procedure, and rpIdHash to the SHA-256 hash of rpId.
     // Otherwise, reject promise with a DOMException whose name is
     // "SecurityError", and terminate this algorithm.
 
-    // TODO: relax the same-origin restriction
-
-    rpId.Assign(NS_ConvertUTF16toUTF8(aOptions.mRpId.Value()));
+    if (NS_FAILED(RelaxSameOrigin(aOptions.mRpId.Value(), rpId))) {
+      promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
+      return promise.forget();
+    }
   }
 
   CryptoBuffer rpIdHash;
   if (!rpIdHash.SetLength(SHA256_LENGTH, fallible)) {
     promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
     return promise.forget();
   }
 
--- a/dom/u2f/WebAuthentication.h
+++ b/dom/u2f/WebAuthentication.h
@@ -93,16 +93,19 @@ private:
              const WebAuthnExtensions& aExtensions);
   void
   U2FAuthGetAssertion(const RefPtr<AssertionRequest>& aRequest,
                    const Authenticator& aToken, CryptoBuffer& aRpIdHash,
                    const nsACString& aClientData, CryptoBuffer& aClientDataHash,
                    nsTArray<CryptoBuffer>& aAllowList,
                    const WebAuthnExtensions& aExtensions);
 
+  nsresult
+  RelaxSameOrigin(const nsAString& aInputRpId, nsACString& aRelaxedRpId);
+
   nsCOMPtr<nsPIDOMWindowInner> mParent;
   nsString mOrigin;
   Sequence<Authenticator> mAuthenticators;
   bool mInitialized;
 };
 
 } // namespace dom
 } // namespace mozilla