--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -28,16 +28,17 @@
#include "nsICookiePermission.h"
#include "nsIScriptSecurityManager.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsContentUtils.h"
#include "nsUnicharUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "BatteryManager.h"
+#include "mozilla/dom/CredentialsContainer.h"
#include "mozilla/dom/GamepadServiceTest.h"
#include "mozilla/dom/PowerManager.h"
#include "mozilla/dom/WakeLock.h"
#include "mozilla/dom/power/PowerManagerService.h"
#include "mozilla/dom/FlyWebPublishedServer.h"
#include "mozilla/dom/FlyWebService.h"
#include "mozilla/dom/Permissions.h"
#include "mozilla/dom/Presentation.h"
@@ -201,16 +202,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
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)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
@@ -2005,10 +2007,19 @@ WebAuthentication*
Navigator::Authentication()
{
if (!mAuthentication) {
mAuthentication = new WebAuthentication(GetWindow());
}
return mAuthentication;
}
+CredentialsContainer*
+Navigator::Credentials()
+{
+ if (!mCredentials) {
+ mCredentials = new CredentialsContainer(GetWindow());
+ }
+ return mCredentials;
+}
+
} // namespace dom
} // namespace mozilla
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -38,16 +38,17 @@ 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
//*****************************************************************************
namespace mozilla {
@@ -221,16 +222,17 @@ public:
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();
static void GetAcceptLanguages(nsTArray<nsString>& aLanguages);
@@ -290,16 +292,17 @@ private:
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;
RefPtr<VRServiceTest> mVRServiceTest;
copy from dom/webauthn/WebAuthentication.cpp
copy to dom/credentialmanagement/CredentialsContainer.cpp
--- a/dom/webauthn/WebAuthentication.cpp
+++ b/dom/credentialmanagement/CredentialsContainer.cpp
@@ -1,58 +1,46 @@
/* -*- 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/CredentialsContainer.h"
+#include "mozilla/dom/Promise.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_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CredentialsContainer, mParent)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(CredentialsContainer)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(CredentialsContainer)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CredentialsContainer)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
-WebAuthentication::WebAuthentication(nsPIDOMWindowInner* aParent) :
+CredentialsContainer::CredentialsContainer(nsPIDOMWindowInner* aParent) :
mParent(aParent)
{
MOZ_ASSERT(aParent);
}
-WebAuthentication::~WebAuthentication()
+CredentialsContainer::~CredentialsContainer()
{}
JSObject*
-WebAuthentication::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+CredentialsContainer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
- return WebAuthenticationBinding::Wrap(aCx, this, aGivenProto);
+ return CredentialsContainerBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
-WebAuthentication::MakeCredential(JSContext* aCx, const Account& aAccount,
- const Sequence<ScopedCredentialParameters>& aCryptoParameters,
- const ArrayBufferViewOrArrayBuffer& aChallenge,
- const ScopedCredentialOptions& aOptions)
+CredentialsContainer::Create(const CredentialCreationOptions& aOptions)
{
RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
MOZ_ASSERT(mgr);
- return mgr->MakeCredential(mParent, aCx, aAccount, aCryptoParameters, aChallenge, aOptions);
-}
-
-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);
+ return mgr->MakeCredential(mParent, aOptions.mPublicKey);
}
} // namespace dom
} // namespace mozilla
copy from dom/webauthn/WebAuthentication.h
copy to dom/credentialmanagement/CredentialsContainer.h
--- a/dom/webauthn/WebAuthentication.h
+++ b/dom/credentialmanagement/CredentialsContainer.h
@@ -1,66 +1,45 @@
/* -*- 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
+#ifndef mozilla_dom_CredentialsContainer_h
+#define mozilla_dom_CredentialsContainer_h
-#include "mozilla/dom/WebAuthenticationBinding.h"
+#include "mozilla/dom/CredentialManagementBinding.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
+class CredentialsContainer final : public nsISupports
+ , public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebAuthentication)
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CredentialsContainer)
- explicit WebAuthentication(nsPIDOMWindowInner* aParent);
+ explicit CredentialsContainer(nsPIDOMWindowInner* aParent);
nsPIDOMWindowInner*
GetParentObject() const
{
return mParent;
}
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<Promise>
- MakeCredential(JSContext* aCx, const Account& accountInformation,
- const Sequence<ScopedCredentialParameters>& cryptoParameters,
- const ArrayBufferViewOrArrayBuffer& attestationChallenge,
- const ScopedCredentialOptions& options);
+ Create(const CredentialCreationOptions& aOptions);
- already_AddRefed<Promise>
- GetAssertion(const ArrayBufferViewOrArrayBuffer& assertionChallenge,
- const AssertionOptions& options);
private:
- ~WebAuthentication();
-
- already_AddRefed<Promise> CreatePromise();
- nsresult GetOrigin(/*out*/ nsAString& aOrigin);
+ ~CredentialsContainer();
nsCOMPtr<nsPIDOMWindowInner> mParent;
};
} // namespace dom
} // namespace mozilla
-#endif // mozilla_dom_WebAuthentication_h
+#endif // mozilla_dom_CredentialsContainer_h
--- a/dom/credentialmanagement/moz.build
+++ b/dom/credentialmanagement/moz.build
@@ -4,15 +4,19 @@
# 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/.
with Files("**"):
BUG_COMPONENT = ("Core", "DOM: Device Interfaces")
EXPORTS.mozilla.dom += [
'Credential.h',
+ 'CredentialsContainer.h',
]
UNIFIED_SOURCES += [
'Credential.cpp',
+ 'CredentialsContainer.cpp',
]
+include('/ipc/chromium/chromium-config.mozbuild')
+
FINAL_LIBRARY = 'xul'
--- a/dom/webauthn/PWebAuthnTransaction.ipdl
+++ b/dom/webauthn/PWebAuthnTransaction.ipdl
@@ -15,21 +15,17 @@
*/
include protocol PBackground;
namespace mozilla {
namespace dom {
struct WebAuthnScopedCredentialDescriptor {
- // Converted from mozilla::dom::ScopedCredentialType enum
- uint32_t type;
uint8_t[] id;
- // Converted from mozilla::dom::WebAuthnTransport enum
- uint32_t[] transports;
};
struct WebAuthnExtension {
/* TODO Fill in with predefined extensions */
};
struct WebAuthnTransactionInfo {
uint8_t[] RpIdHash;
deleted file mode 100644
--- a/dom/webauthn/ScopedCredential.cpp
+++ /dev/null
@@ -1,66 +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/ScopedCredential.h"
-#include "mozilla/dom/WebAuthenticationBinding.h"
-
-namespace mozilla {
-namespace dom {
-
-// Only needed for refcounted objects.
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ScopedCredential, mParent)
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ScopedCredential)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ScopedCredential)
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScopedCredential)
- NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
- NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END
-
-ScopedCredential::ScopedCredential(nsPIDOMWindowInner* aParent)
- : mParent(aParent)
- , mType(ScopedCredentialType::ScopedCred)
-{}
-
-ScopedCredential::~ScopedCredential()
-{}
-
-JSObject*
-ScopedCredential::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
-{
- return ScopedCredentialBinding::Wrap(aCx, this, aGivenProto);
-}
-
-ScopedCredentialType
-ScopedCredential::Type() const
-{
- return mType;
-}
-
-void
-ScopedCredential::GetId(JSContext* aCx,
- JS::MutableHandle<JSObject*> aRetVal) const
-{
- aRetVal.set(mIdBuffer.ToUint8Array(aCx));
-}
-
-nsresult
-ScopedCredential::SetType(ScopedCredentialType aType)
-{
- mType = aType;
- return NS_OK;
-}
-
-nsresult
-ScopedCredential::SetId(CryptoBuffer& aBuffer)
-{
- if (!mIdBuffer.Assign(aBuffer)) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
- return NS_OK;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/webauthn/ScopedCredential.h
+++ /dev/null
@@ -1,66 +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_ScopedCredential_h
-#define mozilla_dom_ScopedCredential_h
-
-#include "js/TypeDecls.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/dom/BindingDeclarations.h"
-#include "mozilla/dom/CryptoBuffer.h"
-#include "mozilla/dom/WebAuthenticationBinding.h"
-#include "nsCycleCollectionParticipant.h"
-#include "nsWrapperCache.h"
-
-namespace mozilla {
-namespace dom {
-
-class ScopedCredential final : public nsISupports
- , public nsWrapperCache
-{
-public:
- NS_DECL_CYCLE_COLLECTING_ISUPPORTS
- NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ScopedCredential)
-
-public:
- explicit ScopedCredential(nsPIDOMWindowInner* aParent);
-
-protected:
- ~ScopedCredential();
-
-public:
- nsISupports*
- GetParentObject() const
- {
- return mParent;
- }
-
- virtual JSObject*
- WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
-
- ScopedCredentialType
- Type() const;
-
- void
- GetId(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal) const;
-
- nsresult
- SetType(ScopedCredentialType aType);
-
- nsresult
- SetId(CryptoBuffer& aBuffer);
-
-private:
- nsCOMPtr<nsPIDOMWindowInner> mParent;
- CryptoBuffer mIdBuffer;
- ScopedCredentialType mType;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_ScopedCredential_h
--- a/dom/webauthn/WebAuthentication.cpp
+++ b/dom/webauthn/WebAuthentication.cpp
@@ -30,27 +30,16 @@ WebAuthentication::~WebAuthentication()
JSObject*
WebAuthentication::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return WebAuthenticationBinding::Wrap(aCx, this, aGivenProto);
}
already_AddRefed<Promise>
-WebAuthentication::MakeCredential(JSContext* aCx, const Account& aAccount,
- const Sequence<ScopedCredentialParameters>& aCryptoParameters,
- const ArrayBufferViewOrArrayBuffer& aChallenge,
- const ScopedCredentialOptions& aOptions)
-{
- RefPtr<WebAuthnManager> mgr = WebAuthnManager::GetOrCreate();
- MOZ_ASSERT(mgr);
- return mgr->MakeCredential(mParent, aCx, aAccount, aCryptoParameters, aChallenge, aOptions);
-}
-
-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);
}
--- a/dom/webauthn/WebAuthentication.h
+++ b/dom/webauthn/WebAuthentication.h
@@ -38,22 +38,16 @@ public:
{
return mParent;
}
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
already_AddRefed<Promise>
- MakeCredential(JSContext* aCx, const Account& accountInformation,
- const Sequence<ScopedCredentialParameters>& cryptoParameters,
- const ArrayBufferViewOrArrayBuffer& attestationChallenge,
- const ScopedCredentialOptions& options);
-
- already_AddRefed<Promise>
GetAssertion(const ArrayBufferViewOrArrayBuffer& assertionChallenge,
const AssertionOptions& options);
private:
~WebAuthentication();
already_AddRefed<Promise> CreatePromise();
nsresult GetOrigin(/*out*/ nsAString& aOrigin);
--- a/dom/webauthn/WebAuthnManager.cpp
+++ b/dom/webauthn/WebAuthnManager.cpp
@@ -35,17 +35,17 @@ static mozilla::LazyLogModule gWebAuthnM
NS_IMPL_ISUPPORTS(WebAuthnManager, nsIIPCBackgroundChildCreateCallback);
/***********************************************************************
* Utility Functions
**********************************************************************/
template<class OOS>
static nsresult
-GetAlgorithmName(JSContext* aCx, const OOS& aAlgorithm,
+GetAlgorithmName(const OOS& aAlgorithm,
/* out */ nsString& aName)
{
MOZ_ASSERT(aAlgorithm.IsString()); // TODO: remove assertion when we coerce.
if (aAlgorithm.IsString()) {
// If string, then treat as algorithm name
aName.Assign(aAlgorithm.GetAsString());
} else {
@@ -95,20 +95,20 @@ AssembleClientData(const nsAString& aOri
MOZ_ASSERT(NS_IsMainThread());
nsString challengeBase64;
nsresult rv = aChallenge.ToJwkBase64(challengeBase64);
if (NS_WARN_IF(NS_FAILED(rv))) {
return NS_ERROR_FAILURE;
}
- WebAuthnClientData clientDataObject;
+ CollectedClientData clientDataObject;
+ clientDataObject.mChallenge.Assign(challengeBase64);
clientDataObject.mOrigin.Assign(aOrigin);
- clientDataObject.mHashAlg.SetAsString().Assign(NS_LITERAL_STRING("S256"));
- clientDataObject.mChallenge.Assign(challengeBase64);
+ clientDataObject.mHashAlg.Assign(NS_LITERAL_STRING("S256"));
nsAutoString temp;
if (NS_WARN_IF(!clientDataObject.ToJSON(temp))) {
return NS_ERROR_FAILURE;
}
aJsonOut.Assign(NS_ConvertUTF16toUTF8(temp));
return NS_OK;
@@ -210,21 +210,18 @@ WebAuthnManager::GetOrCreate()
WebAuthnManager*
WebAuthnManager::Get()
{
MOZ_ASSERT(NS_IsMainThread());
return gWebAuthnManager;
}
already_AddRefed<Promise>
-WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent, JSContext* aCx,
- const Account& aAccountInformation,
- const Sequence<ScopedCredentialParameters>& aCryptoParameters,
- const ArrayBufferViewOrArrayBuffer& aChallenge,
- const ScopedCredentialOptions& aOptions)
+WebAuthnManager::MakeCredential(nsPIDOMWindowInner* aParent,
+ const MakeCredentialOptions& aOptions)
{
MOZ_ASSERT(aParent);
MaybeClearTransaction();
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aParent);
ErrorResult rv;
@@ -240,37 +237,37 @@ WebAuthnManager::MakeCredential(nsPIDOMW
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();
+ if (aOptions.mTimeout.WasPassed()) {
+ adjustedTimeout = aOptions.mTimeout.Value();
adjustedTimeout = std::max(15.0, adjustedTimeout);
adjustedTimeout = std::min(120.0, adjustedTimeout);
}
nsCString rpId;
- if (!aOptions.mRpId.WasPassed()) {
- // If rpId is not specified, then set rpId to callerOrigin, and rpIdHash to
+ if (!aOptions.mRp.mId.WasPassed()) {
+ // If rp.id is not specified, then set rpId to callerOrigin, and rpIdHash to
// the SHA-256 hash of rpId.
rpId.Assign(NS_ConvertUTF16toUTF8(origin));
} else {
// 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.
- if (NS_FAILED(RelaxSameOrigin(aParent, aOptions.mRpId.Value(), rpId))) {
+ if (NS_FAILED(RelaxSameOrigin(aParent, aOptions.mRp.mId.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);
@@ -288,74 +285,75 @@ WebAuthnManager::MakeCredential(nsPIDOMW
srv = HashCString(hashService, rpId, rpIdHash);
if (NS_WARN_IF(NS_FAILED(srv))) {
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
// Process each element of cryptoParameters using the following steps, to
// produce a new sequence normalizedParameters.
- nsTArray<ScopedCredentialParameters> normalizedParams;
- for (size_t a = 0; a < aCryptoParameters.Length(); ++a) {
+ nsTArray<PublicKeyCredentialParameters> normalizedParams;
+ for (size_t a = 0; a < aOptions.mParameters.Length(); ++a) {
// Let current be the currently selected element of
// cryptoParameters.
- // If current.type does not contain a ScopedCredentialType
+ // If current.type does not contain a PublicKeyCredentialType
// supported by this implementation, then stop processing current and move
// on to the next element in cryptoParameters.
- if (aCryptoParameters[a].mType != ScopedCredentialType::ScopedCred) {
+ if (aOptions.mParameters[a].mType != PublicKeyCredentialType::Public_key) {
continue;
}
// Let normalizedAlgorithm be the result of normalizing an algorithm using
// the procedure defined in [WebCryptoAPI], with alg set to
// current.algorithm and op set to 'generateKey'. If an error occurs during
// this procedure, then stop processing current and move on to the next
// element in cryptoParameters.
nsString algName;
- if (NS_FAILED(GetAlgorithmName(aCx, aCryptoParameters[a].mAlgorithm,
+ if (NS_FAILED(GetAlgorithmName(aOptions.mParameters[a].mAlgorithm,
algName))) {
continue;
}
- // Add a new object of type ScopedCredentialParameters to
+ // Add a new object of type PublicKeyCredentialParameters to
// normalizedParameters, with type set to current.type and algorithm set to
// normalizedAlgorithm.
- ScopedCredentialParameters normalizedObj;
- normalizedObj.mType = aCryptoParameters[a].mType;
+ PublicKeyCredentialParameters normalizedObj;
+ normalizedObj.mType = aOptions.mParameters[a].mType;
normalizedObj.mAlgorithm.SetAsString().Assign(algName);
if (!normalizedParams.AppendElement(normalizedObj, mozilla::fallible)){
promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
return promise.forget();
}
}
// If normalizedAlgorithm is empty and cryptoParameters was not empty, cancel
// the timer started in step 2, reject promise with a DOMException whose name
// is "NotSupportedError", and terminate this algorithm.
- if (normalizedParams.IsEmpty() && !aCryptoParameters.IsEmpty()) {
+ if (normalizedParams.IsEmpty() && !aOptions.mParameters.IsEmpty()) {
promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
return promise.forget();
}
// TODO: The following check should not be here. This is checking for
// parameters specific to the soft key, and should be put in the soft key
// manager in the parent process. Still need to serialize
- // ScopedCredentialParameters first.
+ // PublicKeyCredentialParameters first.
- // Check if at least one of the specified combinations of ScopedCredentialType
- // and cryptographic parameters is supported. If not, return an error code
- // equivalent to NotSupportedError and terminate the operation.
+ // Check if at least one of the specified combinations of
+ // PublicKeyCredentialParameters and cryptographic parameters is supported. If
+ // not, return an error code equivalent to NotSupportedError and terminate the
+ // operation.
bool isValidCombination = false;
for (size_t a = 0; a < normalizedParams.Length(); ++a) {
- if (normalizedParams[a].mType == ScopedCredentialType::ScopedCred &&
+ if (normalizedParams[a].mType == PublicKeyCredentialType::Public_key &&
normalizedParams[a].mAlgorithm.IsString() &&
normalizedParams[a].mAlgorithm.GetAsString().EqualsLiteral(
WEBCRYPTO_NAMED_CURVE_P256)) {
isValidCombination = true;
break;
}
}
if (!isValidCombination) {
@@ -374,17 +372,17 @@ WebAuthnManager::MakeCredential(nsPIDOMW
// Currently no extensions are supported
//
// Use attestationChallenge, 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);
@@ -402,25 +400,19 @@ WebAuthnManager::MakeCredential(nsPIDOMW
promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR);
return promise.forget();
}
nsTArray<WebAuthnScopedCredentialDescriptor> excludeList;
if (aOptions.mExcludeList.WasPassed()) {
for (const auto& s: aOptions.mExcludeList.Value()) {
WebAuthnScopedCredentialDescriptor c;
- c.type() = static_cast<uint32_t>(s.mType);
CryptoBuffer cb;
cb.Assign(s.mId);
c.id() = cb;
- if (s.mTransports.WasPassed()) {
- for (const auto& t: s.mTransports.Value()) {
- c.transports().AppendElement(static_cast<uint32_t>(t));
- }
- }
excludeList.AppendElement(c);
}
}
// TODO: Add extension list building
nsTArray<WebAuthnExtension> extensions;
WebAuthnTransactionInfo info(rpIdHash,
@@ -571,25 +563,19 @@ WebAuthnManager::GetAssertion(nsPIDOMWin
if (!aOptions.mAllowList.WasPassed()) {
promise->MaybeReject(NS_ERROR_DOM_NOT_ALLOWED_ERR);
return promise.forget();
}
nsTArray<WebAuthnScopedCredentialDescriptor> allowList;
for (const auto& s: aOptions.mAllowList.Value()) {
WebAuthnScopedCredentialDescriptor c;
- c.type() = static_cast<uint32_t>(s.mType);
CryptoBuffer cb;
cb.Assign(s.mId);
c.id() = cb;
- if (s.mTransports.WasPassed()) {
- for (const auto& t: s.mTransports.Value()) {
- c.transports().AppendElement(static_cast<uint32_t>(t));
- }
- }
allowList.AppendElement(c);
}
// TODO: Add extension list building
// If extensions was specified, process any extensions supported by this
// 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
--- a/dom/webauthn/WebAuthnManager.h
+++ b/dom/webauthn/WebAuthnManager.h
@@ -2,19 +2,19 @@
/* 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_WebAuthnManager_h
#define mozilla_dom_WebAuthnManager_h
-#include "nsIIPCBackgroundChildCreateCallback.h"
#include "mozilla/MozPromise.h"
#include "mozilla/dom/PWebAuthnTransaction.h"
+#include "nsIIPCBackgroundChildCreateCallback.h"
/*
* Content process manager for the WebAuthn protocol. Created on calls to the
* WebAuthentication DOM object, this manager handles establishing IPC channels
* for WebAuthn transactions, as well as keeping track of JS Promise objects
* representing transactions in flight.
*
* The WebAuthn spec (https://www.w3.org/TR/webauthn/) allows for two different
@@ -68,21 +68,18 @@ public:
void
FinishGetAssertion(nsTArray<uint8_t>& aCredentialId,
nsTArray<uint8_t>& aSigBuffer);
void
Cancel(const nsresult& aError);
already_AddRefed<Promise>
- MakeCredential(nsPIDOMWindowInner* aParent, JSContext* aCx,
- const Account& aAccountInformation,
- const Sequence<ScopedCredentialParameters>& aCryptoParameters,
- const ArrayBufferViewOrArrayBuffer& aAttestationChallenge,
- const ScopedCredentialOptions& aOptions);
+ MakeCredential(nsPIDOMWindowInner* aParent,
+ const MakeCredentialOptions& aOptions);
already_AddRefed<Promise>
GetAssertion(nsPIDOMWindowInner* aParent,
const ArrayBufferViewOrArrayBuffer& aAssertionChallenge,
const AssertionOptions& aOptions);
void StartRegister();
void StartSign();
--- a/dom/webauthn/moz.build
+++ b/dom/webauthn/moz.build
@@ -12,17 +12,16 @@ IPDL_SOURCES += [
]
EXPORTS.mozilla.dom += [
'AuthenticatorAssertionResponse.h',
'AuthenticatorAttestationResponse.h',
'AuthenticatorResponse.h',
'NSSU2FTokenRemote.h',
'PublicKeyCredential.h',
- 'ScopedCredential.h',
'U2FSoftTokenManager.h',
'U2FTokenManager.h',
'U2FTokenTransport.h',
'WebAuthentication.h',
'WebAuthnManager.h',
'WebAuthnRequest.h',
'WebAuthnTransactionChild.h',
'WebAuthnTransactionParent.h',
@@ -30,17 +29,16 @@ EXPORTS.mozilla.dom += [
]
UNIFIED_SOURCES += [
'AuthenticatorAssertionResponse.cpp',
'AuthenticatorAttestationResponse.cpp',
'AuthenticatorResponse.cpp',
'NSSU2FTokenRemote.cpp',
'PublicKeyCredential.cpp',
- 'ScopedCredential.cpp',
'U2FSoftTokenManager.cpp',
'U2FTokenManager.cpp',
'WebAuthentication.cpp',
'WebAuthnManager.cpp',
'WebAuthnTransactionChild.cpp',
'WebAuthnTransactionParent.cpp',
'WebAuthnUtil.cpp'
]
--- a/dom/webauthn/tests/test_webauthn_get_assertion.html
+++ b/dom/webauthn/tests/test_webauthn_get_assertion.html
@@ -38,18 +38,20 @@
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.authentication.makeCredential, undefined, "WebAuthn makeCredential 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");
let authn = navigator.authentication;
let gAssertionChallenge = new Uint8Array(16);
window.crypto.getRandomValues(gAssertionChallenge);
let invalidCred = { type: "Magic", id: base64ToBytes("AAA=") };
let unknownCred = { type: "ScopedCred", id: base64ToBytes("AAA=") };
--- a/dom/webauthn/tests/test_webauthn_loopback.html
+++ b/dom/webauthn/tests/test_webauthn_loopback.html
@@ -21,20 +21,23 @@
// 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");
- isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential 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");
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();
@@ -98,37 +101,47 @@ function() {
})
.then(function(aSignedData) {
console.log(aPublicKey, aSignedData, signatureValue);
return verifySignature(aPublicKey, aSignedData, signatureValue);
})
}
function testMakeCredential() {
- let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
- let param = {type: "ScopedCred", algorithm: "p-256"};
-
- authn.makeCredential(acct, [param], gCredentialChallenge)
+ let rp = {id: document.origin, name: "none", icon: "none"};
+ let user = {id: "none", name: "none", icon: "none", displayName: "none"};
+ let param = {type: "public-key", algorithm: "P-256"};
+ let makeCredentialOptions = {
+ rp: rp,
+ user: user,
+ challenge: gCredentialChallenge,
+ parameters: [param]
+ };
+ credm.create({publicKey: makeCredentialOptions})
.then(checkCredentialValid)
.then(testMakeDuplicate)
.catch(function(aReason) {
ok(false, aReason);
SimpleTest.finish();
});
}
function testMakeDuplicate(aCredInfo) {
- let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
- let param = {type: "ScopedCred", algorithm: "p-256"};
- let options = {rpId: document.origin,
- excludeList: [{type: "ScopedCred",
- id: Uint8Array.from(aCredInfo.rawId),
- transports: ["usb"]}]};
-
- authn.makeCredential(acct, [param], gCredentialChallenge, options)
+ let rp = {id: document.origin, name: "none", icon: "none"};
+ let user = {id: "none", name: "none", icon: "none", displayName: "none"};
+ let param = {type: "public-key", algorithm: "P-256"};
+ let makeCredentialOptions = {
+ rp: rp,
+ user: user,
+ challenge: gCredentialChallenge,
+ parameters: [param],
+ excludeList: [{type: "public-key", id: Uint8Array.from(aCredInfo.rawId),
+ transports: ["usb"]}]
+ };
+ credm.create({publicKey: makeCredentialOptions})
.then(function() {
// We should have errored here!
ok(false, "The excludeList didn't stop a duplicate being created!");
SimpleTest.finish();
})
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), "Expect NotAllowedError, got " + aReason);
testAssertion(aCredInfo);
--- a/dom/webauthn/tests/test_webauthn_make_credential.html
+++ b/dom/webauthn/tests/test_webauthn_make_credential.html
@@ -11,186 +11,240 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Test for MakeCredential 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";
+ "use strict";
- // Execute the full-scope test
- SimpleTest.waitForExplicitFinish();
+ // Execute the full-scope test
+ SimpleTest.waitForExplicitFinish();
- function arrivingHereIsGood(aResult) {
- ok(true, "Good result! Received a: " + aResult);
- return Promise.resolve();
- }
+ function arrivingHereIsGood(aResult) {
+ ok(true, "Good result! Received a: " + aResult);
+ return Promise.resolve();
+ }
- function arrivingHereIsBad(aResult) {
- ok(false, "Bad result! Received a: " + aResult);
- return Promise.resolve();
- }
+ function arrivingHereIsBad(aResult) {
+ ok(false, "Bad result! Received a: " + aResult);
+ return Promise.resolve();
+ }
- function expectNotAllowedError(aResult) {
- ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError");
- return Promise.resolve();
- }
+ function expectNotAllowedError(aResult) {
+ ok(aResult.toString().startsWith("NotAllowedError"), "Expecting a NotAllowedError");
+ return Promise.resolve();
+ }
+
+ function expectTypeError(aResult) {
+ ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
+ return Promise.resolve();
+ }
- function expectTypeError(aResult) {
- ok(aResult.toString().startsWith("TypeError"), "Expecting a TypeError");
- return Promise.resolve();
- }
-
- function expectNotSupportedError(aResult) {
- ok(aResult.toString().startsWith("NotSupportedError"), "Expecting a NotSupportedError");
- return Promise.resolve();
- }
+ function expectNotSupportedError(aResult) {
+ 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");
- isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential API endpoint must exist");
- isnot(navigator.authentication.getAssertion, undefined, "WebAuthn getAssertion API endpoint must exist");
+ 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");
- let authn = navigator.authentication;
+ 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"};
+ let unsupportedParam = {type: "public-key", algorithm: "3DES"};
+ let badParam = {type: "SimplePassword", algorithm: "MaxLength=2"};
- let gCredentialChallenge = new Uint8Array(16);
- window.crypto.getRandomValues(gCredentialChallenge);
-
- let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
- let param = {type: "ScopedCred", algorithm: "p-256"};
- let unsupportedParam = {type: "ScopedCred", algorithm: "3DES"};
- let badParam = {type: "SimplePassword", algorithm: "MaxLength=2"};
+ var testFuncs = [
+ // Test basic good call
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
- var testFuncs = [
- // Test basic good call
- function() {
- return authn.makeCredential(acct, [param], gCredentialChallenge)
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
+ // Test empty account
+ function() {
+ let makeCredentialOptions = {
+ challenge: gCredentialChallenge, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
+
+ // Test without a parameter
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge, parameters: []
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectNotSupportedError);
+ },
- // Test empty account
- function() {
- return authn.makeCredential({}, [param], gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
-
- // Test without a parameter
- function() {
- return authn.makeCredential(acct, [], gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectNotSupportedError);
- },
+ // Test without a parameter array at all
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test without a parameter array at all
- function() {
- return authn.makeCredential(acct, null, gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
+ // Test with an unsupported parameter
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge, parameters: [unsupportedParam]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectNotSupportedError);
+ },
- // Test with an unsupported parameter
- function() {
- return authn.makeCredential(acct, [unsupportedParam], gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectNotSupportedError);
- },
+ // Test with an unsupported parameter and a good one
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge,
+ parameters: [param, unsupportedParam]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
- // Test with an unsupported parameter and a good one
- function() {
- return authn.makeCredential(acct, [unsupportedParam, param], gCredentialChallenge)
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
+ // Test with a bad parameter
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge, parameters: [badParam]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test with a bad parameter
- function() {
- return authn.makeCredential(acct, [badParam], gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
-
- // Test with an unsupported parameter, and a bad one
- function() {
- return authn.makeCredential(acct, [unsupportedParam, badParam],
- gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
+ // Test with an unsupported parameter, and a bad one
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge,
+ parameters: [unsupportedParam, badParam]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test with an unsupported parameter, a bad one, and a good one. This
- // should still fail, as anything with a badParam should fail.
- function() {
- return authn.makeCredential(acct, [unsupportedParam, badParam, param],
- gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
+ // Test with an unsupported parameter, a bad one, and a good one. This
+ // should still fail, as anything with a badParam should fail.
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge,
+ parameters: [param, unsupportedParam, badParam]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test without a challenge
- function() {
- return authn.makeCredential(acct, [param], null)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
+ // Test without a challenge
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test with an invalid challenge
- function() {
- return authn.makeCredential(acct, [param], "begone, thou ill-fitting moist glove!")
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
+ // Test with an invalid challenge
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: "begone, thou ill-fitting moist glove!",
+ parameters: [unsupportedParam]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test with duplicate parameters
- function() {
- return authn.makeCredential(acct, [param, param, param], gCredentialChallenge)
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
+ // Test with duplicate parameters
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: gCredentialChallenge,
+ parameters: [param, param, param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
- // Test an incomplete account
- function() {
- return authn.makeCredential({id: "none"
- }, [param], gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
-
- function() {
- return authn.makeCredential({name: "none", imageURL: "http://example.com/404"},
- [param], gCredentialChallenge)
- .then(arrivingHereIsBad)
- .catch(expectTypeError);
- },
+ // Test with missing rp
+ function() {
+ let makeCredentialOptions = {
+ user: user, challenge: gCredentialChallenge, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- // Test a complete account
- function() {
- return authn.makeCredential({rpDisplayName: "Foxxy", displayName: "Foxxy V",
- id: "foxes_are_the_best@example.com",
- name: "Fox F. Foxington",
- imageURL: "https://example.com/fox.svg"},
- [param], gCredentialChallenge)
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- }];
+ // Test with missing user
+ function() {
+ let makeCredentialOptions = {
+ rp: rp, challenge: gCredentialChallenge, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectTypeError);
+ },
- var i = 0;
- var runNextTest = () => {
- if (i == testFuncs.length) {
- SimpleTest.finish();
- return;
- }
- testFuncs[i]().then(() => { runNextTest(); });
- i = i + 1;
- };
- runNextTest();
- };
+ // Test a complete account
+ function() {
+ let completeRP = {id: "Foxxy RP", name: "Foxxy Name",
+ icon: "https://example.com/fox.svg"};
+ let completeUser = {id: "foxes_are_the_best@example.com",
+ name: "Fox F. Foxington",
+ icon: "https://example.com/fox.svg",
+ displayName: "Foxxy V"};
+ let makeCredentialOptions = {
+ rp: completeRP, user: completeUser, challenge: gCredentialChallenge,
+ parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ }];
+
+ 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_no_token.html
+++ b/dom/webauthn/tests/test_webauthn_no_token.html
@@ -22,52 +22,59 @@
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");
- isnot(navigator.authentication.makeCredential, undefined, "WebAuthn makeCredential 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");
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);
testMakeCredential();
function testMakeCredential() {
- let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
- let param = {type: "ScopedCred", algorithm: "p-256"};
- authn.makeCredential(acct, [param], credentialChallenge)
+ 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"};
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: credentialChallenge, parameters: [param]
+ };
+ credm.create({publicKey: makeCredentialOptions})
.then(function(aResult) {
ok(false, "Should have failed.");
testAssertion();
})
.catch(function(aReason) {
ok(aReason.toString().startsWith("NotAllowedError"), aReason);
testAssertion();
});
}
function testAssertion() {
let newCredential = {
type: "ScopedCred",
id: credentialId,
- transports: [ "usb" ],
+ transports: ["usb"],
}
let assertOptions = {rpId: document.origin, timeoutSeconds: 5,
- allowList: [ newCredential ]};
+ allowList: [newCredential]};
authn.getAssertion(assertionChallenge, assertOptions)
.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
@@ -11,176 +11,202 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<h1>Test Same Origin Policy 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";
+ "use strict";
- // Execute the full-scope test
- SimpleTest.waitForExplicitFinish();
+ // Execute the full-scope test
+ SimpleTest.waitForExplicitFinish();
- var gTrackedCredential = {};
+ var gTrackedCredential = {};
- function arrivingHereIsGood(aResult) {
- ok(true, "Good result! Received a: " + aResult);
- return Promise.resolve();
- }
+ function arrivingHereIsGood(aResult) {
+ ok(true, "Good result! Received a: " + aResult);
+ return Promise.resolve();
+ }
- function arrivingHereIsBad(aResult) {
- // TODO: Change to `ok` when Bug 1329764 lands
- todo(false, "Bad result! Received a: " + aResult);
- return Promise.resolve();
- }
+ function arrivingHereIsBad(aResult) {
+ // TODO: Change to `ok` when Bug 1329764 lands
+ todo(false, "Bad result! Received a: " + aResult);
+ return Promise.resolve();
+ }
- function expectSecurityError(aResult) {
- // TODO: Change to `ok` when Bug 1329764 lands
- todo(aResult.toString().startsWith("SecurityError"), "Expecting a SecurityError");
- return Promise.resolve();
- }
+ 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",
- id: Uint8Array.from(aPublicKeyCredential.rawId),
- transports: [ "usb" ],
- }
- return Promise.resolve(aPublicKeyCredential);
- }
+ function keepThisPublicKeyCredential(aPublicKeyCredential) {
+ gTrackedCredential = {
+ type: "ScopedCred",
+ id: Uint8Array.from(aPublicKeyCredential.rawId),
+ transports: [ "usb" ],
+ }
+ return Promise.resolve(aPublicKeyCredential);
+ }
- function runTests() {
- isnot(navigator.authentication, undefined, "WebAuthn API endpoint must exist");
- isnot(navigator.authentication.makeCredential, undefined,
- "WebAuthn makeCredential API endpoint must exist");
- isnot(navigator.authentication.getAssertion, undefined,
- "WebAuthn getAssertion API endpoint must exist");
+ 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");
+
+ let authn = navigator.authentication;
+ let credm = navigator.credentials;
- let authn = navigator.authentication;
+ let chall = new Uint8Array(16);
+ window.crypto.getRandomValues(chall);
- let chall = new Uint8Array(16);
- window.crypto.getRandomValues(chall);
-
- let acct = {rpDisplayName: "none", displayName: "none", id: "none"};
- let param = {type: "ScopedCred", algorithm: "p-256"};
+ let user = {id: "none", name: "none", icon: "none", displayName: "none"};
+ let param = {type: "public-key", algorithm: "p-256"};
- var testFuncs = [
- function() {
- // Test basic good call
- return authn.makeCredential(acct, [param], chall, {rpId: document.origin})
- .then(keepThisPublicKeyCredential)
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
+ var testFuncs = [
+ function() {
+ // Test basic good call
+ let rp = {id: document.origin};
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: chall, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(keepThisPublicKeyCredential)
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
- function() {
- // Test rpId being unset
- return authn.makeCredential(acct, [param], chall, {})
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
- function() {
- // Test this origin with optional fields
- return authn.makeCredential(acct, [param], chall,
- {rpId: "user:pass@" + document.origin + ":8888"})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function() {
- // Test blank rpId
- return authn.makeCredential(acct, [param], chall, {rpId: ""})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function() {
- // Test subdomain of this origin
- return authn.makeCredential(acct, [param], chall,
- {rpId: "subdomain." + document.origin})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function() {
- // Test another origin
- return authn.makeCredential(acct, [param], chall, {rpId: "example.com"})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function () {
- // est a different domain within the same TLD
- return authn.makeCredential(acct, [param], chall, {rpId: "alt.test"})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function () {
- // Test basic good call
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
- rpId: document.origin})
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
- function () {
- // Test rpId being unset
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ]})
- .then(arrivingHereIsGood)
- .catch(arrivingHereIsBad);
- },
- function () {
- // Test this origin with optional fields
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
- rpId: "user:pass@" + document.origin + ":8888"})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function () {
- // Test blank rpId
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
- rpId: ""})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function () {
- // Test subdomain of this origin
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
- rpId: "subdomain." + document.origin})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function () {
- // Test another origin
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
- rpId: "example.com"})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError);
- },
- function () {
- // Test a different domain within the same TLD
- return authn.getAssertion(chall, {allowList: [ gTrackedCredential ],
- rpId: "alt.test"})
- .then(arrivingHereIsBad)
- .catch(expectSecurityError)
- },
- function () {
- SimpleTest.finish();
- }
- ];
- var i = 0;
- var runNextTest = () => {
- if (i == testFuncs.length) {
- SimpleTest.finish();
- return;
- }
- console.log(i);
- testFuncs[i]().then(() => { runNextTest(); });
- i = i + 1;
- };
- runNextTest();
- };
- SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
- ["security.webauth.webauthn_enable_softtoken", true],
- ["security.webauth.webauthn_enable_usbtoken", false]]},
- runTests);
+ function() {
+ // Test rp.id being unset
+ let makeCredentialOptions = {
+ rp: {}, user: user, challenge: chall, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
+ function() {
+ // Test this origin with optional fields
+ let rp = {id: "user:pass@" + document.origin + ":8888"};
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: chall, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function() {
+ // Test blank rp.id
+ let rp = {id: ""};
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: chall, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function() {
+ // Test subdomain of this origin
+ let rp = {id: "subdomain." + document.origin};
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: chall, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function() {
+ // Test another origin
+ let rp = {id: "example.com"};
+ let makeCredentialOptions = {
+ rp: rp, user: user, challenge: chall, parameters: [param]
+ };
+ return credm.create({publicKey: makeCredentialOptions})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function () {
+ // Test a different domain within the same TLD
+ let rp = {id: "alt.test"};
+ let makeCredentialOptions = {
+ 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})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
+ function () {
+ // Test rpId being unset
+ return authn.getAssertion(chall, {allowList: [gTrackedCredential]})
+ .then(arrivingHereIsGood)
+ .catch(arrivingHereIsBad);
+ },
+ function () {
+ // Test this origin with optional fields
+ return authn.getAssertion(chall, {allowList: [gTrackedCredential],
+ rpId: "user:pass@" + document.origin + ":8888"})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function () {
+ // Test blank rpId
+ return authn.getAssertion(chall, {allowList: [gTrackedCredential],
+ rpId: ""})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function () {
+ // Test subdomain of this origin
+ return authn.getAssertion(chall, {allowList: [gTrackedCredential],
+ rpId: "subdomain." + document.origin})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function () {
+ // Test another origin
+ return authn.getAssertion(chall, {allowList: [gTrackedCredential],
+ rpId: "example.com"})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError);
+ },
+ function () {
+ // Test a different domain within the same TLD
+ return authn.getAssertion(chall, {allowList: [gTrackedCredential],
+ rpId: "alt.test"})
+ .then(arrivingHereIsBad)
+ .catch(expectSecurityError)
+ },
+ function () {
+ SimpleTest.finish();
+ }
+ ];
+ var i = 0;
+ var runNextTest = () => {
+ if (i == testFuncs.length) {
+ SimpleTest.finish();
+ return;
+ }
+ console.log(i);
+ testFuncs[i]().then(() => { runNextTest(); });
+ i = i + 1;
+ };
+ runNextTest();
+ };
+ SpecialPowers.pushPrefEnv({"set": [["security.webauth.webauthn", true],
+ ["security.webauth.webauthn_enable_softtoken", true],
+ ["security.webauth.webauthn_enable_usbtoken", false]]},
+ runTests);
</script>
</body>
</html>
--- a/dom/webidl/CredentialManagement.webidl
+++ b/dom/webidl/CredentialManagement.webidl
@@ -7,8 +7,17 @@
* https://www.w3.org/TR/credential-management-1/
*/
[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?> create(optional CredentialCreationOptions options);
+};
+
+dictionary CredentialCreationOptions {
+ MakeCredentialOptions publicKey;
+};
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -368,8 +368,13 @@ partial interface Navigator {
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
@@ -22,73 +22,97 @@ interface AuthenticatorResponse {
readonly attribute ArrayBuffer clientDataJSON;
};
[SecureContext, Pref="security.webauth.webauthn"]
interface AuthenticatorAttestationResponse : AuthenticatorResponse {
readonly attribute ArrayBuffer attestationObject;
};
-dictionary Account {
- required DOMString rpDisplayName;
- required DOMString displayName;
- required DOMString id;
- DOMString name;
- DOMString imageURL;
+dictionary PublicKeyCredentialParameters {
+ required PublicKeyCredentialType type;
+ required WebAuthnAlgorithmID algorithm; // NOTE: changed from AllgorithmIdentifier because typedef (object or DOMString) not serializable
+};
+
+dictionary PublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
+ DOMString displayName;
+};
+
+dictionary MakeCredentialOptions {
+ required PublicKeyCredentialEntity rp;
+ required PublicKeyCredentialUserEntity user;
+
+ required BufferSource challenge;
+ required sequence<PublicKeyCredentialParameters> parameters;
+
+ unsigned long timeout;
+ sequence<PublicKeyCredentialDescriptor> excludeList;
+ AuthenticatorSelectionCriteria authenticatorSelection;
+ // Extensions are not supported yet.
+ // AuthenticationExtensions extensions;
+};
+
+dictionary PublicKeyCredentialEntity {
+ DOMString id;
+ DOMString name;
+ USVString icon;
+};
+
+dictionary AuthenticatorSelectionCriteria {
+ Attachment attachment;
+ boolean requireResidentKey = false;
+};
+
+enum Attachment {
+ "platform",
+ "cross-platform"
+};
+
+dictionary CollectedClientData {
+ required DOMString challenge;
+ required DOMString origin;
+ required DOMString hashAlg;
+ DOMString tokenBinding;
+ // Extensions are not supported yet.
+ // AuthenticationExtensions clientExtensions;
+ // AuthenticationExtensions authenticatorExtensions;
+};
+
+enum PublicKeyCredentialType {
+ "public-key"
+};
+
+dictionary PublicKeyCredentialDescriptor {
+ required PublicKeyCredentialType type;
+ required BufferSource id;
+ sequence<WebAuthnTransport> transports;
};
typedef (boolean or DOMString) WebAuthnAlgorithmID; // Fix when upstream there's a definition of how to serialize AlgorithmIdentifier
-dictionary ScopedCredentialParameters {
- required ScopedCredentialType type;
- required WebAuthnAlgorithmID algorithm; // NOTE: changed from AllgorithmIdentifier because typedef (object or DOMString) not serializable
-};
-
-dictionary ScopedCredentialOptions {
- unsigned long timeoutSeconds;
- USVString rpId;
- sequence<ScopedCredentialDescriptor> excludeList;
- WebAuthnExtensions extensions;
-};
-
[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 {
};
-// Renamed from "ClientData" to avoid a collision with U2F
-dictionary WebAuthnClientData {
- required DOMString challenge;
- required DOMString origin;
- required WebAuthnAlgorithmID hashAlg; // NOTE: changed from AllgorithmIdentifier because typedef (object or DOMString) not serializable
- DOMString tokenBinding;
- WebAuthnExtensions extensions;
-};
-
enum ScopedCredentialType {
"ScopedCred"
};
-[SecureContext, Pref="security.webauth.webauthn"]
-interface ScopedCredential {
- readonly attribute ScopedCredentialType type;
- readonly attribute ArrayBuffer id;
-};
-
dictionary ScopedCredentialDescriptor {
required ScopedCredentialType type;
required BufferSource id;
sequence <WebAuthnTransport> transports;
};
// Renamed from "Transport" to avoid a collision with U2F
enum WebAuthnTransport {
@@ -96,20 +120,13 @@ enum WebAuthnTransport {
"nfc",
"ble"
};
/***** The Main API *****/
[SecureContext, Pref="security.webauth.webauthn"]
interface WebAuthentication {
- Promise<PublicKeyCredential> makeCredential (
- Account accountInformation,
- sequence<ScopedCredentialParameters> cryptoParameters,
- BufferSource attestationChallenge,
- optional ScopedCredentialOptions options
- );
-
Promise<PublicKeyCredential> getAssertion (
BufferSource assertionChallenge,
optional AssertionOptions options
);
};