1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "mozilla/Services.h"
6 #include "mozilla/StaticPrefs_security.h"
7 #include "nsIObserverService.h"
8 #include "nsThreadUtils.h"
9 #include "WebAuthnService.h"
10 #include "WebAuthnTransportIdentifiers.h"
12 namespace mozilla::dom
{
14 already_AddRefed
<nsIWebAuthnService
> NewWebAuthnService() {
15 nsCOMPtr
<nsIWebAuthnService
> webauthnService(new WebAuthnService());
16 return webauthnService
.forget();
19 NS_IMPL_ISUPPORTS(WebAuthnService
, nsIWebAuthnService
)
22 WebAuthnService::MakeCredential(uint64_t aTransactionId
,
23 uint64_t browsingContextId
,
24 nsIWebAuthnRegisterArgs
* aArgs
,
25 nsIWebAuthnRegisterPromise
* aPromise
) {
26 auto guard
= mTransactionState
.Lock();
27 if (guard
->isSome()) {
28 guard
->ref().service
->Reset();
31 *guard
= Some(TransactionState
{DefaultService()});
32 return guard
->ref().service
->MakeCredential(aTransactionId
, browsingContextId
,
37 WebAuthnService::GetAssertion(uint64_t aTransactionId
,
38 uint64_t browsingContextId
,
39 nsIWebAuthnSignArgs
* aArgs
,
40 nsIWebAuthnSignPromise
* aPromise
) {
41 auto guard
= mTransactionState
.Lock();
42 if (guard
->isSome()) {
43 guard
->ref().service
->Reset();
46 *guard
= Some(TransactionState
{DefaultService()});
49 #if defined(XP_MACOSX)
50 // The macOS security key API doesn't handle the AppID extension. So we'll
51 // use authenticator-rs if it's likely that the request requires AppID. We
52 // consider it likely if 1) the AppID extension is present, 2) the allow list
53 // is non-empty, and 3) none of the allowed credentials use the
54 // "internal" or "hybrid" transport.
56 rv
= aArgs
->GetAppId(appId
);
57 if (rv
== NS_OK
) { // AppID is set
58 uint8_t transportSet
= 0;
59 nsTArray
<uint8_t> allowListTransports
;
60 Unused
<< aArgs
->GetAllowListTransports(allowListTransports
);
61 for (const uint8_t& transport
: allowListTransports
) {
62 transportSet
|= transport
;
64 uint8_t passkeyTransportMask
=
65 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL
|
66 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_HYBRID
;
67 if (allowListTransports
.Length() > 0 &&
68 (transportSet
& passkeyTransportMask
) == 0) {
69 guard
->ref().service
= AuthrsService();
74 rv
= guard
->ref().service
->GetAssertion(aTransactionId
, browsingContextId
,
80 // If this is a conditionally mediated request, notify observers that there
81 // is a pending transaction. This is mainly useful in tests.
82 bool conditionallyMediated
;
83 Unused
<< aArgs
->GetConditionallyMediated(&conditionallyMediated
);
84 if (conditionallyMediated
) {
85 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(__func__
, []() {
86 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
88 os
->NotifyObservers(nullptr, "webauthn:conditional-get-pending",
92 NS_DispatchToMainThread(runnable
.forget());
99 WebAuthnService::GetIsUVPAA(bool* aAvailable
) {
100 return DefaultService()->GetIsUVPAA(aAvailable
);
104 WebAuthnService::HasPendingConditionalGet(uint64_t aBrowsingContextId
,
105 const nsAString
& aOrigin
,
107 return SelectedService()->HasPendingConditionalGet(aBrowsingContextId
,
112 WebAuthnService::GetAutoFillEntries(
113 uint64_t aTransactionId
, nsTArray
<RefPtr
<nsIWebAuthnAutoFillEntry
>>& aRv
) {
114 return SelectedService()->GetAutoFillEntries(aTransactionId
, aRv
);
118 WebAuthnService::SelectAutoFillEntry(uint64_t aTransactionId
,
119 const nsTArray
<uint8_t>& aCredentialId
) {
120 return SelectedService()->SelectAutoFillEntry(aTransactionId
, aCredentialId
);
124 WebAuthnService::ResumeConditionalGet(uint64_t aTransactionId
) {
125 return SelectedService()->ResumeConditionalGet(aTransactionId
);
129 WebAuthnService::Reset() {
130 auto guard
= mTransactionState
.Lock();
131 if (guard
->isSome()) {
132 guard
->ref().service
->Reset();
139 WebAuthnService::Cancel(uint64_t aTransactionId
) {
140 return SelectedService()->Cancel(aTransactionId
);
144 WebAuthnService::PinCallback(uint64_t aTransactionId
, const nsACString
& aPin
) {
145 return SelectedService()->PinCallback(aTransactionId
, aPin
);
149 WebAuthnService::ResumeMakeCredential(uint64_t aTransactionId
,
150 bool aForceNoneAttestation
) {
151 return SelectedService()->ResumeMakeCredential(aTransactionId
,
152 aForceNoneAttestation
);
156 WebAuthnService::SelectionCallback(uint64_t aTransactionId
, uint64_t aIndex
) {
157 return SelectedService()->SelectionCallback(aTransactionId
, aIndex
);
161 WebAuthnService::AddVirtualAuthenticator(
162 const nsACString
& protocol
, const nsACString
& transport
,
163 bool hasResidentKey
, bool hasUserVerification
, bool isUserConsenting
,
164 bool isUserVerified
, uint64_t* retval
) {
165 return SelectedService()->AddVirtualAuthenticator(
166 protocol
, transport
, hasResidentKey
, hasUserVerification
,
167 isUserConsenting
, isUserVerified
, retval
);
171 WebAuthnService::RemoveVirtualAuthenticator(uint64_t authenticatorId
) {
172 return SelectedService()->RemoveVirtualAuthenticator(authenticatorId
);
176 WebAuthnService::AddCredential(uint64_t authenticatorId
,
177 const nsACString
& credentialId
,
178 bool isResidentCredential
,
179 const nsACString
& rpId
,
180 const nsACString
& privateKey
,
181 const nsACString
& userHandle
,
182 uint32_t signCount
) {
183 return SelectedService()->AddCredential(authenticatorId
, credentialId
,
184 isResidentCredential
, rpId
,
185 privateKey
, userHandle
, signCount
);
189 WebAuthnService::GetCredentials(
190 uint64_t authenticatorId
,
191 nsTArray
<RefPtr
<nsICredentialParameters
>>& retval
) {
192 return SelectedService()->GetCredentials(authenticatorId
, retval
);
196 WebAuthnService::RemoveCredential(uint64_t authenticatorId
,
197 const nsACString
& credentialId
) {
198 return SelectedService()->RemoveCredential(authenticatorId
, credentialId
);
202 WebAuthnService::RemoveAllCredentials(uint64_t authenticatorId
) {
203 return SelectedService()->RemoveAllCredentials(authenticatorId
);
207 WebAuthnService::SetUserVerified(uint64_t authenticatorId
,
208 bool isUserVerified
) {
209 return SelectedService()->SetUserVerified(authenticatorId
, isUserVerified
);
213 WebAuthnService::Listen() { return SelectedService()->Listen(); }
216 WebAuthnService::RunCommand(const nsACString
& cmd
) {
217 return SelectedService()->RunCommand(cmd
);
220 } // namespace mozilla::dom