--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -44,17 +44,16 @@
#include "mozilla/dom/Presentation.h"
#include "mozilla/dom/ServiceWorkerContainer.h"
#include "mozilla/dom/StorageManager.h"
#include "mozilla/dom/TCPSocket.h"
#include "mozilla/dom/URLSearchParams.h"
#include "mozilla/dom/VRDisplay.h"
#include "mozilla/dom/VRDisplayEvent.h"
#include "mozilla/dom/VRServiceTest.h"
-#include "mozilla/dom/WebAuthentication.h"
#include "mozilla/dom/workers/RuntimeService.h"
#include "mozilla/Hal.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/SSE.h"
#include "mozilla/StaticPtr.h"
#include "Connection.h"
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
#include "nsGlobalWindow.h"
@@ -201,17 +200,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
- NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAuthentication)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCredentials)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresentation)
@@ -1998,25 +1996,16 @@ Navigator::GetPresentation(ErrorResult&
return nullptr;
}
mPresentation = Presentation::Create(mWindow);
}
return mPresentation;
}
-WebAuthentication*
-Navigator::Authentication()
-{
- if (!mAuthentication) {
- mAuthentication = new WebAuthentication(GetWindow());
- }
- return mAuthentication;
-}
-
CredentialsContainer*
Navigator::Credentials()
{
if (!mCredentials) {
mCredentials = new CredentialsContainer(GetWindow());
}
return mCredentials;
}
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -37,17 +37,16 @@ class systemMessageCallback;
class MediaDevices;
struct MediaStreamConstraints;
class WakeLock;
class ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams;
class ServiceWorkerContainer;
class DOMRequest;
struct FlyWebPublishOptions;
struct FlyWebFilter;
-class WebAuthentication;
class CredentialsContainer;
} // namespace dom
} // namespace mozilla
//*****************************************************************************
// Navigator: Script "navigator" object
//*****************************************************************************
@@ -221,17 +220,16 @@ public:
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
NavigatorUserMediaErrorCallback& aOnError,
uint64_t aInnerWindowID,
const nsAString& aCallID,
ErrorResult& aRv);
already_AddRefed<ServiceWorkerContainer> ServiceWorker();
- mozilla::dom::WebAuthentication* Authentication();
mozilla::dom::CredentialsContainer* Credentials();
void GetLanguages(nsTArray<nsString>& aLanguages);
bool MozE10sEnabled();
StorageManager* Storage();
@@ -291,17 +289,16 @@ private:
RefPtr<nsPluginArray> mPlugins;
RefPtr<Permissions> mPermissions;
RefPtr<Geolocation> mGeolocation;
RefPtr<DesktopNotificationCenter> mNotification;
RefPtr<battery::BatteryManager> mBatteryManager;
RefPtr<Promise> mBatteryPromise;
RefPtr<PowerManager> mPowerManager;
RefPtr<network::Connection> mConnection;
- RefPtr<WebAuthentication> mAuthentication;
RefPtr<CredentialsContainer> mCredentials;
RefPtr<MediaDevices> mMediaDevices;
RefPtr<time::TimeManager> mTimeManager;
RefPtr<ServiceWorkerContainer> mServiceWorkerContainer;
nsCOMPtr<nsPIDOMWindowInner> mWindow;
RefPtr<Presentation> mPresentation;
RefPtr<GamepadServiceTest> mGamepadServiceTest;
nsTArray<RefPtr<Promise> > mVRGetDisplaysPromises;
--- a/dom/credentialmanagement/CredentialsContainer.cpp
+++ b/dom/credentialmanagement/CredentialsContainer.cpp
@@ -30,16 +30,24 @@ CredentialsContainer::~CredentialsContai
JSObject*
CredentialsContainer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return CredentialsContainerBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
+CredentialsContainer::Get(const CredentialRequestOptions& aOptions)
+{
+ RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
+ MOZ_ASSERT(mgr);
+ return mgr->GetAssertion(mParent, aOptions.mPublicKey);
+}
+
+already_AddRefed<Promise>
CredentialsContainer::Create(const CredentialCreationOptions& aOptions)
{
RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
MOZ_ASSERT(mgr);
return mgr->MakeCredential(mParent, aOptions.mPublicKey);
}
} // namespace dom
--- a/dom/credentialmanagement/CredentialsContainer.h
+++ b/dom/credentialmanagement/CredentialsContainer.h
@@ -26,16 +26,18 @@ public:
{
return mParent;
}
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<Promise>
+ Get(const CredentialRequestOptions& aOptions);
+ already_AddRefed<Promise>
Create(const CredentialCreationOptions& aOptions);
private:
~CredentialsContainer();
nsCOMPtr<nsPIDOMWindowInner> mParent;
};
deleted file mode 100644
--- a/dom/webauthn/WebAuthentication.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/WebAuthentication.h"
-#include "mozilla/dom/WebAuthnManager.h"
-
-namespace mozilla {
-namespace dom {
-
-// Only needed for refcounted objects.
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebAuthentication, mParent)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(WebAuthentication)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(WebAuthentication)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebAuthentication)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-WebAuthentication::WebAuthentication(nsPIDOMWindowInner* aParent) :
- mParent(aParent)
-{
- MOZ_ASSERT(aParent);
-}
-
-WebAuthentication::~WebAuthentication()
-{}
-
-JSObject*
-WebAuthentication::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
- return WebAuthenticationBinding::Wrap(aCx, this, aGivenProto);
-}
-
-already_AddRefed<Promise>
-WebAuthentication::GetAssertion(const ArrayBufferViewOrArrayBuffer& aChallenge,
- const AssertionOptions& aOptions)
-{
- RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
- MOZ_ASSERT(mgr);
- return mgr->GetAssertion(mParent, aChallenge, aOptions);
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/webauthn/WebAuthentication.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_WebAuthentication_h
-#define mozilla_dom_WebAuthentication_h
-
-#include "mozilla/dom/WebAuthenticationBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-struct Account;
-class ArrayBufferViewOrArrayBuffer;
-struct AssertionOptions;
-struct ScopedCredentialOptions;
-struct ScopedCredentialParameters;
-
-} // namespace dom
-} // namespace mozilla
-
-namespace mozilla {
-namespace dom {
-
-class WebAuthentication final : public nsISupports
- , public nsWrapperCache
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebAuthentication)
-
- explicit WebAuthentication(nsPIDOMWindowInner* aParent);
-
- nsPIDOMWindowInner*
- GetParentObject() const
- {
- return mParent;
- }
-
- virtual JSObject*
- WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
- already_AddRefed<Promise>
- GetAssertion(const ArrayBufferViewOrArrayBuffer& assertionChallenge,
- const AssertionOptions& options);
-private:
- ~WebAuthentication();
-
- already_AddRefed<Promise> CreatePromise();
- nsresult GetOrigin(/*out*/ nsAString& aOrigin);
-
- nsCOMPtr<nsPIDOMWindowInner> mParent;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_WebAuthentication_h
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -451,18 +451,17 @@ void
WebAuthnManager::StartSign() {
if (mChild) {
mChild->SendRequestSign(mInfo.ref());
}
}
already_AddRefed<Promise>
WebAuthnManager::GetAssertion(nsPIDOMWindowInner* aParent,
- const ArrayBufferViewOrArrayBuffer& aChallenge,
- const AssertionOptions& aOptions)
+ const PublicKeyCredentialRequestOptions& aOptions)
{
MOZ_ASSERT(aParent);
MaybeClearTransaction();
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
ErrorResult rv;
@@ -477,21 +476,21 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
promise->MaybeReject(rv);
return promise.forget();
}
// If timeoutSeconds was specified, check if its value lies within a
// reasonable range as defined by the platform and if not, correct it to the
// closest value lying within that range.
- double adjustedTimeout = 30.0;
- if (aOptions.mTimeoutSeconds.WasPassed()) {
- adjustedTimeout = aOptions.mTimeoutSeconds.Value();
- adjustedTimeout = std::max(15.0, adjustedTimeout);
- adjustedTimeout = std::min(120.0, adjustedTimeout);
+ uint32_t adjustedTimeout = 30000;
+ if (aOptions.mTimeout.WasPassed()) {
+ adjustedTimeout = aOptions.mTimeout.Value();
+ adjustedTimeout = std::max(15000u, adjustedTimeout);
+ adjustedTimeout = std::min(120000u, adjustedTimeout);
}
nsCString rpId;
if (!aOptions.mRpId.WasPassed()) {
// If rpId is not specified, then set rpId to callerOrigin, and rpIdHash to
// the SHA-256 hash of rpId.
rpId.Assign(NS_ConvertUTF16toUTF8(origin));
} else {
@@ -529,17 +528,17 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
return promise.forget();
}
// Use assertionChallenge, callerOrigin and rpId, along with the token binding
// key associated with callerOrigin (if any), to create a ClientData structure
// representing this request. Choose a hash algorithm for hashAlg and compute
// the clientDataJSON and clientDataHash.
CryptoBuffer challenge;
- if (!challenge.Assign(aChallenge)) {
+ if (!challenge.Assign(aOptions.mChallenge)) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
nsAutoCString clientDataJSON;
srv = AssembleClientData(origin, challenge, clientDataJSON);
if (NS_WARN_IF(NS_FAILED(srv))) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
@@ -555,23 +554,23 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
srv = HashCString(hashService, clientDataJSON, clientDataHash);
if (NS_WARN_IF(NS_FAILED(srv))) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
// Note: we only support U2F-style authentication for now, so we effectively
// require an AllowList.
- if (!aOptions.mAllowList.WasPassed()) {
+ if (aOptions.mAllowList.Length() < 1) {
promise->MaybeReject(NS_ERROR_DOM_NOT_ALLOWED_ERR);
return promise.forget();
}
nsTArray<WebAuthnScopedCredentialDescriptor> allowList;
- for (const auto& s: aOptions.mAllowList.Value()) {
+ for (const auto& s: aOptions.mAllowList) {
WebAuthnScopedCredentialDescriptor c;
CryptoBuffer cb;
cb.Assign(s.mId);
c.id() = cb;
allowList.AppendElement(c);
}
// TODO: Add extension list building
@@ -579,17 +578,17 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
// client platform, to produce the extension data that needs to be sent to the
// authenticator. If an error is encountered while processing an extension,
// skip that extension and do not produce any extension data for it. Call the
// result of this processing clientExtensions.
nsTArray<WebAuthnExtension> extensions;
WebAuthnTransactionInfo info(rpIdHash,
clientDataHash,
- 10000,
+ adjustedTimeout,
allowList,
extensions);
RefPtr<MozPromise<nsresult, nsresult, false>> p = GetOrCreateBackgroundActor();
p->Then(AbstractThread::MainThread(), __func__,
[]() {
WebAuthnManager* mgr = WebAuthnManager::Get();
if (!mgr) {
return;
--- a/dom/webauthn/WebAuthnManager.h
+++ b/dom/webauthn/WebAuthnManager.h
@@ -73,18 +73,17 @@ public:
Cancel(const nsresult& aError);
already_AddRefed<Promise>
MakeCredential(nsPIDOMWindowInner* aParent,
const MakeCredentialOptions& aOptions);
already_AddRefed<Promise>
GetAssertion(nsPIDOMWindowInner* aParent,
- const ArrayBufferViewOrArrayBuffer& aAssertionChallenge,
- const AssertionOptions& aOptions);
+ const PublicKeyCredentialRequestOptions& aOptions);
void StartRegister();
void StartSign();
// nsIIPCbackgroundChildCreateCallback methods
void ActorCreated(PBackgroundChild* aActor) override;
void ActorFailed() override;
void ActorDestroyed();
--- a/dom/webauthn/moz.build
+++ b/dom/webauthn/moz.build
@@ -15,33 +15,31 @@ EXPORTS.mozilla.dom += [
'AuthenticatorAssertionResponse.h',
'AuthenticatorAttestationResponse.h',
'AuthenticatorResponse.h',
'NSSU2FTokenRemote.h',
'PublicKeyCredential.h',
'U2FSoftTokenManager.h',
'U2FTokenManager.h',
'U2FTokenTransport.h',
- 'WebAuthentication.h',
'WebAuthnManager.h',
'WebAuthnRequest.h',
'WebAuthnTransactionChild.h',
'WebAuthnTransactionParent.h',
'WebAuthnUtil.h'
]
UNIFIED_SOURCES += [
'AuthenticatorAssertionResponse.cpp',
'AuthenticatorAttestationResponse.cpp',
'AuthenticatorResponse.cpp',
'NSSU2FTokenRemote.cpp',
'PublicKeyCredential.cpp',
'U2FSoftTokenManager.cpp',
'U2FTokenManager.cpp',
- 'WebAuthentication.cpp',
'WebAuthnManager.cpp',
'WebAuthnTransactionChild.cpp',
'WebAuthnTransactionParent.cpp',
'WebAuthnUtil.cpp'
]
include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/webauthn/tests/test_webauthn_get_assertion.html
+++ b/dom/webauthn/tests/test_webauthn_get_assertion.html
@@ -11,100 +11,119 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Tests for GetAssertion for W3C Web Authentication</h1>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1309284">Mozilla Bug 1309284</a>
<script class="testbody" type="text/javascript">
- "use strict";
-
- // Execute the full-scope test
- SimpleTest.waitForExplicitFinish();
+ "use strict";
- function arrivingHereIsBad(aResult) {
- ok(false, "Bad result! Received a: " + aResult);
- return Promise.resolve();
- }
+ // Execute the full-scope test
+ SimpleTest.waitForExplicitFinish();
- function expectNotAllowedError(aResult) {
- ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError");
- return Promise.resolve();
- }
+ function arrivingHereIsBad(aResult) {
+ ok(false, "Bad result! Received a: " + aResult);
+ return Promise.resolve();
+ }
- function expectTypeError(aResult) {
- ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
- return Promise.resolve();
- }
+ function expectNotAllowedError(aResult) {
+ ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError");
+ return Promise.resolve();
+ }
- SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
- ["security.webauth.webauthn_enable_softtoken", true],
- ["security.webauth.webauthn_enable_usbtoken", false]]},
- runTests);
+ function expectTypeError(aResult) {
+ ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
+ return Promise.resolve();
+ }
+
+ SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
+ ["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_usbtoken", false]]},
+ runTests);
- function runTests() {
- isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
- isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
- is(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint does not exist any longer");
- isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
- isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
+ function runTests() {
+ is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
+ isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
+ isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
+ isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist");
- let authn = navigator.authentication;
+ let credm = navigator.credentials;
- let gAssertionChallenge = new Uint8Array(16);
- window.crypto.getRandomValues(gAssertionChallenge);
+ let gAssertionChallenge = new Uint8Array(16);
+ window.crypto.getRandomValues(gAssertionChallenge);
- let invalidCred = { type: "Magic", id: base64ToBytes("AAA=") };
- let unknownCred = { type: "ScopedCred", id: base64ToBytes("AAA=") };
+ let invalidCred = {type: "Magic", id: base64ToBytes("AAA=")};
+ let unknownCred = {type: "public-key", id: base64ToBytes("AAA=")};
- var testFuncs = [
- function () {
- // Test basic good call, but without giving a credential so expect failures
- // this is OK by the standard, but not supported by U2F-backed authenticators
- // like the soft token in use here.
- return authn.getAssertion(gAssertionChallenge)
- .then(arrivingHereIsBad)
- .catch(expectNotAllowedError);
- },
- function () {
- // Test with an unexpected option
- return authn.getAssertion(gAssertionChallenge, { unknownValue: "hi" })
- .then(arrivingHereIsBad)
- .catch(expectNotAllowedError);
- },
- function () {
- // Test with an invalid credential
- return authn.getAssertion(gAssertionChallenge, { allowList: [invalidCred] })
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
- function () {
- // Test with an unknown credential
- return authn.getAssertion(gAssertionChallenge, { allowList: [unknownCred] })
- .then(arrivingHereIsBad)
- .catch(expectNotAllowedError);
- },
- function () {
- // Test with an unexpected option and an invalid credential
- return authn.getAssertion(gAssertionChallenge, { unknownValue: "hi" })
- .then(arrivingHereIsBad)
- .catch(expectNotAllowedError);
- }
- ];
+ var testFuncs = [
+ function () {
+ // Test basic good call, but without giving a credential so expect failures
+ // this is OK by the standard, but not supported by U2F-backed authenticators
+ // like the soft token in use here.
+ let publicKeyCredentialRequestOptions = {
+ challenge: gAssertionChallenge
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectNotAllowedError);
+ },
+ function () {
+ // Test with an unexpected option
+ let publicKeyCredentialRequestOptions = {
+ challenge: gAssertionChallenge,
+ unknownValue: "hi"
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectNotAllowedError);
+ },
+ function () {
+ // Test with an invalid credential
+ let publicKeyCredentialRequestOptions = {
+ challenge: gAssertionChallenge,
+ allowList: [invalidCred]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
+ function () {
+ // Test with an unknown credential
+ let publicKeyCredentialRequestOptions = {
+ challenge: gAssertionChallenge,
+ allowList: [unknownCred]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectNotAllowedError);
+ },
+ function () {
+ // Test with an unexpected option and an invalid credential
+ let publicKeyCredentialRequestOptions = {
+ challenge: gAssertionChallenge,
+ unknownValue: "hi",
+ allowList: [invalidCred]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ }
+ ];
- var i = 0;
- var runNextTest = () => {
- if (i == testFuncs.length) {
- SimpleTest.finish();
- return;
- }
- testFuncs[i]().then(() => { runNextTest(); });
- i = i + 1;
- };
- runNextTest();
+ var i = 0;
+ var runNextTest = () => {
+ if (i == testFuncs.length) {
+ SimpleTest.finish();
+ return;
+ }
+ testFuncs[i]().then(() => { runNextTest(); });
+ i = i + 1;
+ };
+ runNextTest();
- }
+ }
</script>
</body>
</html>
--- a/dom/webauthn/tests/test_webauthn_loopback.html
+++ b/dom/webauthn/tests/test_webauthn_loopback.html
@@ -20,23 +20,21 @@
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false]]},
function() {
- isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
+ is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
- is(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint does not exist any longer");
- isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
+ isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist");
- let authn = navigator.authentication;
let credm = navigator.credentials;
let gCredentialChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gCredentialChallenge);
let gAssertionChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gAssertionChallenge);
testMakeCredential();
@@ -145,24 +143,28 @@ function() {
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), "Expect NotAllowedError, got " + aReason);
testAssertion(aCredInfo);
});
}
function testAssertion(aCredInfo) {
let newCredential = {
- type: "ScopedCred",
+ type: "public-key",
id: Uint8Array.from(aCredInfo.rawId),
transports: ["usb"],
}
- let assertOptions = {rpId: document.origin, timeoutSeconds: 5,
- allowList: [newCredential]};
- authn.getAssertion(gAssertionChallenge, assertOptions)
+ let publicKeyCredentialRequestOptions = {
+ challenge: gAssertionChallenge,
+ timeout: 5000, // the minimum timeout is actually 15 seconds
+ rpId: document.origin,
+ allowList: [newCredential]
+ };
+ credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(function(aAssertion) {
/* Pass along the pubKey. */
return checkAssertionAndSigValid(aCredInfo.u2fReg.publicKey, aAssertion);
})
.then(function(aSigVerifyResult) {
ok(aSigVerifyResult, "Signing signature verified");
SimpleTest.finish();
})
--- a/dom/webauthn/tests/test_webauthn_make_credential.html
+++ b/dom/webauthn/tests/test_webauthn_make_credential.html
@@ -45,23 +45,21 @@
ok(aResult.toString().startsWith("NotSupportedError"), "Expecting a NotSupportedError");
return Promise.resolve();
}
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", true],
["security.webauth.webauthn_enable_usbtoken", false]]}, runTests);
function runTests() {
- isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
+ is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
- is(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint does not exist any longer");
- isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
+ isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist");
- let authn = navigator.authentication;
let credm = navigator.credentials;
let gCredentialChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gCredentialChallenge);
let rp = {id: "none", name: "none", icon: "none"};
let user = {id: "none", name: "none", icon: "none", displayName: "none"};
let param = {type: "public-key", algorithm: "p-256"};
--- a/dom/webauthn/tests/test_webauthn_no_token.html
+++ b/dom/webauthn/tests/test_webauthn_no_token.html
@@ -21,23 +21,21 @@
// Execute the full-scope test
SimpleTest.waitForExplicitFinish();
// Turn off all tokens. This should result in "not allowed" failures
SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
["security.webauth.webauthn_enable_softtoken", false],
["security.webauth.webauthn_enable_usbtoken", false]]},
function() {
- isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
+ is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
- is(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint does not exist any longer");
- isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
+ isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist");
- let authn = navigator.authentication;
let credm = navigator.credentials;
let credentialChallenge = new Uint8Array(16);
window.crypto.getRandomValues(credentialChallenge);
let assertionChallenge = new Uint8Array(16);
window.crypto.getRandomValues(assertionChallenge);
let credentialId = new Uint8Array(128);
window.crypto.getRandomValues(credentialId);
@@ -59,23 +57,27 @@ function() {
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), aReason);
testAssertion();
});
}
function testAssertion() {
let newCredential = {
- type: "ScopedCred",
+ type: "public-key",
id: credentialId,
transports: ["usb"],
}
- let assertOptions = {rpId: document.origin, timeoutSeconds: 5,
- allowList: [newCredential]};
- authn.getAssertion(assertionChallenge, assertOptions)
+ let publicKeyCredentialRequestOptions = {
+ challenge: assertionChallenge,
+ timeout: 5000, // the minimum timeout is actually 15 seconds
+ rpId: document.origin,
+ allowList: [newCredential]
+ };
+ credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(function(aResult) {
ok(false, "Should have failed.");
SimpleTest.finish();
})
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), aReason);
SimpleTest.finish();
})
--- a/dom/webauthn/tests/test_webauthn_sameorigin.html
+++ b/dom/webauthn/tests/test_webauthn_sameorigin.html
@@ -37,31 +37,29 @@
function expectSecurityError(aResult) {
// TODO: Change to `ok` when Bug 1329764 lands
todo(aResult.toString().startsWith("SecurityError"), "Expecting a SecurityError");
return Promise.resolve();
}
function keepThisPublicKeyCredential(aPublicKeyCredential) {
gTrackedCredential = {
- type: "ScopedCred",
+ type: "public-key",
id: Uint8Array.from(aPublicKeyCredential.rawId),
transports: [ "usb" ],
}
return Promise.resolve(aPublicKeyCredential);
}
function runTests() {
- isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
+ is(navigator.authentication, undefined, "navigator.authentication does not exist any longer");
isnot(navigator.credentials, undefined, "Credential Management API endpoint must exist");
- is(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint does not exist any longer");
- isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
isnot(navigator.credentials.create, undefined, "CredentialManagement create API endpoint must exist");
+ isnot(navigator.credentials.get, undefined, "CredentialManagement get API endpoint must exist");
- let authn = navigator.authentication;
let credm = navigator.credentials;
let chall = new Uint8Array(16);
window.crypto.getRandomValues(chall);
let user = {id: "none", name: "none", icon: "none", displayName: "none"};
let param = {type: "public-key", algorithm: "p-256"};
@@ -134,59 +132,87 @@
rp: rp, user: user, challenge: chall, parameters: [param]
};
return credm.create({publicKey: makeCredentialOptions})
.then(arrivingHereIsBad)
.catch(expectSecurityError);
},
function () {
// Test basic good call
- return authn.getAssertion(chall, {allowList: [gTrackedCredential],
- rpId: document.origin})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ rpId: document.origin,
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
},
function () {
// Test rpId being unset
- return authn.getAssertion(chall, {allowList: [gTrackedCredential]})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsGood)
.catch(arrivingHereIsBad);
},
function () {
// Test this origin with optional fields
- return authn.getAssertion(chall, {allowList: [gTrackedCredential],
- rpId: "user:pass@" + document.origin + ":8888"})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ rpId: "user:pass@" + document.origin + ":8888",
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsBad)
.catch(expectSecurityError);
},
function () {
// Test blank rpId
- return authn.getAssertion(chall, {allowList: [gTrackedCredential],
- rpId: ""})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ rpId: "",
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsBad)
.catch(expectSecurityError);
},
function () {
// Test subdomain of this origin
- return authn.getAssertion(chall, {allowList: [gTrackedCredential],
- rpId: "subdomain." + document.origin})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ rpId: "subdomain." + document.origin,
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsBad)
.catch(expectSecurityError);
},
function () {
// Test another origin
- return authn.getAssertion(chall, {allowList: [gTrackedCredential],
- rpId: "example.com"})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ rpId: "example.com",
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsBad)
.catch(expectSecurityError);
},
function () {
// Test a different domain within the same TLD
- return authn.getAssertion(chall, {allowList: [gTrackedCredential],
- rpId: "alt.test"})
+ let publicKeyCredentialRequestOptions = {
+ challenge: chall,
+ rpId: "alt.test",
+ allowList: [gTrackedCredential]
+ };
+ return credm.get({publicKey: publicKeyCredentialRequestOptions})
.then(arrivingHereIsBad)
.catch(expectSecurityError)
},
function () {
SimpleTest.finish();
}
];
var i = 0;
--- a/dom/webidl/CredentialManagement.webidl
+++ b/dom/webidl/CredentialManagement.webidl
@@ -10,14 +10,19 @@
[Exposed=Window, SecureContext, Pref="security.webauth.webauthn"]
interface Credential {
readonly attribute USVString id;
readonly attribute DOMString type;
};
[Exposed=Window, SecureContext, Pref="security.webauth.webauthn"]
interface CredentialsContainer {
+ Promise<Credential?> get(optional CredentialRequestOptions options);
Promise<Credential?> create(optional CredentialCreationOptions options);
};
+dictionary CredentialRequestOptions {
+ PublicKeyCredentialRequestOptions publicKey;
+};
+
dictionary CredentialCreationOptions {
MakeCredentialOptions publicKey;
};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -366,15 +366,10 @@ partial interface Navigator {
[NoInterfaceObject, Exposed=(Window,Worker)]
interface NavigatorConcurrentHardware {
readonly attribute unsigned long long hardwareConcurrency;
};
partial interface Navigator {
[Pref="security.webauth.webauthn", SameObject]
- readonly attribute WebAuthentication authentication;
-};
-
-partial interface Navigator {
- [Pref="security.webauth.webauthn", SameObject]
readonly attribute CredentialsContainer credentials;
};
--- a/dom/webidl/WebAuthentication.webidl
+++ b/dom/webidl/WebAuthentication.webidl
@@ -61,16 +61,25 @@ dictionary AuthenticatorSelectionCriteri
boolean requireResidentKey = false;
};
enum Attachment {
"platform",
"cross-platform"
};
+dictionary PublicKeyCredentialRequestOptions {
+ required BufferSource challenge;
+ unsigned long timeout;
+ USVString rpId;
+ sequence<PublicKeyCredentialDescriptor> allowList = [];
+ // Extensions are not supported yet.
+ // AuthenticationExtensions extensions;
+};
+
dictionary CollectedClientData {
required DOMString challenge;
required DOMString origin;
required DOMString hashAlg;
DOMString tokenBinding;
// Extensions are not supported yet.
// AuthenticationExtensions clientExtensions;
// AuthenticationExtensions authenticatorExtensions;
@@ -89,44 +98,14 @@ dictionary PublicKeyCredentialDescriptor
typedef (boolean or DOMString) WebAuthnAlgorithmID; // Fix when upstream there's a definition of how to serialize AlgorithmIdentifier
[SecureContext, Pref="security.webauth.webauthn"]
interface AuthenticatorAssertionResponse : AuthenticatorResponse {
readonly attribute ArrayBuffer authenticatorData;
readonly attribute ArrayBuffer signature;
};
-dictionary AssertionOptions {
- unsigned long timeoutSeconds;
- USVString rpId;
- sequence<ScopedCredentialDescriptor> allowList;
- WebAuthnExtensions extensions;
-};
-
-dictionary WebAuthnExtensions {
-};
-
-enum ScopedCredentialType {
- "ScopedCred"
-};
-
-dictionary ScopedCredentialDescriptor {
- required ScopedCredentialType type;
- required BufferSource id;
- sequence <WebAuthnTransport> transports;
-};
-
// Renamed from "Transport" to avoid a collision with U2F
enum WebAuthnTransport {
"usb",
"nfc",
"ble"
};
-
-/***** The Main API *****/
-
-[SecureContext, Pref="security.webauth.webauthn"]
-interface WebAuthentication {
- Promise<PublicKeyCredential> getAssertion (
- BufferSource assertionChallenge,
- optional AssertionOptions options
- );
-};