Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: components/webauth/authenticator_impl.cc

Issue 2788823002: Add the Mojo implementation of authenticator.mojom's MakeCredential. (Closed)
Patch Set: Rebasing to relocate WebRuntimeFeatures Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/webauth/authenticator_impl.cc
diff --git a/components/webauth/authenticator_impl.cc b/components/webauth/authenticator_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b72c3c94287e8a49719b2e30504648ef36b7b0f5
--- /dev/null
+++ b/components/webauth/authenticator_impl.cc
@@ -0,0 +1,161 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/webauth/authenticator_impl.h"
+
+#include <memory>
+
+#include "base/json/json_writer.h"
+#include "base/memory/ptr_util.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "crypto/sha2.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+
+using content::RenderFrameHost;
+using content::WebContents;
+
+namespace webauth {
+
+const char kGetAssertionType[] = "navigator.id.getAssertion";
+
+// JSON key values
+const char kTypeKey[] = "type";
+const char kChallengeKey[] = "challenge";
+const char kOriginKey[] = "origin";
+const char kCidPubkeyKey[] = "cid_pubkey";
+
+// Serializes the |value| to a JSON string and returns the result.
+std::string SerializeValueToJson(const base::Value& value) {
+ std::string json;
+ base::JSONWriter::Write(value, &json);
+ return json;
+}
+
+// static
+void AuthenticatorImpl::Create(RenderFrameHost* render_frame_host,
+ mojom::AuthenticatorRequest request) {
+ auto authenticator_impl =
+ base::WrapUnique(new AuthenticatorImpl(render_frame_host));
+ mojo::MakeStrongBinding(std::move(authenticator_impl), std::move(request));
+}
+
+AuthenticatorImpl::~AuthenticatorImpl() {
+ if (!connection_error_handler_.is_null())
+ connection_error_handler_.Run();
+}
+
+AuthenticatorImpl::AuthenticatorImpl(RenderFrameHost* render_frame_host) {
+ DCHECK(render_frame_host);
+ set_connection_error_handler(base::Bind(
+ &AuthenticatorImpl::OnConnectionTerminated, base::Unretained(this)));
+ callerOrigin_ = render_frame_host->GetLastCommittedOrigin();
+}
+
+// mojom:Authenticator
+void AuthenticatorImpl::MakeCredential(
+ mojom::RelyingPartyAccountPtr account,
+ std::vector<mojom::ScopedCredentialParametersPtr> parameters,
+ const std::vector<uint8_t>& challenge,
+ mojom::ScopedCredentialOptionsPtr options,
+ MakeCredentialCallback callback) {
+ std::string effectiveDomain;
+ std::string relyingPartyId;
+ std::string clientDataJSON;
+ base::DictionaryValue clientData;
jochen (gone - plz use gerrit) 2017/05/30 12:03:02 should all be like effective_domain etc..
kpaulhamus 2017/05/31 20:56:05 Done.
+
+ // Steps 3 & 4 of https://w3c.github.io/webauthn/#makeCredential
+ // opaque origin
+ if (callerOrigin_.Serialize() == "") {
jochen (gone - plz use gerrit) 2017/05/30 12:03:02 caller_origin_.unique()
kpaulhamus 2017/05/31 20:56:05 Done.
+ std::move(callback).Run(mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR,
+ NULL);
+ return;
+ }
+
+ if (!options->relying_party_id) {
+ relyingPartyId = callerOrigin_.Serialize();
+ } else {
+ effectiveDomain = callerOrigin_.host();
+
+ if (effectiveDomain.empty()) {
+ std::move(callback).Run(mojom::AuthenticatorStatus::SECURITY_ERROR, NULL);
+ return;
+ }
+ // TODO(kpaulhamus): Check if relyingPartyId is a registrable domain
+ // suffix of and equal to effectiveDomain and set relyingPartyId
+ // appropriately.
+ relyingPartyId = options->relying_party_id.value_or(std::string());
+ }
+
+ // TODO(kpaulhamus): Check ScopedCredentialParameter's type and
+ // algorithmIdentifier after algorithmIdentifier is added to mojom to
+ // make sure it is U2F_V2.
+
+ clientData.SetString(kTypeKey, kGetAssertionType);
+ clientData.SetString(
+ kChallengeKey,
+ base::StringPiece(reinterpret_cast<const char*>(challenge.data()),
+ challenge.size()));
+ clientData.SetString(kOriginKey, relyingPartyId);
+ // Channel ID is optional, and missing if the browser doesn't support it.
+ // It is present and set to the constant "unused" if the browser
+ // supports Channel ID but is not using it to talk to the origin.
+ // TODO(kpaulhamus): Fetch and add the Channel ID public key used to
+ // communicate with the origin.
+ clientData.SetString(kCidPubkeyKey, "unused");
+
+ // SHA-256 hash the JSON data structure
+ clientDataJSON = SerializeValueToJson(clientData);
+ std::string clientDataHash = crypto::SHA256HashString(clientDataJSON);
+
+ auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
+
+ // Step 16 of https://w3c.github.io/webauthn/#makeCredential
+ timeout_callback_.Reset(base::Bind(&AuthenticatorImpl::OnTimeout,
+ base::Unretained(this),
+ copyable_callback));
+
+ // base::Unretained(this), Passed(&callback)));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, timeout_callback_.callback(),
+ base::TimeDelta::FromSecondsD(options->adjusted_timeout));
+
+ // Per fido-u2f-raw-message-formats:
+ // The challenge parameter is the SHA-256 hash of the Client Data,
+ // a stringified JSON data structure that the FIDO Client prepares.
+ // Among other things, the Client Data contains the challenge from the
+ // relying party (hence the name of the parameter).
+ // The application parameter is the SHA-256 hash of the UTF-8 encoding of
+ // the application identity of the application requesting the registration
+ /*
+ U2fRegister(clientDataHash, app_param, base::Bind(
+ &AuthenticatorImpl::onRegister, weak_factory_.GetWeakPtr(),
+ std::move(clientDataJSON), callback));
+ */
+
+ timeout_callback_.Cancel();
+ std::move(callback).Run(mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, NULL);
+}
+
+// Callback to handle the async response from a U2fDevice.
+void AuthenticatorImpl::OnRegister(MakeCredentialCallback callback,
+ std::string& clientDataJSON,
+ uint8_t status_code,
+ std::vector<uint8_t> data) {
+ timeout_callback_.Cancel();
+ std::move(callback).Run(mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, NULL);
+}
+
+// Runs when timer expires and cancels all issued requests to a U2fDevice.
+void AuthenticatorImpl::OnTimeout(MakeCredentialCallback callback) {
+ std::move(callback).Run(mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR, NULL);
+}
+
+void AuthenticatorImpl::OnConnectionTerminated() {
+ // Closures and cleanup due to either a browser-side error or
+ // as a result of the connection_error_handler, which can mean
+ // that the renderer has decided to close the pipe for various
+ // reasons.
+}
+} // namespace webauth

Powered by Google App Engine
This is Rietveld 408576698