Bug 1536773 - WebAuthn does not return userHandle back during Authentication r=jcj a=pascalc
authorAkshay Kumar <akshay.sonu@gmail.com>
Thu, 21 Mar 2019 11:37:07 +0000
changeset 526097 bfdb7d766a6d6a817db48093f78b1391d50e53e9
parent 526096 2b9a4ac6d5f2466152e6f9e64974e6ff1c6f87e0
child 526098 7b5b8c302a1ab509c7e995254f0e7a809db07327
push id2032
push userffxbld-merge
push dateMon, 13 May 2019 09:36:57 +0000
treeherdermozilla-release@455c1065dcbe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjcj, pascalc
bugs1536773
milestone67.0
Bug 1536773 - WebAuthn does not return userHandle back during Authentication r=jcj a=pascalc Differential Revision: https://phabricator.services.mozilla.com/D24189
dom/webauthn/PWebAuthnTransaction.ipdl
dom/webauthn/U2FHIDTokenManager.cpp
dom/webauthn/U2FSoftTokenManager.cpp
dom/webauthn/WebAuthnManager.cpp
dom/webauthn/WinWebAuthnManager.cpp
--- a/dom/webauthn/PWebAuthnTransaction.ipdl
+++ b/dom/webauthn/PWebAuthnTransaction.ipdl
@@ -125,16 +125,17 @@ struct WebAuthnGetAssertionInfo {
 struct WebAuthnGetAssertionResult {
   nsCString ClientDataJSON;
   uint8_t[] KeyHandle;
   uint8_t[] Signature;
   uint8_t[] AuthenticatorData;
   WebAuthnExtensionResult[] Extensions;
   /* Might be empty if the token implementation doesn't support CTAP1. */
   uint8_t[] SignatureData;
+  uint8_t[] UserHandle;
 };
 
 async protocol PWebAuthnTransaction {
   manager PBackground;
 
   parent:
     async RequestRegister(uint64_t aTransactionId, WebAuthnMakeCredentialInfo aTransactionInfo);
     async RequestSign(uint64_t aTransactionId, WebAuthnGetAssertionInfo aTransactionInfo);
--- a/dom/webauthn/U2FHIDTokenManager.cpp
+++ b/dom/webauthn/U2FHIDTokenManager.cpp
@@ -399,16 +399,18 @@ void U2FHIDTokenManager::HandleSignResul
   CryptoBuffer authenticatorData;
   rv = AssembleAuthenticatorData(chosenAppIdBuf, flags, counterBuf,
                                  emptyAttestationData, authenticatorData);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     mSignPromise.Reject(NS_ERROR_DOM_UNKNOWN_ERR, __func__);
     return;
   }
 
+  nsTArray<uint8_t> userHandle;
+
   WebAuthnGetAssertionResult result(mTransaction.ref().mClientDataJSON,
                                     keyHandle, signatureBuf, authenticatorData,
-                                    extensions, rawSignatureBuf);
+                                    extensions, rawSignatureBuf, userHandle);
   mSignPromise.Resolve(std::move(result), __func__);
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/webauthn/U2FSoftTokenManager.cpp
+++ b/dom/webauthn/U2FSoftTokenManager.cpp
@@ -963,19 +963,21 @@ RefPtr<U2FSignPromise> U2FSoftTokenManag
   CryptoBuffer authenticatorData;
   CryptoBuffer emptyAttestationData;
   rv = AssembleAuthenticatorData(chosenAppIdBuf, 0x01, counterBuf,
                                  emptyAttestationData, authenticatorData);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return U2FSignPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
   }
 
+  nsTArray<uint8_t> userHandle;
+
   WebAuthnGetAssertionResult result(aInfo.ClientDataJSON(), keyHandle,
                                     signatureBuf, authenticatorData, extensions,
-                                    signatureDataBuf);
+                                    signatureDataBuf, userHandle);
   return U2FSignPromise::CreateAndResolve(std::move(result), __func__);
 }
 
 void U2FSoftTokenManager::Cancel() {
   // This implementation is sync, requests can't be aborted.
 }
 
 }  // namespace dom
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -697,26 +697,34 @@ void WebAuthnManager::FinishGetAssertion
 
   nsAutoString credentialBase64Url;
   nsresult rv = credentialBuf.ToJwkBase64(credentialBase64Url);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     RejectTransaction(rv);
     return;
   }
 
+  CryptoBuffer userHandleBuf;
+  // U2FTokenManager don't return user handle.
+  // Best effort.
+  userHandleBuf.Assign(aResult.UserHandle());
+
   // If any authenticator returns success:
 
   // Create a new PublicKeyCredential object named value and populate its fields
   // with the values returned from the authenticator as well as the
   // clientDataJSON computed earlier.
   RefPtr<AuthenticatorAssertionResponse> assertion =
       new AuthenticatorAssertionResponse(mParent);
   assertion->SetClientDataJSON(clientDataBuf);
   assertion->SetAuthenticatorData(authenticatorDataBuf);
   assertion->SetSignature(signatureBuf);
+  if (!userHandleBuf.IsEmpty()) {
+    assertion->SetUserHandle(userHandleBuf);
+  }
 
   RefPtr<PublicKeyCredential> credential = new PublicKeyCredential(mParent);
   credential->SetId(credentialBase64Url);
   credential->SetType(NS_LITERAL_STRING("public-key"));
   credential->SetRawId(credentialBuf);
   credential->SetResponse(assertion);
 
   // Forward client extension results.
--- a/dom/webauthn/WinWebAuthnManager.cpp
+++ b/dom/webauthn/WinWebAuthnManager.cpp
@@ -633,29 +633,33 @@ void WinWebAuthnManager::Sign(PWebAuthnT
       signature.AppendElements(pWebAuthNAssertion->pbSignature,
                                pWebAuthNAssertion->cbSignature);
     }
 
     nsTArray<uint8_t> keyHandle;
     keyHandle.AppendElements(pWebAuthNAssertion->Credential.pbId,
                              pWebAuthNAssertion->Credential.cbId);
 
+    nsTArray<uint8_t> userHandle;
+    userHandle.AppendElements(pWebAuthNAssertion->pbUserId,
+                              pWebAuthNAssertion->cbUserId);
+
     nsTArray<uint8_t> authenticatorData;
     authenticatorData.AppendElements(pWebAuthNAssertion->pbAuthenticatorData,
                                      pWebAuthNAssertion->cbAuthenticatorData);
 
     nsTArray<WebAuthnExtensionResult> extensions;
 
     if (pbU2fAppIdUsed && *pbU2fAppIdUsed) {
       extensions.AppendElement(WebAuthnExtensionResultAppId(true));
     }
 
     WebAuthnGetAssertionResult result(aInfo.ClientDataJSON(), keyHandle,
                                       signature, authenticatorData, extensions,
-                                      signature);
+                                      signature, userHandle);
 
     Unused << mTransactionParent->SendConfirmSign(aTransactionId, result);
     ClearTransaction();
 
     gWinWebauthnFreeAssertion(pWebAuthNAssertion);
 
   } else {
     PCWSTR errorName = gWinWebauthnGetErrorName(hr);