WebAuthnHandler.h (5628B)
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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_WebAuthnHandler_h 8 #define mozilla_dom_WebAuthnHandler_h 9 10 #include "mozilla/Maybe.h" 11 #include "mozilla/MozPromise.h" 12 #include "mozilla/dom/AbortSignal.h" 13 #include "mozilla/dom/PWebAuthnTransaction.h" 14 #include "mozilla/dom/PWebAuthnTransactionChild.h" 15 #include "mozilla/dom/Promise.h" 16 #include "mozilla/dom/WebAuthnTransactionChild.h" 17 18 /* 19 * Content process handler for the WebAuthn protocol. Created on calls to the 20 * WebAuthentication DOM object, this is responsible for establishing IPC 21 * channels for WebAuthn transactions as well as keeping track of JS Promise 22 * objects representing transactions in flight. 23 * 24 * The WebAuthn spec (https://www.w3.org/TR/webauthn/) allows for two different 25 * types of transactions: registration and signing. When either of these is 26 * requested via the DOM API, the following steps are executed in the 27 * WebAuthnHandler: 28 * 29 * - Validation of the request. Return a failed promise to js if request does 30 * not have correct parameters. 31 * 32 * - If request is valid, open a new IPC channel for running the transaction. If 33 * another transaction is already running in this content process, cancel it. 34 * Return a pending promise to js. 35 * 36 * - Send transaction information to parent process. 37 * 38 * - On return of successful transaction information from parent process, turn 39 * information into DOM object format required by spec, and resolve promise 40 * (by running the Finish* functions of WebAuthnHandler). On cancellation 41 * request from parent, reject promise with corresponding error code. 42 * 43 */ 44 45 namespace mozilla::dom { 46 47 class Credential; 48 class PublicKeyCredential; 49 struct PublicKeyCredentialCreationOptions; 50 struct PublicKeyCredentialRequestOptions; 51 52 enum class WebAuthnTransactionType { Create, Get }; 53 54 class WebAuthnTransaction { 55 public: 56 explicit WebAuthnTransaction(const RefPtr<Promise>& aPromise, 57 WebAuthnTransactionType aType) 58 : mPromise(aPromise), mType(aType) {} 59 60 // JS Promise representing the transaction status. 61 RefPtr<Promise> mPromise; 62 63 WebAuthnTransactionType mType; 64 65 // These holders are used to track the transaction once it has been dispatched 66 // to the parent process. Once ->Track()'d, they must either be disconnected 67 // (through a call to WebAuthnHandler::CancelTransaction) or completed 68 // (through a response on the IPC channel) before this WebAuthnTransaction is 69 // destroyed. 70 MozPromiseRequestHolder<PWebAuthnTransactionChild::RequestRegisterPromise> 71 mRegisterHolder; 72 MozPromiseRequestHolder<PWebAuthnTransactionChild::RequestSignPromise> 73 mSignHolder; 74 }; 75 76 class WebAuthnHandler final : public AbortFollower { 77 public: 78 NS_DECL_CYCLE_COLLECTING_ISUPPORTS 79 NS_DECL_CYCLE_COLLECTION_CLASS(WebAuthnHandler) 80 81 explicit WebAuthnHandler(nsPIDOMWindowInner* aWindow) : mWindow(aWindow) { 82 MOZ_ASSERT(NS_IsMainThread()); 83 MOZ_ASSERT(aWindow); 84 } 85 86 already_AddRefed<Promise> MakeCredential( 87 const PublicKeyCredentialCreationOptions& aOptions, 88 const Optional<OwningNonNull<AbortSignal>>& aSignal, ErrorResult& aError); 89 90 already_AddRefed<Promise> GetAssertion( 91 const PublicKeyCredentialRequestOptions& aOptions, 92 const bool aConditionallyMediated, 93 const Optional<OwningNonNull<AbortSignal>>& aSignal, ErrorResult& aError); 94 95 already_AddRefed<Promise> Store(const Credential& aCredential, 96 ErrorResult& aError); 97 98 already_AddRefed<Promise> IsUVPAA(GlobalObject& aGlobal, ErrorResult& aError); 99 100 void ActorDestroyed(); 101 102 // AbortFollower 103 void RunAbortAlgorithm() override; 104 105 private: 106 virtual ~WebAuthnHandler(); 107 108 bool MaybeCreateActor(); 109 110 void FinishMakeCredential(const WebAuthnMakeCredentialResult& aResult); 111 112 void FinishGetAssertion(const WebAuthnGetAssertionResult& aResult); 113 114 // Send a Cancel message to the parent, reject the promise with the given 115 // reason (an nsresult or JS::Handle<JS::Value>), and clear the transaction. 116 template <typename T> 117 void CancelTransaction(const T& aReason) { 118 MOZ_ASSERT(mActor); 119 MOZ_ASSERT(mTransaction.isSome()); 120 121 mTransaction.ref().mRegisterHolder.DisconnectIfExists(); 122 mTransaction.ref().mSignHolder.DisconnectIfExists(); 123 124 mActor->SendRequestCancel(); 125 RejectTransaction(aReason); 126 } 127 128 // Resolve the promise with the given credential. 129 void ResolveTransaction(const RefPtr<PublicKeyCredential>& aCredential); 130 131 // Reject the promise with the given reason (an nsresult or JS::Value), and 132 // clear the transaction. 133 template <typename T> 134 void RejectTransaction(const T& aReason); 135 136 // The parent window. 137 nsCOMPtr<nsPIDOMWindowInner> mWindow; 138 139 // IPC Channel to the parent process. 140 RefPtr<WebAuthnTransactionChild> mActor; 141 142 // The current transaction, if any. 143 Maybe<WebAuthnTransaction> mTransaction; 144 }; 145 146 inline void ImplCycleCollectionTraverse( 147 nsCycleCollectionTraversalCallback& aCallback, 148 WebAuthnTransaction& aTransaction, const char* aName, uint32_t aFlags = 0) { 149 ImplCycleCollectionTraverse(aCallback, aTransaction.mPromise, aName, aFlags); 150 } 151 152 inline void ImplCycleCollectionUnlink(WebAuthnTransaction& aTransaction) { 153 ImplCycleCollectionUnlink(aTransaction.mPromise); 154 } 155 156 } // namespace mozilla::dom 157 158 #endif // mozilla_dom_WebAuthnHandler_h