1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #import <AuthenticationServices/AuthenticationServices.h>
9 #include "MacOSWebAuthnService.h"
11 #include "CFTypeRefPtr.h"
12 #include "WebAuthnAutoFillEntry.h"
13 #include "WebAuthnEnumStrings.h"
14 #include "WebAuthnResult.h"
15 #include "WebAuthnTransportIdentifiers.h"
16 #include "mozilla/Maybe.h"
17 #include "mozilla/StaticPrefs_security.h"
18 #include "mozilla/dom/CanonicalBrowsingContext.h"
19 #include "nsCocoaUtils.h"
20 #include "nsIWebAuthnPromise.h"
21 #include "nsThreadUtils.h"
23 // The documentation for the platform APIs used here can be found at:
24 // https://developer.apple.com/documentation/authenticationservices/public-private_key_authentication/supporting_passkeys
27 static mozilla::LazyLogModule gMacOSWebAuthnServiceLog("macoswebauthnservice");
30 namespace mozilla::dom {
31 class API_AVAILABLE(macos(13.3)) MacOSWebAuthnService;
32 } // namespace mozilla::dom
34 // The following ASC* declarations are from the private framework
35 // AuthenticationServicesCore. The full definitions can be found in WebKit's
36 // source at Source/WebKit/Platform/spi/Cocoa/AuthenticationServicesCoreSPI.h.
37 // Overriding ASAuthorizationController's _requestContextWithRequests is
38 // currently the only way to provide the right information to the macOS
39 // WebAuthn API (namely, the clientDataHash for requests made to physical
42 NS_ASSUME_NONNULL_BEGIN
44 @class ASCPublicKeyCredentialDescriptor;
45 @interface ASCPublicKeyCredentialDescriptor : NSObject <NSSecureCoding>
46 - (instancetype)initWithCredentialID:(NSData*)credentialID
48 (nullable NSArray<NSString*>*)allowedTransports;
51 @protocol ASCPublicKeyCredentialCreationOptions
52 @property(nonatomic, copy) NSData* clientDataHash;
53 @property(nonatomic, nullable, copy) NSData* challenge;
54 @property(nonatomic, copy)
55 NSArray<ASCPublicKeyCredentialDescriptor*>* excludedCredentials;
58 @protocol ASCPublicKeyCredentialAssertionOptions <NSCopying>
59 @property(nonatomic, copy) NSData* clientDataHash;
62 @protocol ASCCredentialRequestContext
63 @property(nonatomic, nullable, copy) id<ASCPublicKeyCredentialCreationOptions>
64 platformKeyCredentialCreationOptions;
65 @property(nonatomic, nullable, copy) id<ASCPublicKeyCredentialCreationOptions>
66 securityKeyCredentialCreationOptions;
67 @property(nonatomic, nullable, copy) id<ASCPublicKeyCredentialAssertionOptions>
68 platformKeyCredentialAssertionOptions;
69 @property(nonatomic, nullable, copy) id<ASCPublicKeyCredentialAssertionOptions>
70 securityKeyCredentialAssertionOptions;
73 @interface ASAuthorizationController (Secrets)
74 - (id<ASCCredentialRequestContext>)
75 _requestContextWithRequests:(NSArray<ASAuthorizationRequest*>*)requests
76 error:(NSError**)outError;
79 NSArray<NSString*>* TransportsByteToTransportsArray(const uint8_t aTransports)
80 API_AVAILABLE(macos(13.3)) {
81 NSMutableArray<NSString*>* transportsNS = [[NSMutableArray alloc] init];
82 if ((aTransports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) ==
83 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_USB) {
86 ASAuthorizationSecurityKeyPublicKeyCredentialDescriptorTransportUSB];
88 if ((aTransports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) ==
89 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_NFC) {
92 ASAuthorizationSecurityKeyPublicKeyCredentialDescriptorTransportNFC];
94 if ((aTransports & MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) ==
95 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_BLE) {
98 ASAuthorizationSecurityKeyPublicKeyCredentialDescriptorTransportBluetooth];
100 // TODO (bug 1859367): the platform doesn't have a definition for "internal"
101 // transport. When it does, this code should be updated to handle it.
105 NSArray* CredentialListsToCredentialDescriptorArray(
106 const nsTArray<nsTArray<uint8_t>>& aCredentialList,
107 const nsTArray<uint8_t>& aCredentialListTransports,
108 const Class credentialDescriptorClass) API_AVAILABLE(macos(13.3)) {
109 MOZ_ASSERT(aCredentialList.Length() == aCredentialListTransports.Length());
110 NSMutableArray* credentials = [[NSMutableArray alloc] init];
111 for (size_t i = 0; i < aCredentialList.Length(); i++) {
112 const nsTArray<uint8_t>& credentialId = aCredentialList[i];
113 const uint8_t& credentialTransports = aCredentialListTransports[i];
114 NSData* credentialIdNS = [NSData dataWithBytes:credentialId.Elements()
115 length:credentialId.Length()];
116 NSArray<NSString*>* credentialTransportsNS =
117 TransportsByteToTransportsArray(credentialTransports);
118 NSObject* credential = [[credentialDescriptorClass alloc]
119 initWithCredentialID:credentialIdNS
120 transports:credentialTransportsNS];
121 [credentials addObject:credential];
126 // MacOSAuthorizationController is an ASAuthorizationController that overrides
127 // _requestContextWithRequests so that the implementation can set some options
128 // that aren't directly settable using the public API.
129 API_AVAILABLE(macos(13.3))
130 @interface MacOSAuthorizationController : ASAuthorizationController
133 @implementation MacOSAuthorizationController {
134 nsTArray<uint8_t> mClientDataHash;
135 nsTArray<nsTArray<uint8_t>> mCredentialList;
136 nsTArray<uint8_t> mCredentialListTransports;
139 - (void)setRegistrationOptions:
140 (id<ASCPublicKeyCredentialCreationOptions>)registrationOptions {
141 registrationOptions.clientDataHash =
142 [NSData dataWithBytes:mClientDataHash.Elements()
143 length:mClientDataHash.Length()];
144 // Unset challenge so that the implementation uses clientDataHash (the API
145 // returns an error otherwise).
146 registrationOptions.challenge = nil;
147 const Class publicKeyCredentialDescriptorClass =
148 NSClassFromString(@"ASCPublicKeyCredentialDescriptor");
149 NSArray<ASCPublicKeyCredentialDescriptor*>* excludedCredentials =
150 CredentialListsToCredentialDescriptorArray(
151 mCredentialList, mCredentialListTransports,
152 publicKeyCredentialDescriptorClass);
153 if ([excludedCredentials count] > 0) {
154 registrationOptions.excludedCredentials = excludedCredentials;
158 - (void)stashClientDataHash:(nsTArray<uint8_t>&&)clientDataHash
159 andCredentialList:(nsTArray<nsTArray<uint8_t>>&&)credentialList
160 andCredentialListTransports:(nsTArray<uint8_t>&&)credentialListTransports {
161 mClientDataHash = std::move(clientDataHash);
162 mCredentialList = std::move(credentialList);
163 mCredentialListTransports = std::move(credentialListTransports);
166 - (id<ASCCredentialRequestContext>)
167 _requestContextWithRequests:(NSArray<ASAuthorizationRequest*>*)requests
168 error:(NSError**)outError {
169 id<ASCCredentialRequestContext> context =
170 [super _requestContextWithRequests:requests error:outError];
172 if (context.platformKeyCredentialCreationOptions) {
173 [self setRegistrationOptions:context.platformKeyCredentialCreationOptions];
175 if (context.securityKeyCredentialCreationOptions) {
176 [self setRegistrationOptions:context.securityKeyCredentialCreationOptions];
179 if (context.platformKeyCredentialAssertionOptions) {
180 id<ASCPublicKeyCredentialAssertionOptions> assertionOptions =
181 context.platformKeyCredentialAssertionOptions;
182 assertionOptions.clientDataHash =
183 [NSData dataWithBytes:mClientDataHash.Elements()
184 length:mClientDataHash.Length()];
185 context.platformKeyCredentialAssertionOptions =
186 [assertionOptions copyWithZone:nil];
188 if (context.securityKeyCredentialAssertionOptions) {
189 id<ASCPublicKeyCredentialAssertionOptions> assertionOptions =
190 context.securityKeyCredentialAssertionOptions;
191 assertionOptions.clientDataHash =
192 [NSData dataWithBytes:mClientDataHash.Elements()
193 length:mClientDataHash.Length()];
194 context.securityKeyCredentialAssertionOptions =
195 [assertionOptions copyWithZone:nil];
202 // MacOSAuthenticatorRequestDelegate is an ASAuthorizationControllerDelegate,
203 // which can be set as an ASAuthorizationController's delegate to be called
204 // back when a request for a platform authenticator attestation or assertion
205 // response completes either with an attestation or assertion
206 // (didCompleteWithAuthorization) or with an error (didCompleteWithError).
207 API_AVAILABLE(macos(13.3))
208 @interface MacOSAuthenticatorRequestDelegate
209 : NSObject <ASAuthorizationControllerDelegate>
210 - (void)setCallback:(mozilla::dom::MacOSWebAuthnService*)callback;
213 // MacOSAuthenticatorPresentationContextProvider is an
214 // ASAuthorizationControllerPresentationContextProviding, which can be set as
215 // an ASAuthorizationController's presentationContextProvider, and provides a
216 // presentation anchor for the ASAuthorizationController. Basically, this
217 // provides the API a handle to the window that made the request.
218 API_AVAILABLE(macos(13.3))
219 @interface MacOSAuthenticatorPresentationContextProvider
220 : NSObject <ASAuthorizationControllerPresentationContextProviding>
221 @property(nonatomic, strong) NSWindow* window;
224 namespace mozilla::dom {
226 #pragma clang diagnostic push
227 #pragma clang diagnostic ignored "-Wnullability-completeness"
228 class API_AVAILABLE(macos(13.3)) MacOSWebAuthnService final
229 : public nsIWebAuthnService {
231 MacOSWebAuthnService()
232 : mTransactionState(Nothing(),
233 "MacOSWebAuthnService::mTransactionState") {}
235 NS_DECL_THREADSAFE_ISUPPORTS
236 NS_DECL_NSIWEBAUTHNSERVICE
238 void FinishMakeCredential(const nsTArray<uint8_t>& aRawAttestationObject,
239 const nsTArray<uint8_t>& aCredentialId,
240 const nsTArray<nsString>& aTransports,
241 const Maybe<nsString>& aAuthenticatorAttachment);
243 void FinishGetAssertion(const nsTArray<uint8_t>& aCredentialId,
244 const nsTArray<uint8_t>& aSignature,
245 const nsTArray<uint8_t>& aAuthenticatorData,
246 const nsTArray<uint8_t>& aUserHandle,
247 const Maybe<nsString>& aAuthenticatorAttachment);
248 void ReleasePlatformResources();
249 void AbortTransaction(nsresult aError);
252 ~MacOSWebAuthnService() = default;
254 void PerformRequests(NSArray<ASAuthorizationRequest*>* aRequests,
255 nsTArray<uint8_t>&& aClientDataHash,
256 nsTArray<nsTArray<uint8_t>>&& aCredentialList,
257 nsTArray<uint8_t>&& aCredentialListTransports,
258 uint64_t aBrowsingContextId);
260 struct TransactionState {
261 uint64_t transactionId;
262 uint64_t browsingContextId;
263 Maybe<RefPtr<nsIWebAuthnSignArgs>> pendingSignArgs;
264 Maybe<RefPtr<nsIWebAuthnSignPromise>> pendingSignPromise;
265 Maybe<nsTArray<RefPtr<nsIWebAuthnAutoFillEntry>>> autoFillEntries;
268 using TransactionStateMutex = DataMutex<Maybe<TransactionState>>;
269 void DoGetAssertion(Maybe<nsTArray<uint8_t>>&& aSelectedCredentialId,
270 const TransactionStateMutex::AutoLock& aGuard);
272 TransactionStateMutex mTransactionState;
275 ASAuthorizationWebBrowserPublicKeyCredentialManager* mCredentialManager = nil;
276 nsCOMPtr<nsIWebAuthnRegisterPromise> mRegisterPromise;
277 nsCOMPtr<nsIWebAuthnSignPromise> mSignPromise;
278 MacOSAuthorizationController* mAuthorizationController = nil;
279 MacOSAuthenticatorRequestDelegate* mRequestDelegate = nil;
280 MacOSAuthenticatorPresentationContextProvider* mPresentationContextProvider =
283 #pragma clang diagnostic pop
285 } // namespace mozilla::dom
287 nsTArray<uint8_t> NSDataToArray(NSData* data) {
288 nsTArray<uint8_t> array(reinterpret_cast<const uint8_t*>(data.bytes),
293 @implementation MacOSAuthenticatorRequestDelegate {
294 RefPtr<mozilla::dom::MacOSWebAuthnService> mCallback;
297 - (void)setCallback:(mozilla::dom::MacOSWebAuthnService*)callback {
298 mCallback = callback;
301 - (void)authorizationController:(ASAuthorizationController*)controller
302 didCompleteWithAuthorization:(ASAuthorization*)authorization {
303 if ([authorization.credential
305 @protocol(ASAuthorizationPublicKeyCredentialRegistration)]) {
306 MOZ_LOG(gMacOSWebAuthnServiceLog, mozilla::LogLevel::Debug,
307 ("MacOSAuthenticatorRequestDelegate::didCompleteWithAuthorization: "
308 "got registration"));
309 id<ASAuthorizationPublicKeyCredentialRegistration> credential =
310 (id<ASAuthorizationPublicKeyCredentialRegistration>)
311 authorization.credential;
312 nsTArray<uint8_t> rawAttestationObject(
313 NSDataToArray(credential.rawAttestationObject));
314 nsTArray<uint8_t> credentialId(NSDataToArray(credential.credentialID));
315 nsTArray<nsString> transports;
316 mozilla::Maybe<nsString> authenticatorAttachment;
317 if ([credential isKindOfClass:
318 [ASAuthorizationPlatformPublicKeyCredentialRegistration
320 transports.AppendElement(u"internal"_ns);
321 #if defined(MAC_OS_VERSION_13_5) && \
322 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_13_5
323 if (__builtin_available(macos 13.5, *)) {
324 ASAuthorizationPlatformPublicKeyCredentialRegistration*
326 (ASAuthorizationPlatformPublicKeyCredentialRegistration*)
328 switch (platformCredential.attachment) {
329 case ASAuthorizationPublicKeyCredentialAttachmentCrossPlatform:
330 authenticatorAttachment.emplace(u"cross-platform"_ns);
332 case ASAuthorizationPublicKeyCredentialAttachmentPlatform:
333 authenticatorAttachment.emplace(u"platform"_ns);
341 // The platform didn't tell us what transport was used, but we know it
342 // wasn't the internal transport. The transport response is not signed by
343 // the authenticator. It represents the "transports that the authenticator
344 // is believed to support, or an empty sequence if the information is
345 // unavailable". We believe macOS supports usb, so we return usb.
346 transports.AppendElement(u"usb"_ns);
347 authenticatorAttachment.emplace(u"cross-platform"_ns);
349 mCallback->FinishMakeCredential(rawAttestationObject, credentialId,
350 transports, authenticatorAttachment);
351 } else if ([authorization.credential
353 @protocol(ASAuthorizationPublicKeyCredentialAssertion)]) {
354 MOZ_LOG(gMacOSWebAuthnServiceLog, mozilla::LogLevel::Debug,
355 ("MacOSAuthenticatorRequestDelegate::didCompleteWithAuthorization: "
357 id<ASAuthorizationPublicKeyCredentialAssertion> credential =
358 (id<ASAuthorizationPublicKeyCredentialAssertion>)
359 authorization.credential;
360 nsTArray<uint8_t> credentialId(NSDataToArray(credential.credentialID));
361 nsTArray<uint8_t> signature(NSDataToArray(credential.signature));
362 nsTArray<uint8_t> rawAuthenticatorData(
363 NSDataToArray(credential.rawAuthenticatorData));
364 nsTArray<uint8_t> userHandle(NSDataToArray(credential.userID));
365 mozilla::Maybe<nsString> authenticatorAttachment;
367 isKindOfClass:[ASAuthorizationPlatformPublicKeyCredentialAssertion
369 #if defined(MAC_OS_VERSION_13_5) && \
370 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_13_5
371 if (__builtin_available(macos 13.5, *)) {
372 ASAuthorizationPlatformPublicKeyCredentialAssertion*
374 (ASAuthorizationPlatformPublicKeyCredentialAssertion*)
376 switch (platformCredential.attachment) {
377 case ASAuthorizationPublicKeyCredentialAttachmentCrossPlatform:
378 authenticatorAttachment.emplace(u"cross-platform"_ns);
380 case ASAuthorizationPublicKeyCredentialAttachmentPlatform:
381 authenticatorAttachment.emplace(u"platform"_ns);
389 authenticatorAttachment.emplace(u"cross-platform"_ns);
391 mCallback->FinishGetAssertion(credentialId, signature, rawAuthenticatorData,
392 userHandle, authenticatorAttachment);
395 gMacOSWebAuthnServiceLog, mozilla::LogLevel::Error,
396 ("MacOSAuthenticatorRequestDelegate::didCompleteWithAuthorization: "
397 "authorization.credential is neither registration nor assertion!"));
398 MOZ_ASSERT_UNREACHABLE(
399 "should have ASAuthorizationPublicKeyCredentialRegistration or "
400 "ASAuthorizationPublicKeyCredentialAssertion");
402 mCallback->ReleasePlatformResources();
406 - (void)authorizationController:(ASAuthorizationController*)controller
407 didCompleteWithError:(NSError*)error {
408 nsAutoString errorDescription;
409 nsCocoaUtils::GetStringForNSString(error.localizedDescription,
411 nsAutoString errorDomain;
412 nsCocoaUtils::GetStringForNSString(error.domain, errorDomain);
413 MOZ_LOG(gMacOSWebAuthnServiceLog, mozilla::LogLevel::Warning,
414 ("MacOSAuthenticatorRequestDelegate::didCompleteWithError: domain "
415 "'%s' code %ld (%s)",
416 NS_ConvertUTF16toUTF8(errorDomain).get(), error.code,
417 NS_ConvertUTF16toUTF8(errorDescription).get()));
418 nsresult rv = NS_ERROR_DOM_NOT_ALLOWED_ERR;
419 // For some reason, the error for "the credential used in a registration was
420 // on the exclude list" is in the "WKErrorDomain" domain with code 8, which
421 // is presumably WKErrorDuplicateCredential.
422 const NSInteger WKErrorDuplicateCredential = 8;
423 if (errorDomain.EqualsLiteral("WKErrorDomain") &&
424 error.code == WKErrorDuplicateCredential) {
425 rv = NS_ERROR_DOM_INVALID_STATE_ERR;
426 } else if (error.domain == ASAuthorizationErrorDomain) {
427 switch (error.code) {
428 case ASAuthorizationErrorCanceled:
429 rv = NS_ERROR_DOM_ABORT_ERR;
431 case ASAuthorizationErrorFailed:
432 // The message is right, but it's not about indexeddb.
433 // See https://webidl.spec.whatwg.org/#constrainterror
434 rv = NS_ERROR_DOM_INDEXEDDB_CONSTRAINT_ERR;
436 case ASAuthorizationErrorUnknown:
437 rv = NS_ERROR_DOM_UNKNOWN_ERR;
440 // rv already has a default value
444 mCallback->AbortTransaction(rv);
449 @implementation MacOSAuthenticatorPresentationContextProvider
450 @synthesize window = window;
452 - (ASPresentationAnchor)presentationAnchorForAuthorizationController:
453 (ASAuthorizationController*)controller {
458 namespace mozilla::dom {
460 #pragma clang diagnostic push
461 #pragma clang diagnostic ignored "-Wnullability-completeness"
462 // Given a browsingContextId, attempts to determine the NSWindow associated
463 // with that browser.
464 nsresult BrowsingContextIdToNSWindow(uint64_t browsingContextId,
467 RefPtr<BrowsingContext> browsingContext(
468 BrowsingContext::Get(browsingContextId));
469 if (!browsingContext) {
470 return NS_ERROR_NOT_AVAILABLE;
472 CanonicalBrowsingContext* canonicalBrowsingContext =
473 browsingContext->Canonical();
474 if (!canonicalBrowsingContext) {
475 return NS_ERROR_NOT_AVAILABLE;
477 nsCOMPtr<nsIWidget> widget(
478 canonicalBrowsingContext->GetParentProcessWidgetContaining());
480 return NS_ERROR_NOT_AVAILABLE;
482 *window = static_cast<NSWindow*>(widget->GetNativeData(NS_NATIVE_WINDOW));
485 #pragma clang diagnostic pop
487 already_AddRefed<nsIWebAuthnService> NewMacOSWebAuthnServiceIfAvailable() {
488 MOZ_ASSERT(XRE_IsParentProcess());
489 if (!StaticPrefs::security_webauthn_enable_macos_passkeys()) {
491 gMacOSWebAuthnServiceLog, LogLevel::Debug,
492 ("macOS platform support for webauthn (passkeys) disabled by pref"));
495 // This code checks for the entitlement
496 // 'com.apple.developer.web-browser.public-key-credential', which must be
497 // true to be able to use the platform APIs.
498 CFTypeRefPtr<SecTaskRef> entitlementTask(
499 CFTypeRefPtr<SecTaskRef>::WrapUnderCreateRule(
500 SecTaskCreateFromSelf(nullptr)));
501 CFTypeRefPtr<CFBooleanRef> entitlementValue(
502 CFTypeRefPtr<CFBooleanRef>::WrapUnderCreateRule(
503 reinterpret_cast<CFBooleanRef>(SecTaskCopyValueForEntitlement(
504 entitlementTask.get(),
505 CFSTR("com.apple.developer.web-browser.public-key-credential"),
507 if (!entitlementValue || !CFBooleanGetValue(entitlementValue.get())) {
509 gMacOSWebAuthnServiceLog, LogLevel::Warning,
510 ("entitlement com.apple.developer.web-browser.public-key-credential "
511 "not present: platform passkey APIs will not be available"));
514 nsCOMPtr<nsIWebAuthnService> service(new MacOSWebAuthnService());
515 return service.forget();
518 void MacOSWebAuthnService::AbortTransaction(nsresult aError) {
519 MOZ_ASSERT(NS_IsMainThread());
520 if (mRegisterPromise) {
521 Unused << mRegisterPromise->Reject(aError);
522 mRegisterPromise = nullptr;
525 Unused << mSignPromise->Reject(aError);
526 mSignPromise = nullptr;
528 ReleasePlatformResources();
531 #pragma clang diagnostic push
532 #pragma clang diagnostic ignored "-Wnullability-completeness"
533 NS_IMPL_ISUPPORTS(MacOSWebAuthnService, nsIWebAuthnService)
534 #pragma clang diagnostic pop
537 MacOSWebAuthnService::MakeCredential(uint64_t aTransactionId,
538 uint64_t aBrowsingContextId,
539 nsIWebAuthnRegisterArgs* aArgs,
540 nsIWebAuthnRegisterPromise* aPromise) {
542 auto guard = mTransactionState.Lock();
543 *guard = Some(TransactionState{
550 NS_DispatchToMainThread(NS_NewRunnableFunction(
551 "MacOSWebAuthnService::MakeCredential",
552 [self = RefPtr{this}, browsingContextId(aBrowsingContextId),
553 aArgs = nsCOMPtr{aArgs}, aPromise = nsCOMPtr{aPromise}]() {
554 // Bug 1884574 - The Reset() call above should have cancelled any
555 // transactions that were dispatched to the platform, the platform
556 // should have called didCompleteWithError, and didCompleteWithError
557 // should have rejected the pending promise. However, in some scenarios,
558 // the platform fails to call the callback, and this leads to a
559 // diagnostic assertion failure when we drop `mRegisterPromise`. Avoid
560 // this by aborting the transaction here.
561 if (self->mRegisterPromise) {
562 MOZ_LOG(gMacOSWebAuthnServiceLog, mozilla::LogLevel::Debug,
563 ("MacOSAuthenticatorRequestDelegate::MakeCredential: "
564 "platform failed to call callback"));
565 self->AbortTransaction(NS_ERROR_DOM_ABORT_ERR);
567 self->mRegisterPromise = aPromise;
570 Unused << aArgs->GetRpId(rpId);
571 NSString* rpIdNS = nsCocoaUtils::ToNSString(rpId);
573 nsTArray<uint8_t> challenge;
574 Unused << aArgs->GetChallenge(challenge);
575 NSData* challengeNS = [NSData dataWithBytes:challenge.Elements()
576 length:challenge.Length()];
578 nsTArray<uint8_t> userId;
579 Unused << aArgs->GetUserId(userId);
580 NSData* userIdNS = [NSData dataWithBytes:userId.Elements()
581 length:userId.Length()];
583 nsAutoString userName;
584 Unused << aArgs->GetUserName(userName);
585 NSString* userNameNS = nsCocoaUtils::ToNSString(userName);
587 nsAutoString userDisplayName;
588 Unused << aArgs->GetUserName(userDisplayName);
589 NSString* userDisplayNameNS = nsCocoaUtils::ToNSString(userDisplayName);
591 nsTArray<int32_t> coseAlgs;
592 Unused << aArgs->GetCoseAlgs(coseAlgs);
593 NSMutableArray* credentialParameters = [[NSMutableArray alloc] init];
594 for (const auto& coseAlg : coseAlgs) {
595 ASAuthorizationPublicKeyCredentialParameters* credentialParameter =
596 [[ASAuthorizationPublicKeyCredentialParameters alloc]
597 initWithAlgorithm:coseAlg];
598 [credentialParameters addObject:credentialParameter];
601 nsTArray<nsTArray<uint8_t>> excludeList;
602 Unused << aArgs->GetExcludeList(excludeList);
603 nsTArray<uint8_t> excludeListTransports;
604 Unused << aArgs->GetExcludeListTransports(excludeListTransports);
605 if (excludeList.Length() != excludeListTransports.Length()) {
606 self->mRegisterPromise->Reject(NS_ERROR_INVALID_ARG);
610 Maybe<ASAuthorizationPublicKeyCredentialUserVerificationPreference>
611 userVerificationPreference = Nothing();
612 nsAutoString userVerification;
613 Unused << aArgs->GetUserVerification(userVerification);
614 // This mapping needs to be reviewed if values are added to the
615 // UserVerificationRequirement enum.
616 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
617 if (userVerification.EqualsLiteral(
618 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
619 userVerificationPreference.emplace(
620 ASAuthorizationPublicKeyCredentialUserVerificationPreferenceRequired);
621 } else if (userVerification.EqualsLiteral(
622 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
623 userVerificationPreference.emplace(
624 ASAuthorizationPublicKeyCredentialUserVerificationPreferencePreferred);
626 userVerification.EqualsLiteral(
627 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED)) {
628 userVerificationPreference.emplace(
629 ASAuthorizationPublicKeyCredentialUserVerificationPreferenceDiscouraged);
632 // The API doesn't support attestation for platform passkeys, so this is
633 // only used for security keys.
634 ASAuthorizationPublicKeyCredentialAttestationKind attestationPreference;
635 nsAutoString mozAttestationPreference;
636 Unused << aArgs->GetAttestationConveyancePreference(
637 mozAttestationPreference);
638 if (mozAttestationPreference.EqualsLiteral(
639 MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_INDIRECT)) {
640 attestationPreference =
641 ASAuthorizationPublicKeyCredentialAttestationKindIndirect;
642 } else if (mozAttestationPreference.EqualsLiteral(
643 MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_DIRECT)) {
644 attestationPreference =
645 ASAuthorizationPublicKeyCredentialAttestationKindDirect;
647 mozAttestationPreference.EqualsLiteral(
648 MOZ_WEBAUTHN_ATTESTATION_CONVEYANCE_PREFERENCE_ENTERPRISE)) {
649 attestationPreference =
650 ASAuthorizationPublicKeyCredentialAttestationKindEnterprise;
652 attestationPreference =
653 ASAuthorizationPublicKeyCredentialAttestationKindNone;
656 ASAuthorizationPublicKeyCredentialResidentKeyPreference
657 residentKeyPreference;
658 nsAutoString mozResidentKey;
659 Unused << aArgs->GetResidentKey(mozResidentKey);
660 // This mapping needs to be reviewed if values are added to the
661 // ResidentKeyRequirement enum.
662 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
663 if (mozResidentKey.EqualsLiteral(
664 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED)) {
665 residentKeyPreference =
666 ASAuthorizationPublicKeyCredentialResidentKeyPreferenceRequired;
667 } else if (mozResidentKey.EqualsLiteral(
668 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_PREFERRED)) {
669 residentKeyPreference =
670 ASAuthorizationPublicKeyCredentialResidentKeyPreferencePreferred;
672 MOZ_ASSERT(mozResidentKey.EqualsLiteral(
673 MOZ_WEBAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED));
674 residentKeyPreference =
675 ASAuthorizationPublicKeyCredentialResidentKeyPreferenceDiscouraged;
678 // Initialize the platform provider with the rpId.
679 ASAuthorizationPlatformPublicKeyCredentialProvider* platformProvider =
680 [[ASAuthorizationPlatformPublicKeyCredentialProvider alloc]
681 initWithRelyingPartyIdentifier:rpIdNS];
682 // Make a credential registration request with the challenge, userName,
684 ASAuthorizationPlatformPublicKeyCredentialRegistrationRequest*
685 platformRegistrationRequest = [platformProvider
686 createCredentialRegistrationRequestWithChallenge:challengeNS
689 [platformProvider release];
691 // The API doesn't support attestation for platform passkeys
692 platformRegistrationRequest.attestationPreference =
693 ASAuthorizationPublicKeyCredentialAttestationKindNone;
694 if (userVerificationPreference.isSome()) {
695 platformRegistrationRequest.userVerificationPreference =
696 *userVerificationPreference;
699 // Initialize the cross-platform provider with the rpId.
700 ASAuthorizationSecurityKeyPublicKeyCredentialProvider*
701 crossPlatformProvider =
702 [[ASAuthorizationSecurityKeyPublicKeyCredentialProvider alloc]
703 initWithRelyingPartyIdentifier:rpIdNS];
704 // Make a credential registration request with the challenge,
705 // userDisplayName, userName, and userId.
706 ASAuthorizationSecurityKeyPublicKeyCredentialRegistrationRequest*
707 crossPlatformRegistrationRequest = [crossPlatformProvider
708 createCredentialRegistrationRequestWithChallenge:challengeNS
713 [crossPlatformProvider release];
714 crossPlatformRegistrationRequest.attestationPreference =
715 attestationPreference;
716 crossPlatformRegistrationRequest.credentialParameters =
717 credentialParameters;
718 crossPlatformRegistrationRequest.residentKeyPreference =
719 residentKeyPreference;
720 if (userVerificationPreference.isSome()) {
721 crossPlatformRegistrationRequest.userVerificationPreference =
722 *userVerificationPreference;
724 nsTArray<uint8_t> clientDataHash;
725 nsresult rv = aArgs->GetClientDataHash(clientDataHash);
727 self->mRegisterPromise->Reject(rv);
730 nsAutoString authenticatorAttachment;
731 rv = aArgs->GetAuthenticatorAttachment(authenticatorAttachment);
732 if (NS_FAILED(rv) && rv != NS_ERROR_NOT_AVAILABLE) {
733 self->mRegisterPromise->Reject(rv);
736 NSMutableArray* requests = [[NSMutableArray alloc] init];
737 if (authenticatorAttachment.EqualsLiteral(
738 MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM)) {
739 [requests addObject:platformRegistrationRequest];
740 } else if (authenticatorAttachment.EqualsLiteral(
741 MOZ_WEBAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM)) {
742 [requests addObject:crossPlatformRegistrationRequest];
744 // Regarding the value of authenticator attachment, according to the
745 // specification, "client platforms MUST ignore unknown values,
746 // treating an unknown value as if the member does not exist".
747 [requests addObject:platformRegistrationRequest];
748 [requests addObject:crossPlatformRegistrationRequest];
750 self->PerformRequests(
751 requests, std::move(clientDataHash), std::move(excludeList),
752 std::move(excludeListTransports), browsingContextId);
757 void MacOSWebAuthnService::PerformRequests(
758 NSArray<ASAuthorizationRequest*>* aRequests,
759 nsTArray<uint8_t>&& aClientDataHash,
760 nsTArray<nsTArray<uint8_t>>&& aCredentialList,
761 nsTArray<uint8_t>&& aCredentialListTransports,
762 uint64_t aBrowsingContextId) {
763 MOZ_ASSERT(NS_IsMainThread());
764 // Create a MacOSAuthorizationController and initialize it with the requests.
765 MOZ_ASSERT(!mAuthorizationController);
766 mAuthorizationController = [[MacOSAuthorizationController alloc]
767 initWithAuthorizationRequests:aRequests];
768 [mAuthorizationController
769 stashClientDataHash:std::move(aClientDataHash)
770 andCredentialList:std::move(aCredentialList)
771 andCredentialListTransports:std::move(aCredentialListTransports)];
773 // Set up the delegate to run when the operation completes.
774 MOZ_ASSERT(!mRequestDelegate);
775 mRequestDelegate = [[MacOSAuthenticatorRequestDelegate alloc] init];
776 [mRequestDelegate setCallback:this];
777 mAuthorizationController.delegate = mRequestDelegate;
779 // Create a presentation context provider so the API knows which window
781 NSWindow* window = nullptr;
782 nsresult rv = BrowsingContextIdToNSWindow(aBrowsingContextId, &window);
784 AbortTransaction(NS_ERROR_DOM_INVALID_STATE_ERR);
787 MOZ_ASSERT(!mPresentationContextProvider);
788 mPresentationContextProvider =
789 [[MacOSAuthenticatorPresentationContextProvider alloc] init];
790 mPresentationContextProvider.window = window;
791 mAuthorizationController.presentationContextProvider =
792 mPresentationContextProvider;
794 // Finally, perform the request.
795 [mAuthorizationController performRequests];
798 void MacOSWebAuthnService::FinishMakeCredential(
799 const nsTArray<uint8_t>& aRawAttestationObject,
800 const nsTArray<uint8_t>& aCredentialId,
801 const nsTArray<nsString>& aTransports,
802 const Maybe<nsString>& aAuthenticatorAttachment) {
803 MOZ_ASSERT(NS_IsMainThread());
804 if (!mRegisterPromise) {
808 RefPtr<WebAuthnRegisterResult> result(new WebAuthnRegisterResult(
809 aRawAttestationObject, Nothing(), aCredentialId, aTransports,
810 aAuthenticatorAttachment));
811 Unused << mRegisterPromise->Resolve(result);
812 mRegisterPromise = nullptr;
816 MacOSWebAuthnService::GetAssertion(uint64_t aTransactionId,
817 uint64_t aBrowsingContextId,
818 nsIWebAuthnSignArgs* aArgs,
819 nsIWebAuthnSignPromise* aPromise) {
822 auto guard = mTransactionState.Lock();
823 *guard = Some(TransactionState{
827 Some(RefPtr{aPromise}),
831 bool conditionallyMediated;
832 Unused << aArgs->GetConditionallyMediated(&conditionallyMediated);
833 if (!conditionallyMediated) {
834 DoGetAssertion(Nothing(), guard);
838 // Using conditional mediation, so dispatch a task to collect any available
840 NS_DispatchToMainThread(NS_NewRunnableFunction(
841 "platformCredentialsForRelyingParty",
842 [self = RefPtr{this}, aTransactionId, aArgs = nsCOMPtr{aArgs}]() {
843 // This handler is called when platformCredentialsForRelyingParty
845 auto credentialsCompletionHandler = ^(
846 NSArray<ASAuthorizationWebBrowserPlatformPublicKeyCredential*>*
848 nsTArray<RefPtr<nsIWebAuthnAutoFillEntry>> autoFillEntries;
849 for (NSUInteger i = 0; i < credentials.count; i++) {
850 const auto& credential = credentials[i];
851 nsAutoString userName;
852 nsCocoaUtils::GetStringForNSString(credential.name, userName);
854 nsCocoaUtils::GetStringForNSString(credential.relyingParty, rpId);
855 autoFillEntries.AppendElement(new WebAuthnAutoFillEntry(
856 nsIWebAuthnAutoFillEntry::PROVIDER_PLATFORM_MACOS, userName,
857 rpId, NSDataToArray(credential.credentialID)));
859 auto guard = self->mTransactionState.Lock();
860 if (guard->isSome() && guard->ref().transactionId == aTransactionId) {
861 guard->ref().autoFillEntries.emplace(std::move(autoFillEntries));
864 // This handler is called when
865 // requestAuthorizationForPublicKeyCredentials completes.
866 auto authorizationHandler = ^(
867 ASAuthorizationWebBrowserPublicKeyCredentialManagerAuthorizationState
868 authorizationState) {
869 // If authorized, list any available passkeys.
870 if (authorizationState ==
871 ASAuthorizationWebBrowserPublicKeyCredentialManagerAuthorizationStateAuthorized) {
873 Unused << aArgs->GetRpId(rpId);
874 [self->mCredentialManager
875 platformCredentialsForRelyingParty:nsCocoaUtils::ToNSString(
878 credentialsCompletionHandler];
881 if (!self->mCredentialManager) {
882 self->mCredentialManager =
883 [[ASAuthorizationWebBrowserPublicKeyCredentialManager alloc]
886 // Request authorization to examine any available passkeys. This will
887 // cause a permission prompt to appear once.
888 [self->mCredentialManager
889 requestAuthorizationForPublicKeyCredentials:authorizationHandler];
895 void MacOSWebAuthnService::DoGetAssertion(
896 Maybe<nsTArray<uint8_t>>&& aSelectedCredentialId,
897 const TransactionStateMutex::AutoLock& aGuard) {
898 if (aGuard->isNothing() || aGuard->ref().pendingSignArgs.isNothing() ||
899 aGuard->ref().pendingSignPromise.isNothing()) {
903 // Take the pending Args and Promise to prevent repeated calls to
904 // DoGetAssertion for this transaction.
905 RefPtr<nsIWebAuthnSignArgs> aArgs = aGuard->ref().pendingSignArgs.extract();
906 RefPtr<nsIWebAuthnSignPromise> aPromise =
907 aGuard->ref().pendingSignPromise.extract();
908 uint64_t aBrowsingContextId = aGuard->ref().browsingContextId;
910 NS_DispatchToMainThread(NS_NewRunnableFunction(
911 "MacOSWebAuthnService::MakeCredential",
912 [self = RefPtr{this}, browsingContextId(aBrowsingContextId), aArgs,
914 aSelectedCredentialId = std::move(aSelectedCredentialId)]() mutable {
915 // Bug 1884574 - This AbortTransaction call is necessary.
916 // See comment in MacOSWebAuthnService::MakeCredential.
917 if (self->mSignPromise) {
918 MOZ_LOG(gMacOSWebAuthnServiceLog, mozilla::LogLevel::Debug,
919 ("MacOSAuthenticatorRequestDelegate::DoGetAssertion: "
920 "platform failed to call callback"));
921 self->AbortTransaction(NS_ERROR_DOM_ABORT_ERR);
923 self->mSignPromise = aPromise;
926 Unused << aArgs->GetRpId(rpId);
927 NSString* rpIdNS = nsCocoaUtils::ToNSString(rpId);
929 nsTArray<uint8_t> challenge;
930 Unused << aArgs->GetChallenge(challenge);
931 NSData* challengeNS = [NSData dataWithBytes:challenge.Elements()
932 length:challenge.Length()];
934 nsTArray<nsTArray<uint8_t>> allowList;
935 nsTArray<uint8_t> allowListTransports;
936 if (aSelectedCredentialId.isSome()) {
937 allowList.AppendElement(aSelectedCredentialId.extract());
938 allowListTransports.AppendElement(
939 MOZ_WEBAUTHN_AUTHENTICATOR_TRANSPORT_ID_INTERNAL);
941 Unused << aArgs->GetAllowList(allowList);
942 Unused << aArgs->GetAllowListTransports(allowListTransports);
944 NSMutableArray* platformAllowedCredentials =
945 [[NSMutableArray alloc] init];
946 for (const auto& allowedCredentialId : allowList) {
947 NSData* allowedCredentialIdNS =
948 [NSData dataWithBytes:allowedCredentialId.Elements()
949 length:allowedCredentialId.Length()];
950 ASAuthorizationPlatformPublicKeyCredentialDescriptor*
952 [[ASAuthorizationPlatformPublicKeyCredentialDescriptor alloc]
953 initWithCredentialID:allowedCredentialIdNS];
954 [platformAllowedCredentials addObject:allowedCredential];
956 const Class securityKeyPublicKeyCredentialDescriptorClass =
958 @"ASAuthorizationSecurityKeyPublicKeyCredentialDescriptor");
959 NSArray<ASAuthorizationSecurityKeyPublicKeyCredentialDescriptor*>*
960 crossPlatformAllowedCredentials =
961 CredentialListsToCredentialDescriptorArray(
962 allowList, allowListTransports,
963 securityKeyPublicKeyCredentialDescriptorClass);
965 Maybe<ASAuthorizationPublicKeyCredentialUserVerificationPreference>
966 userVerificationPreference = Nothing();
967 nsAutoString userVerification;
968 Unused << aArgs->GetUserVerification(userVerification);
969 // This mapping needs to be reviewed if values are added to the
970 // UserVerificationRequirement enum.
971 static_assert(MOZ_WEBAUTHN_ENUM_STRINGS_VERSION == 3);
972 if (userVerification.EqualsLiteral(
973 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED)) {
974 userVerificationPreference.emplace(
975 ASAuthorizationPublicKeyCredentialUserVerificationPreferenceRequired);
976 } else if (userVerification.EqualsLiteral(
977 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED)) {
978 userVerificationPreference.emplace(
979 ASAuthorizationPublicKeyCredentialUserVerificationPreferencePreferred);
981 userVerification.EqualsLiteral(
982 MOZ_WEBAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED)) {
983 userVerificationPreference.emplace(
984 ASAuthorizationPublicKeyCredentialUserVerificationPreferenceDiscouraged);
987 // Initialize the platform provider with the rpId.
988 ASAuthorizationPlatformPublicKeyCredentialProvider* platformProvider =
989 [[ASAuthorizationPlatformPublicKeyCredentialProvider alloc]
990 initWithRelyingPartyIdentifier:rpIdNS];
991 // Make a credential assertion request with the challenge.
992 ASAuthorizationPlatformPublicKeyCredentialAssertionRequest*
993 platformAssertionRequest = [platformProvider
994 createCredentialAssertionRequestWithChallenge:challengeNS];
995 [platformProvider release];
996 platformAssertionRequest.allowedCredentials =
997 platformAllowedCredentials;
998 if (userVerificationPreference.isSome()) {
999 platformAssertionRequest.userVerificationPreference =
1000 *userVerificationPreference;
1003 // Initialize the cross-platform provider with the rpId.
1004 ASAuthorizationSecurityKeyPublicKeyCredentialProvider*
1005 crossPlatformProvider =
1006 [[ASAuthorizationSecurityKeyPublicKeyCredentialProvider alloc]
1007 initWithRelyingPartyIdentifier:rpIdNS];
1008 // Make a credential assertion request with the challenge.
1009 ASAuthorizationSecurityKeyPublicKeyCredentialAssertionRequest*
1010 crossPlatformAssertionRequest = [crossPlatformProvider
1011 createCredentialAssertionRequestWithChallenge:challengeNS];
1012 [crossPlatformProvider release];
1013 crossPlatformAssertionRequest.allowedCredentials =
1014 crossPlatformAllowedCredentials;
1015 if (userVerificationPreference.isSome()) {
1016 crossPlatformAssertionRequest.userVerificationPreference =
1017 *userVerificationPreference;
1019 nsTArray<uint8_t> clientDataHash;
1020 nsresult rv = aArgs->GetClientDataHash(clientDataHash);
1021 if (NS_FAILED(rv)) {
1022 self->mSignPromise->Reject(rv);
1025 nsTArray<nsTArray<uint8_t>> unusedCredentialIds;
1026 nsTArray<uint8_t> unusedTransports;
1027 // allowList and allowListTransports won't actually get used.
1028 self->PerformRequests(
1029 @[ platformAssertionRequest, crossPlatformAssertionRequest ],
1030 std::move(clientDataHash), std::move(allowList),
1031 std::move(allowListTransports), browsingContextId);
1035 void MacOSWebAuthnService::FinishGetAssertion(
1036 const nsTArray<uint8_t>& aCredentialId, const nsTArray<uint8_t>& aSignature,
1037 const nsTArray<uint8_t>& aAuthenticatorData,
1038 const nsTArray<uint8_t>& aUserHandle,
1039 const Maybe<nsString>& aAuthenticatorAttachment) {
1040 MOZ_ASSERT(NS_IsMainThread());
1041 if (!mSignPromise) {
1045 RefPtr<WebAuthnSignResult> result(new WebAuthnSignResult(
1046 aAuthenticatorData, Nothing(), aCredentialId, aSignature, aUserHandle,
1047 aAuthenticatorAttachment));
1048 Unused << mSignPromise->Resolve(result);
1049 mSignPromise = nullptr;
1052 void MacOSWebAuthnService::ReleasePlatformResources() {
1053 MOZ_ASSERT(NS_IsMainThread());
1054 [mCredentialManager release];
1055 mCredentialManager = nil;
1056 [mAuthorizationController release];
1057 mAuthorizationController = nil;
1058 [mRequestDelegate release];
1059 mRequestDelegate = nil;
1060 [mPresentationContextProvider release];
1061 mPresentationContextProvider = nil;
1065 MacOSWebAuthnService::Reset() {
1066 auto guard = mTransactionState.Lock();
1067 if (guard->isSome()) {
1068 if (guard->ref().pendingSignPromise.isSome()) {
1069 // This request was never dispatched to the platform API, so
1070 // we need to reject the promise ourselves.
1071 guard->ref().pendingSignPromise.ref()->Reject(
1072 NS_ERROR_DOM_NOT_ALLOWED_ERR);
1076 NS_DispatchToMainThread(NS_NewRunnableFunction(
1077 "MacOSWebAuthnService::Cancel", [self = RefPtr{this}] {
1078 // cancel results in the delegate's didCompleteWithError method being
1079 // called, which will release all platform resources.
1080 [self->mAuthorizationController cancel];
1086 MacOSWebAuthnService::GetIsUVPAA(bool* aAvailable) {
1092 MacOSWebAuthnService::Cancel(uint64_t aTransactionId) {
1093 return NS_ERROR_NOT_IMPLEMENTED;
1097 MacOSWebAuthnService::HasPendingConditionalGet(uint64_t aBrowsingContextId,
1098 const nsAString& aOrigin,
1100 auto guard = mTransactionState.Lock();
1101 if (guard->isNothing() ||
1102 guard->ref().browsingContextId != aBrowsingContextId ||
1103 guard->ref().pendingSignArgs.isNothing()) {
1109 Unused << guard->ref().pendingSignArgs.ref()->GetOrigin(origin);
1110 if (origin != aOrigin) {
1115 *aRv = guard->ref().transactionId;
1120 MacOSWebAuthnService::GetAutoFillEntries(
1121 uint64_t aTransactionId, nsTArray<RefPtr<nsIWebAuthnAutoFillEntry>>& aRv) {
1122 auto guard = mTransactionState.Lock();
1123 if (guard->isNothing() || guard->ref().transactionId != aTransactionId ||
1124 guard->ref().pendingSignArgs.isNothing() ||
1125 guard->ref().autoFillEntries.isNothing()) {
1126 return NS_ERROR_NOT_AVAILABLE;
1128 aRv.Assign(guard->ref().autoFillEntries.ref());
1133 MacOSWebAuthnService::SelectAutoFillEntry(
1134 uint64_t aTransactionId, const nsTArray<uint8_t>& aCredentialId) {
1135 auto guard = mTransactionState.Lock();
1136 if (guard->isNothing() || guard->ref().transactionId != aTransactionId ||
1137 guard->ref().pendingSignArgs.isNothing()) {
1138 return NS_ERROR_NOT_AVAILABLE;
1141 nsTArray<nsTArray<uint8_t>> allowList;
1142 Unused << guard->ref().pendingSignArgs.ref()->GetAllowList(allowList);
1143 if (!allowList.IsEmpty() && !allowList.Contains(aCredentialId)) {
1144 return NS_ERROR_FAILURE;
1147 Maybe<nsTArray<uint8_t>> id;
1149 id.ref().Assign(aCredentialId);
1150 DoGetAssertion(std::move(id), guard);
1156 MacOSWebAuthnService::ResumeConditionalGet(uint64_t aTransactionId) {
1157 auto guard = mTransactionState.Lock();
1158 if (guard->isNothing() || guard->ref().transactionId != aTransactionId ||
1159 guard->ref().pendingSignArgs.isNothing()) {
1160 return NS_ERROR_NOT_AVAILABLE;
1162 DoGetAssertion(Nothing(), guard);
1167 MacOSWebAuthnService::PinCallback(uint64_t aTransactionId,
1168 const nsACString& aPin) {
1169 return NS_ERROR_NOT_IMPLEMENTED;
1173 MacOSWebAuthnService::SetHasAttestationConsent(uint64_t aTransactionId,
1175 return NS_ERROR_NOT_IMPLEMENTED;
1179 MacOSWebAuthnService::SelectionCallback(uint64_t aTransactionId,
1181 return NS_ERROR_NOT_IMPLEMENTED;
1185 MacOSWebAuthnService::AddVirtualAuthenticator(
1186 const nsACString& protocol, const nsACString& transport,
1187 bool hasResidentKey, bool hasUserVerification, bool isUserConsenting,
1188 bool isUserVerified, uint64_t* _retval) {
1189 return NS_ERROR_NOT_IMPLEMENTED;
1193 MacOSWebAuthnService::RemoveVirtualAuthenticator(uint64_t authenticatorId) {
1194 return NS_ERROR_NOT_IMPLEMENTED;
1198 MacOSWebAuthnService::AddCredential(uint64_t authenticatorId,
1199 const nsACString& credentialId,
1200 bool isResidentCredential,
1201 const nsACString& rpId,
1202 const nsACString& privateKey,
1203 const nsACString& userHandle,
1204 uint32_t signCount) {
1205 return NS_ERROR_NOT_IMPLEMENTED;
1209 MacOSWebAuthnService::GetCredentials(
1210 uint64_t authenticatorId,
1211 nsTArray<RefPtr<nsICredentialParameters>>& _retval) {
1212 return NS_ERROR_NOT_IMPLEMENTED;
1216 MacOSWebAuthnService::RemoveCredential(uint64_t authenticatorId,
1217 const nsACString& credentialId) {
1218 return NS_ERROR_NOT_IMPLEMENTED;
1222 MacOSWebAuthnService::RemoveAllCredentials(uint64_t authenticatorId) {
1223 return NS_ERROR_NOT_IMPLEMENTED;
1227 MacOSWebAuthnService::SetUserVerified(uint64_t authenticatorId,
1228 bool isUserVerified) {
1229 return NS_ERROR_NOT_IMPLEMENTED;
1233 MacOSWebAuthnService::Listen() { return NS_ERROR_NOT_IMPLEMENTED; }
1236 MacOSWebAuthnService::RunCommand(const nsACString& cmd) {
1237 return NS_ERROR_NOT_IMPLEMENTED;
1240 } // namespace mozilla::dom
1242 NS_ASSUME_NONNULL_END