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/. */
7 #ifndef mozilla_dom_WebAuthnManager_h
8 #define mozilla_dom_WebAuthnManager_h
10 #include "mozilla/Maybe.h"
11 #include "mozilla/MozPromise.h"
12 #include "mozilla/RandomNum.h"
13 #include "mozilla/dom/AbortSignal.h"
14 #include "mozilla/dom/PWebAuthnTransaction.h"
15 #include "mozilla/dom/WebAuthnManagerBase.h"
18 * Content process manager for the WebAuthn protocol. Created on calls to the
19 * WebAuthentication DOM object, this manager handles establishing IPC channels
20 * for WebAuthn transactions, as well as keeping track of JS Promise objects
21 * representing transactions in flight.
23 * The WebAuthn spec (https://www.w3.org/TR/webauthn/) allows for two different
24 * types of transactions: registration and signing. When either of these is
25 * requested via the DOM API, the following steps are executed in the
28 * - Validation of the request. Return a failed promise to js if request does
29 * not have correct parameters.
31 * - If request is valid, open a new IPC channel for running the transaction. If
32 * another transaction is already running in this content process, cancel it.
33 * Return a pending promise to js.
35 * - Send transaction information to parent process (by running the Start*
36 * functions of WebAuthnManager). Assuming another transaction is currently in
37 * flight in another content process, parent will handle canceling it.
39 * - On return of successful transaction information from parent process, turn
40 * information into DOM object format required by spec, and resolve promise
41 * (by running the Finish* functions of WebAuthnManager). On cancellation
42 * request from parent, reject promise with corresponding error code. Either
43 * outcome will also close the IPC channel.
47 namespace mozilla::dom
{
51 class WebAuthnTransaction
{
53 explicit WebAuthnTransaction(const RefPtr
<Promise
>& aPromise
)
54 : mPromise(aPromise
), mId(NextId()) {
58 // JS Promise representing the transaction status.
59 RefPtr
<Promise
> mPromise
;
61 // Unique transaction id.
65 // Generates a probabilistically unique ID for the new transaction. IDs are 53
66 // bits, as they are used in javascript. We use a random value if possible,
67 // otherwise a counter.
68 static uint64_t NextId() {
69 static uint64_t counter
= 0;
70 Maybe
<uint64_t> rand
= mozilla::RandomUint64();
72 rand
.valueOr(++counter
) & UINT64_C(0x1fffffffffffff); // 2^53 - 1
73 // The transaction ID 0 is reserved.
78 class WebAuthnManager final
: public WebAuthnManagerBase
, public AbortFollower
{
80 NS_DECL_ISUPPORTS_INHERITED
81 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WebAuthnManager
, WebAuthnManagerBase
)
83 explicit WebAuthnManager(nsPIDOMWindowInner
* aParent
)
84 : WebAuthnManagerBase(aParent
) {}
86 already_AddRefed
<Promise
> MakeCredential(
87 const PublicKeyCredentialCreationOptions
& aOptions
,
88 const Optional
<OwningNonNull
<AbortSignal
>>& aSignal
, ErrorResult
& aError
);
90 already_AddRefed
<Promise
> GetAssertion(
91 const PublicKeyCredentialRequestOptions
& aOptions
,
92 const bool aConditionallyMediated
,
93 const Optional
<OwningNonNull
<AbortSignal
>>& aSignal
, ErrorResult
& aError
);
95 already_AddRefed
<Promise
> Store(const Credential
& aCredential
,
98 already_AddRefed
<Promise
> IsUVPAA(GlobalObject
& aGlobal
, ErrorResult
& aError
);
100 // WebAuthnManagerBase
102 void FinishMakeCredential(
103 const uint64_t& aTransactionId
,
104 const WebAuthnMakeCredentialResult
& aResult
) override
;
106 void FinishGetAssertion(const uint64_t& aTransactionId
,
107 const WebAuthnGetAssertionResult
& aResult
) override
;
109 void RequestAborted(const uint64_t& aTransactionId
,
110 const nsresult
& aError
) override
;
114 void RunAbortAlgorithm() override
;
117 virtual ~WebAuthnManager();
119 // Send a Cancel message to the parent, reject the promise with the given
120 // reason (an nsresult or JS::Handle<JS::Value>), and clear the transaction.
121 template <typename T
>
122 void CancelTransaction(const T
& aReason
) {
124 RejectTransaction(aReason
);
127 // Reject the promise with the given reason (an nsresult or JS::Value), and
128 // clear the transaction.
129 template <typename T
>
130 void RejectTransaction(const T
& aReason
) {
131 if (!NS_WARN_IF(mTransaction
.isNothing())) {
132 mTransaction
.ref().mPromise
->MaybeReject(aReason
);
138 // Send a Cancel message to the parent.
141 // Clears all information we have about the current transaction.
142 void ClearTransaction();
144 // The current transaction, if any.
145 Maybe
<WebAuthnTransaction
> mTransaction
;
148 inline void ImplCycleCollectionTraverse(
149 nsCycleCollectionTraversalCallback
& aCallback
,
150 WebAuthnTransaction
& aTransaction
, const char* aName
, uint32_t aFlags
= 0) {
151 ImplCycleCollectionTraverse(aCallback
, aTransaction
.mPromise
, aName
, aFlags
);
154 inline void ImplCycleCollectionUnlink(WebAuthnTransaction
& aTransaction
) {
155 ImplCycleCollectionUnlink(aTransaction
.mPromise
);
158 } // namespace mozilla::dom
160 #endif // mozilla_dom_WebAuthnManager_h