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

Unified Diff: third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp

Issue 2788823002: Add the Mojo implementation of authenticator.mojom's MakeCredential. (Closed)
Patch Set: Addressing mkwst comments Created 3 years, 6 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: third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
diff --git a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
index 06cba2c2be2f6b4296dedf8ac97fc645435b2f85..d51a53916edf3acebbd7c83e4eb7d62eb22515bb 100644
--- a/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
+++ b/third_party/WebKit/Source/modules/webauth/WebAuthentication.cpp
@@ -1,4 +1,4 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
+// 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.
@@ -20,23 +20,26 @@
namespace {
const char kNoAuthenticatorError[] = "Authenticator unavailable.";
+// Time to wait for an authenticator to successfully complete an operation.
+static const int kAdjustedTimeoutLower = 60;
+static const int kAdjustedTimeoutUpper = 120;
} // anonymous namespace
namespace mojo {
-
using webauth::mojom::blink::RelyingPartyAccount;
using webauth::mojom::blink::RelyingPartyAccountPtr;
+using webauth::mojom::blink::AuthenticatorStatus;
+using webauth::mojom::blink::ScopedCredentialDescriptor;
using webauth::mojom::blink::ScopedCredentialOptions;
using webauth::mojom::blink::ScopedCredentialOptionsPtr;
using webauth::mojom::blink::ScopedCredentialParameters;
using webauth::mojom::blink::ScopedCredentialParametersPtr;
-using webauth::mojom::blink::ScopedCredentialDescriptor;
using webauth::mojom::blink::ScopedCredentialType;
using webauth::mojom::blink::Transport;
// TODO(kpaulhamus): Make this a TypeConverter
Vector<uint8_t> ConvertBufferSource(const blink::BufferSource& buffer) {
- DCHECK(buffer.isNull());
+ DCHECK(!buffer.isNull());
Vector<uint8_t> vector;
if (buffer.isArrayBuffer()) {
vector.Append(static_cast<uint8_t*>(buffer.getAsArrayBuffer()->Data()),
@@ -69,6 +72,7 @@ Transport ConvertTransport(const String& transport) {
return Transport::USB;
}
+// TODO(kpaulhamus): Make this a TypeConverter
RelyingPartyAccountPtr ConvertRelyingPartyAccount(
const blink::RelyingPartyAccount& account_information,
blink::ScriptPromiseResolver* resolver) {
@@ -88,17 +92,30 @@ ScopedCredentialOptionsPtr ConvertScopedCredentialOptions(
const blink::ScopedCredentialOptions options,
blink::ScriptPromiseResolver* resolver) {
auto mojo_options = ScopedCredentialOptions::New();
- mojo_options->timeout_seconds = options.timeoutSeconds();
- mojo_options->relying_party_id = options.rpId();
-
- // Adds the excludeList members (which are ScopedCredentialDescriptors)
- for (const auto& descriptor : options.excludeList()) {
- auto mojo_descriptor = ScopedCredentialDescriptor::New();
- mojo_descriptor->type = ConvertScopedCredentialType(descriptor.type());
- mojo_descriptor->id = ConvertBufferSource(descriptor.id());
- for (const auto& transport : descriptor.transports())
- mojo_descriptor->transports.push_back(ConvertTransport(transport));
- mojo_options->exclude_list.push_back(std::move(mojo_descriptor));
+ if (options.hasRpId()) {
+ mojo_options->relying_party_id = options.rpId();
+ }
+
+ // Step 4 of https://w3c.github.io/webauthn/#createCredential
+ int predicted_timeout = kAdjustedTimeoutLower;
+ if (options.hasTimeoutSeconds()) {
+ predicted_timeout = static_cast<int>(options.timeoutSeconds());
+ }
+
+ mojo_options->adjusted_timeout = static_cast<double>(
+ std::max(kAdjustedTimeoutLower,
+ std::min(kAdjustedTimeoutUpper, predicted_timeout)));
+
+ if (options.hasExcludeList()) {
+ // Adds the excludeList members (which are ScopedCredentialDescriptors)
+ for (const auto& descriptor : options.excludeList()) {
+ auto mojo_descriptor = ScopedCredentialDescriptor::New();
+ mojo_descriptor->type = ConvertScopedCredentialType(descriptor.type());
+ mojo_descriptor->id = ConvertBufferSource(descriptor.id());
+ for (const auto& transport : descriptor.transports())
+ mojo_descriptor->transports.push_back(ConvertTransport(transport));
+ mojo_options->exclude_list.push_back(std::move(mojo_descriptor));
+ }
}
// TODO(kpaulhamus): add AuthenticationExtensions;
return mojo_options;
@@ -113,18 +130,37 @@ ScopedCredentialParametersPtr ConvertScopedCredentialParameter(
// TODO(kpaulhamus): add AlgorithmIdentifier
return mojo_parameter;
}
+
+blink::DOMException* CreateExceptionFromStatus(AuthenticatorStatus status) {
+ switch (status) {
+ case AuthenticatorStatus::NOT_ALLOWED_ERROR:
+ return blink::DOMException::Create(blink::kNotAllowedError,
+ "Not allowed.");
+ case AuthenticatorStatus::NOT_SUPPORTED_ERROR:
+ return blink::DOMException::Create(
+ blink::kNotSupportedError,
+ "Parameters for this operation are not supported.");
+ case AuthenticatorStatus::SECURITY_ERROR:
+ return blink::DOMException::Create(blink::kSecurityError,
+ "The operation was not allowed.");
+ case AuthenticatorStatus::UNKNOWN_ERROR:
+ return blink::DOMException::Create(blink::kUnknownError,
+ "Request failed.");
+ case AuthenticatorStatus::CANCELLED:
+ return blink::DOMException::Create(blink::kNotAllowedError,
+ "User canceled the operation.");
+ case AuthenticatorStatus::SUCCESS:
+ return nullptr;
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
} // namespace mojo
namespace blink {
-
WebAuthentication::WebAuthentication(LocalFrame& frame)
- : ContextLifecycleObserver(frame.GetDocument()) {
- frame.GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&authenticator_));
- authenticator_.set_connection_error_handler(ConvertToBaseCallback(
- WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError,
- WrapWeakPersistent(this))));
-}
+ : ContextLifecycleObserver(frame.GetDocument()) {}
WebAuthentication::~WebAuthentication() {
// |authenticator_| may still be valid but there should be no more
@@ -132,40 +168,36 @@ WebAuthentication::~WebAuthentication() {
DCHECK(authenticator_requests_.IsEmpty());
}
-void WebAuthentication::Dispose() {}
-
ScriptPromise WebAuthentication::makeCredential(
ScriptState* script_state,
const RelyingPartyAccount& account_information,
const HeapVector<ScopedCredentialParameters> crypto_parameters,
const BufferSource& attestation_challenge,
ScopedCredentialOptions& options) {
- if (!authenticator_) {
- return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError));
- }
+ ScriptPromise promise = RejectIfNotSupported(script_state);
+ if (!promise.IsEmpty())
+ return promise;
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- // TODO(kpaulhamus) validate parameters according to spec
- auto account =
- mojo::ConvertRelyingPartyAccount(account_information, resolver);
Vector<uint8_t> buffer = mojo::ConvertBufferSource(attestation_challenge);
auto opts = mojo::ConvertScopedCredentialOptions(options, resolver);
Vector<webauth::mojom::blink::ScopedCredentialParametersPtr> parameters;
for (const auto& parameter : crypto_parameters) {
- parameters.push_back(
- mojo::ConvertScopedCredentialParameter(parameter, resolver));
+ if (parameter.hasType()) {
+ parameters.push_back(
+ mojo::ConvertScopedCredentialParameter(parameter, resolver));
+ }
}
-
+ auto account =
+ mojo::ConvertRelyingPartyAccount(account_information, resolver);
authenticator_requests_.insert(resolver);
authenticator_->MakeCredential(
std::move(account), std::move(parameters), buffer, std::move(opts),
- ConvertToBaseCallback(Bind(&WebAuthentication::OnMakeCredential,
- WrapPersistent(this),
- WrapPersistent(resolver))));
- return promise;
+ ConvertToBaseCallback(WTF::Bind(&WebAuthentication::OnMakeCredential,
+ WrapPersistent(this),
+ WrapPersistent(resolver))));
+ return resolver->Promise();
}
ScriptPromise WebAuthentication::getAssertion(
@@ -177,44 +209,65 @@ ScriptPromise WebAuthentication::getAssertion(
}
void WebAuthentication::ContextDestroyed(ExecutionContext*) {
- authenticator_.reset();
- authenticator_requests_.clear();
-}
-
-void WebAuthentication::OnAuthenticatorConnectionError() {
- authenticator_.reset();
- for (ScriptPromiseResolver* resolver : authenticator_requests_) {
- resolver->Reject(
- DOMException::Create(kNotFoundError, kNoAuthenticatorError));
- }
- authenticator_requests_.clear();
+ Cleanup();
}
void WebAuthentication::OnMakeCredential(
ScriptPromiseResolver* resolver,
- Vector<webauth::mojom::blink::ScopedCredentialInfoPtr> credentials) {
+ webauth::mojom::blink::AuthenticatorStatus status,
+ webauth::mojom::blink::ScopedCredentialInfoPtr credential) {
if (!MarkRequestComplete(resolver))
return;
- HeapVector<Member<ScopedCredentialInfo>> scoped_credentials;
- for (auto& credential : credentials) {
- if (credential->client_data.IsEmpty() ||
- credential->attestation.IsEmpty()) {
- resolver->Reject(
- DOMException::Create(kNotFoundError, "No credentials returned."));
+ DOMException* error = mojo::CreateExceptionFromStatus(status);
+ if (error) {
+ resolver->Reject(error);
+ Cleanup();
+ return;
+ }
+
+ if (credential->client_data.IsEmpty() || credential->attestation.IsEmpty()) {
+ resolver->Reject(
+ DOMException::Create(kNotFoundError, "No credential returned."));
+ return;
+ }
+
+ DOMArrayBuffer* clientDataBuffer = DOMArrayBuffer::Create(
+ static_cast<void*>(&credential->client_data.front()),
+ credential->client_data.size());
+
+ DOMArrayBuffer* attestationBuffer = DOMArrayBuffer::Create(
+ static_cast<void*>(&credential->attestation.front()),
+ credential->attestation.size());
+
+ ScopedCredentialInfo* scopedCredential =
+ ScopedCredentialInfo::Create(clientDataBuffer, attestationBuffer);
+ resolver->Resolve(scopedCredential);
+}
+
+ScriptPromise WebAuthentication::RejectIfNotSupported(
+ ScriptState* script_state) {
+ if (!authenticator_) {
+ if (!GetFrame()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(kNotSupportedError));
}
- DOMArrayBuffer* client_data_buffer = DOMArrayBuffer::Create(
- static_cast<void*>(&credential->client_data.front()),
- credential->client_data.size());
+ GetFrame()->GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&authenticator_));
- DOMArrayBuffer* attestation_buffer = DOMArrayBuffer::Create(
- static_cast<void*>(&credential->attestation.front()),
- credential->attestation.size());
+ authenticator_.set_connection_error_handler(ConvertToBaseCallback(
+ WTF::Bind(&WebAuthentication::OnAuthenticatorConnectionError,
+ WrapWeakPersistent(this))));
+ }
+ return ScriptPromise();
+}
- scoped_credentials.push_back(
- ScopedCredentialInfo::Create(client_data_buffer, attestation_buffer));
+void WebAuthentication::OnAuthenticatorConnectionError() {
+ for (ScriptPromiseResolver* resolver : authenticator_requests_) {
+ resolver->Reject(
+ DOMException::Create(kNotFoundError, kNoAuthenticatorError));
}
- resolver->Resolve();
+ Cleanup();
}
bool WebAuthentication::MarkRequestComplete(ScriptPromiseResolver* resolver) {
@@ -230,4 +283,10 @@ DEFINE_TRACE(WebAuthentication) {
ContextLifecycleObserver::Trace(visitor);
}
+// Clears the promise resolver, timer, and closes the Mojo connection.
+void WebAuthentication::Cleanup() {
+ authenticator_.reset();
+ authenticator_requests_.clear();
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698