mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-14 10:43:24 +00:00
bug 1332681 - part 2/4 - authentication.getAssertion: return a PublicKeyCredential instead of a WebAuthnAssertion r=jcj,qdot
MozReview-Commit-ID: 72p9lvhQISe --HG-- rename : dom/webauthn/WebAuthnAssertion.cpp => dom/webauthn/AuthenticatorAssertionResponse.cpp rename : dom/webauthn/WebAuthnAssertion.h => dom/webauthn/AuthenticatorAssertionResponse.h extra : rebase_source : f5e77b0a71556764b58ba7822a5716bee5c47d99
This commit is contained in:
parent
07f967118b
commit
0ecb59e4a9
66
dom/webauthn/AuthenticatorAssertionResponse.cpp
Normal file
66
dom/webauthn/AuthenticatorAssertionResponse.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- 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/WebAuthenticationBinding.h"
|
||||
#include "mozilla/dom/AuthenticatorAssertionResponse.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(AuthenticatorAssertionResponse, AuthenticatorResponse)
|
||||
NS_IMPL_RELEASE_INHERITED(AuthenticatorAssertionResponse, AuthenticatorResponse)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AuthenticatorAssertionResponse)
|
||||
NS_INTERFACE_MAP_END_INHERITING(AuthenticatorResponse)
|
||||
|
||||
AuthenticatorAssertionResponse::AuthenticatorAssertionResponse(nsPIDOMWindowInner* aParent)
|
||||
: AuthenticatorResponse(aParent)
|
||||
{}
|
||||
|
||||
AuthenticatorAssertionResponse::~AuthenticatorAssertionResponse()
|
||||
{}
|
||||
|
||||
JSObject*
|
||||
AuthenticatorAssertionResponse::WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AuthenticatorAssertionResponseBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
AuthenticatorAssertionResponse::GetAuthenticatorData(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetVal) const
|
||||
{
|
||||
aRetVal.set(mAuthenticatorData.ToUint8Array(aCx));
|
||||
}
|
||||
|
||||
nsresult
|
||||
AuthenticatorAssertionResponse::SetAuthenticatorData(CryptoBuffer& aBuffer)
|
||||
{
|
||||
if (NS_WARN_IF(!mAuthenticatorData.Assign(aBuffer))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AuthenticatorAssertionResponse::GetSignature(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetVal) const
|
||||
{
|
||||
aRetVal.set(mSignature.ToUint8Array(aCx));
|
||||
}
|
||||
|
||||
nsresult
|
||||
AuthenticatorAssertionResponse::SetSignature(CryptoBuffer& aBuffer)
|
||||
{
|
||||
if (NS_WARN_IF(!mSignature.Assign(aBuffer))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
56
dom/webauthn/AuthenticatorAssertionResponse.h
Normal file
56
dom/webauthn/AuthenticatorAssertionResponse.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* -*- 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_AuthenticatorAssertionResponse_h
|
||||
#define mozilla_dom_AuthenticatorAssertionResponse_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/AuthenticatorResponse.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/CryptoBuffer.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AuthenticatorAssertionResponse final : public AuthenticatorResponse
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
explicit AuthenticatorAssertionResponse(nsPIDOMWindowInner* aParent);
|
||||
|
||||
protected:
|
||||
~AuthenticatorAssertionResponse() override;
|
||||
|
||||
public:
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void
|
||||
GetAuthenticatorData(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal) const;
|
||||
|
||||
nsresult
|
||||
SetAuthenticatorData(CryptoBuffer& aBuffer);
|
||||
|
||||
void
|
||||
GetSignature(JSContext* aCx, JS::MutableHandle<JSObject*> aRetVal) const;
|
||||
|
||||
nsresult
|
||||
SetSignature(CryptoBuffer& aBuffer);
|
||||
|
||||
private:
|
||||
CryptoBuffer mAuthenticatorData;
|
||||
CryptoBuffer mSignature;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_AuthenticatorAssertionResponse_h
|
@ -1,98 +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/WebAuthenticationBinding.h"
|
||||
#include "mozilla/dom/WebAuthnAssertion.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Only needed for refcounted objects.
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebAuthnAssertion, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(WebAuthnAssertion)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(WebAuthnAssertion)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebAuthnAssertion)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
WebAuthnAssertion::WebAuthnAssertion(nsPIDOMWindowInner* aParent)
|
||||
: mParent(aParent)
|
||||
{}
|
||||
|
||||
WebAuthnAssertion::~WebAuthnAssertion()
|
||||
{}
|
||||
|
||||
JSObject*
|
||||
WebAuthnAssertion::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return WebAuthnAssertionBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
already_AddRefed<ScopedCredential>
|
||||
WebAuthnAssertion::Credential() const
|
||||
{
|
||||
RefPtr<ScopedCredential> temp(mCredential);
|
||||
return temp.forget();
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnAssertion::GetClientData(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetVal) const
|
||||
{
|
||||
aRetVal.set(mClientData.ToUint8Array(aCx));
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnAssertion::GetAuthenticatorData(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetVal) const
|
||||
{
|
||||
aRetVal.set(mAuthenticatorData.ToUint8Array(aCx));
|
||||
}
|
||||
|
||||
void
|
||||
WebAuthnAssertion::GetSignature(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aRetVal) const
|
||||
{
|
||||
aRetVal.set(mSignature.ToUint8Array(aCx));
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebAuthnAssertion::SetCredential(RefPtr<ScopedCredential> aCredential)
|
||||
{
|
||||
mCredential = aCredential;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebAuthnAssertion::SetClientData(CryptoBuffer& aBuffer)
|
||||
{
|
||||
if (!mClientData.Assign(aBuffer)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebAuthnAssertion::SetAuthenticatorData(CryptoBuffer& aBuffer)
|
||||
{
|
||||
if (!mAuthenticatorData.Assign(aBuffer)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
WebAuthnAssertion::SetSignature(CryptoBuffer& aBuffer)
|
||||
{
|
||||
if (!mSignature.Assign(aBuffer)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -1,86 +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_WebAuthnAssertion_h
|
||||
#define mozilla_dom_WebAuthnAssertion_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ScopedCredential;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class WebAuthnAssertion final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebAuthnAssertion)
|
||||
|
||||
public:
|
||||
explicit WebAuthnAssertion(nsPIDOMWindowInner* aParent);
|
||||
|
||||
protected:
|
||||
~WebAuthnAssertion();
|
||||
|
||||
public:
|
||||
nsPIDOMWindowInner*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
already_AddRefed<ScopedCredential>
|
||||
Credential() const;
|
||||
|
||||
void
|
||||
GetClientData(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal) const;
|
||||
|
||||
void
|
||||
GetAuthenticatorData(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal) const;
|
||||
|
||||
void
|
||||
GetSignature(JSContext* cx, JS::MutableHandle<JSObject*> aRetVal) const;
|
||||
|
||||
nsresult
|
||||
SetCredential(RefPtr<ScopedCredential> aCredential);
|
||||
|
||||
nsresult
|
||||
SetClientData(CryptoBuffer& aBuffer);
|
||||
|
||||
nsresult
|
||||
SetAuthenticatorData(CryptoBuffer& aBuffer);
|
||||
|
||||
nsresult
|
||||
SetSignature(CryptoBuffer& aBuffer);
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsPIDOMWindowInner> mParent;
|
||||
RefPtr<ScopedCredential> mCredential;
|
||||
CryptoBuffer mAuthenticatorData;
|
||||
CryptoBuffer mClientData;
|
||||
CryptoBuffer mSignature;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_WebAuthnAssertion_h
|
@ -732,21 +732,21 @@ WebAuthnManager::FinishGetAssertion(nsTArray<uint8_t>& aCredentialId,
|
||||
|
||||
// If any authenticator returns success:
|
||||
|
||||
// Create a new WebAuthnAssertion object named value and populate its fields
|
||||
// Create a new PublicKeyCredential object named value and populate its fields
|
||||
// with the values returned from the authenticator as well as the
|
||||
// clientDataJSON computed earlier.
|
||||
|
||||
RefPtr<ScopedCredential> credential = new ScopedCredential(mCurrentParent);
|
||||
credential->SetType(ScopedCredentialType::ScopedCred);
|
||||
credential->SetId(credentialBuf);
|
||||
|
||||
RefPtr<WebAuthnAssertion> assertion = new WebAuthnAssertion(mCurrentParent);
|
||||
assertion->SetCredential(credential);
|
||||
assertion->SetClientData(clientDataBuf);
|
||||
RefPtr<AuthenticatorAssertionResponse> assertion =
|
||||
new AuthenticatorAssertionResponse(mCurrentParent);
|
||||
assertion->SetClientDataJSON(clientDataBuf);
|
||||
assertion->SetAuthenticatorData(authenticatorDataBuf);
|
||||
assertion->SetSignature(signatureData);
|
||||
|
||||
mTransactionPromise->MaybeResolve(assertion);
|
||||
RefPtr<PublicKeyCredential> credential =
|
||||
new PublicKeyCredential(mCurrentParent);
|
||||
credential->SetRawId(credentialBuf);
|
||||
credential->SetResponse(assertion);
|
||||
|
||||
mTransactionPromise->MaybeResolve(credential);
|
||||
MaybeClearTransaction();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ IPDL_SOURCES += [
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'AuthenticatorAssertionResponse.h',
|
||||
'AuthenticatorAttestationResponse.h',
|
||||
'AuthenticatorResponse.h',
|
||||
'NSSU2FTokenRemote.h',
|
||||
@ -21,7 +22,6 @@ EXPORTS.mozilla.dom += [
|
||||
'U2FTokenManager.h',
|
||||
'U2FTokenTransport.h',
|
||||
'WebAuthentication.h',
|
||||
'WebAuthnAssertion.h',
|
||||
'WebAuthnManager.h',
|
||||
'WebAuthnRequest.h',
|
||||
'WebAuthnTransactionChild.h',
|
||||
@ -30,6 +30,7 @@ EXPORTS.mozilla.dom += [
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'AuthenticatorAssertionResponse.cpp',
|
||||
'AuthenticatorAttestationResponse.cpp',
|
||||
'AuthenticatorResponse.cpp',
|
||||
'NSSU2FTokenRemote.cpp',
|
||||
@ -38,7 +39,6 @@ UNIFIED_SOURCES += [
|
||||
'U2FSoftTokenManager.cpp',
|
||||
'U2FTokenManager.cpp',
|
||||
'WebAuthentication.cpp',
|
||||
'WebAuthnAssertion.cpp',
|
||||
'WebAuthnManager.cpp',
|
||||
'WebAuthnTransactionChild.cpp',
|
||||
'WebAuthnTransactionParent.cpp',
|
||||
|
@ -63,37 +63,36 @@ function() {
|
||||
}
|
||||
|
||||
function checkAssertionAndSigValid(aPublicKey, aAssertion) {
|
||||
/* WebAuthnAssertion
|
||||
- Credential
|
||||
-- ID: ID of Credential from AllowList that succeeded
|
||||
-- Type: "ScopedCred"
|
||||
- ClientData: serialized JSON
|
||||
- AuthenticatorData: RP ID Hash || U2F Sign() Response
|
||||
- Signature: U2F Sign() Response */
|
||||
/* PublicKeyCredential : Credential
|
||||
- rawId: ID of Credential from AllowList that succeeded
|
||||
- response : AuthenticatorAssertionResponse : AuthenticatorResponse
|
||||
- clientDataJSON: serialized JSON
|
||||
- authenticatorData: RP ID Hash || U2F Sign() Response
|
||||
- signature: U2F Sign() Response
|
||||
*/
|
||||
|
||||
is(aAssertion.credential.type, "ScopedCred", "Type is correct");
|
||||
ok(aAssertion.credential.id.length > 0, "Key ID exists");
|
||||
ok(aAssertion.rawId.length > 0, "Key ID exists");
|
||||
|
||||
ok(aAssertion.authenticatorData.length > 0, "Authenticator data exists");
|
||||
let clientData = JSON.parse(buffer2string(aAssertion.clientData));
|
||||
ok(aAssertion.response.authenticatorData.length > 0, "Authenticator data exists");
|
||||
let clientData = JSON.parse(buffer2string(aAssertion.response.clientDataJSON));
|
||||
is(clientData.challenge, bytesToBase64UrlSafe(gAssertionChallenge), "Challenge is correct");
|
||||
is(clientData.origin, window.location.origin, "Origin is correct");
|
||||
is(clientData.hashAlg, "S256", "Hash algorithm is correct");
|
||||
|
||||
// Parse the signature data
|
||||
if (aAssertion.signature[0] != 0x01) {
|
||||
if (aAssertion.response.signature[0] != 0x01) {
|
||||
throw "User presence byte not set";
|
||||
}
|
||||
let presenceAndCounter = aAssertion.signature.slice(0,5);
|
||||
let signatureValue = aAssertion.signature.slice(5);
|
||||
let presenceAndCounter = aAssertion.response.signature.slice(0,5);
|
||||
let signatureValue = aAssertion.response.signature.slice(5);
|
||||
|
||||
let rpIdHash = aAssertion.authenticatorData.slice(0,32);
|
||||
let rpIdHash = aAssertion.response.authenticatorData.slice(0,32);
|
||||
|
||||
// Assemble the signed data and verify the signature
|
||||
return deriveAppAndChallengeParam(clientData.origin, aAssertion.clientData)
|
||||
return deriveAppAndChallengeParam(clientData.origin, aAssertion.response.clientDataJSON)
|
||||
.then(function(aParams) {
|
||||
console.log(aParams.appParam, rpIdHash, presenceAndCounter, aParams.challengeParam);
|
||||
console.log("ClientData buffer: ", hexEncode(aAssertion.clientData));
|
||||
console.log("ClientData buffer: ", hexEncode(aAssertion.response.clientDataJSON));
|
||||
console.log("ClientDataHash: ", hexEncode(aParams.challengeParam));
|
||||
return assembleSignedData(aParams.appParam, presenceAndCounter, aParams.challengeParam);
|
||||
})
|
||||
|
@ -50,9 +50,7 @@ dictionary ScopedCredentialOptions {
|
||||
};
|
||||
|
||||
[SecureContext, Pref="security.webauth.webauthn"]
|
||||
interface WebAuthnAssertion {
|
||||
readonly attribute ScopedCredential credential;
|
||||
readonly attribute ArrayBuffer clientData;
|
||||
interface AuthenticatorAssertionResponse : AuthenticatorResponse {
|
||||
readonly attribute ArrayBuffer authenticatorData;
|
||||
readonly attribute ArrayBuffer signature;
|
||||
};
|
||||
@ -110,7 +108,7 @@ interface WebAuthentication {
|
||||
optional ScopedCredentialOptions options
|
||||
);
|
||||
|
||||
Promise<WebAuthnAssertion> getAssertion (
|
||||
Promise<PublicKeyCredential> getAssertion (
|
||||
BufferSource assertionChallenge,
|
||||
optional AssertionOptions options
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user