1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
6 #define CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
7 
8 #include <stdint.h>
9 
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include "base/containers/flat_set.h"
16 #include "base/containers/span.h"
17 #include "base/macros.h"
18 #include "base/optional.h"
19 #include "content/common/content_export.h"
20 #include "content/public/browser/authenticator_request_client_delegate.h"
21 #include "content/public/browser/web_contents_observer.h"
22 #include "device/fido/authenticator_get_assertion_response.h"
23 #include "device/fido/authenticator_make_credential_response.h"
24 #include "device/fido/authenticator_selection_criteria.h"
25 #include "device/fido/client_data.h"
26 #include "device/fido/ctap_get_assertion_request.h"
27 #include "device/fido/ctap_make_credential_request.h"
28 #include "device/fido/fido_constants.h"
29 #include "device/fido/fido_transport_protocol.h"
30 #include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
31 #include "url/origin.h"
32 
33 namespace base {
34 class OneShotTimer;
35 }
36 
37 namespace device {
38 
39 class FidoRequestHandlerBase;
40 
41 enum class FidoReturnCode : uint8_t;
42 
43 enum class GetAssertionStatus;
44 enum class MakeCredentialStatus;
45 
46 }  // namespace device
47 
48 namespace url {
49 class Origin;
50 }
51 
52 namespace content {
53 
54 class BrowserContext;
55 class RenderFrameHost;
56 class WebAuthRequestSecurityChecker;
57 
58 namespace client_data {
59 // These enumerate the possible values for the `type` member of
60 // CollectedClientData. See
61 // https://w3c.github.io/webauthn/#dom-collectedclientdata-type
62 CONTENT_EXPORT extern const char kCreateType[];
63 CONTENT_EXPORT extern const char kGetType[];
64 }  // namespace client_data
65 
66 // Common code for any WebAuthn Authenticator interfaces.
67 class CONTENT_EXPORT AuthenticatorCommon {
68  public:
69   // Permits setting timer for testing.
70   AuthenticatorCommon(RenderFrameHost* render_frame_host,
71                       std::unique_ptr<base::OneShotTimer>);
72   virtual ~AuthenticatorCommon();
73 
74   // This is not-quite an implementation of blink::mojom::Authenticator. The
75   // first two functions take the caller's origin explicitly. This allows the
76   // caller origin to be overridden if needed.
77   void MakeCredential(
78       url::Origin caller_origin,
79       blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
80       blink::mojom::Authenticator::MakeCredentialCallback callback);
81   void GetAssertion(url::Origin caller_origin,
82                     blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
83                     blink::mojom::Authenticator::GetAssertionCallback callback);
84   void IsUserVerifyingPlatformAuthenticatorAvailable(
85       blink::mojom::Authenticator::
86           IsUserVerifyingPlatformAuthenticatorAvailableCallback callback);
87   void Cancel();
88 
89   void Cleanup();
90 
91   void DisableUI();
92 
93  protected:
94   virtual std::unique_ptr<AuthenticatorRequestClientDelegate>
95   CreateRequestDelegate();
96 
97   std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
98 
99  private:
100   friend class AuthenticatorImplTest;
101 
102   // Enumerates whether or not to check that the WebContents has focus.
103   enum class Focus {
104     kDoCheck,
105     kDontCheck,
106   };
107 
108   // Replaces the current |request_| with a |MakeCredentialRequestHandler|,
109   // effectively restarting the request.
110   void StartMakeCredentialRequest(bool allow_skipping_pin_touch);
111 
112   // Replaces the current |request_| with a |GetAssertionRequestHandler|,
113   // effectively restarting the request.
114   void StartGetAssertionRequest(bool allow_skipping_pin_touch);
115 
116   bool IsFocused() const;
117 
118   // Callback to handle the async response from a U2fDevice.
119   void OnRegisterResponse(
120       device::MakeCredentialStatus status_code,
121       base::Optional<device::AuthenticatorMakeCredentialResponse> response_data,
122       const device::FidoAuthenticator* authenticator);
123 
124   // Callback to complete the registration process once a decision about
125   // whether or not to return attestation data has been made.
126   void OnRegisterResponseAttestationDecided(
127       device::AuthenticatorMakeCredentialResponse response_data,
128       bool is_transport_used_internal,
129       bool attestation_permitted);
130 
131   // Callback to handle the async response from a U2fDevice.
132   void OnSignResponse(
133       device::GetAssertionStatus status_code,
134       base::Optional<std::vector<device::AuthenticatorGetAssertionResponse>>
135           response_data,
136       const device::FidoAuthenticator* authenticator);
137 
138   // Runs when timer expires and cancels all issued requests to a U2fDevice.
139   void OnTimeout();
140   // Cancels the currently pending request (if any) with the supplied status.
141   void CancelWithStatus(blink::mojom::AuthenticatorStatus status);
142   // Runs when the user cancels WebAuthN request via UI dialog.
143   void OnCancelFromUI();
144 
145   // Called when a GetAssertion has completed, either because an allow_list was
146   // used and so an answer is returned directly, or because the user selected an
147   // account from the options.
148   void OnAccountSelected(device::AuthenticatorGetAssertionResponse response);
149 
150   // Signals to the request delegate that the request has failed for |reason|.
151   // The request delegate decides whether to present the user with a visual
152   // error before the request is finally resolved with |status|.
153   void SignalFailureToRequestDelegate(
154       const device::FidoAuthenticator* authenticator,
155       AuthenticatorRequestClientDelegate::InterestingFailureReason reason,
156       blink::mojom::AuthenticatorStatus status);
157 
158   void InvokeCallbackAndCleanup(
159       blink::mojom::Authenticator::MakeCredentialCallback callback,
160       blink::mojom::AuthenticatorStatus status,
161       blink::mojom::MakeCredentialAuthenticatorResponsePtr response = nullptr,
162       Focus focus_check = Focus::kDontCheck);
163   void InvokeCallbackAndCleanup(
164       blink::mojom::Authenticator::GetAssertionCallback callback,
165       blink::mojom::AuthenticatorStatus status,
166       blink::mojom::GetAssertionAuthenticatorResponsePtr response = nullptr);
167 
168   BrowserContext* browser_context() const;
169 
170   RenderFrameHost* const render_frame_host_;
171   std::unique_ptr<device::FidoRequestHandlerBase> request_;
172   blink::mojom::Authenticator::MakeCredentialCallback
173       make_credential_response_callback_;
174   blink::mojom::Authenticator::GetAssertionCallback
175       get_assertion_response_callback_;
176   std::string client_data_json_;
177   bool attestation_requested_;
178   // empty_allow_list_ is true iff a GetAssertion is currently pending and the
179   // request did not list any credential IDs in the allow list.
180   bool empty_allow_list_ = false;
181   bool disable_ui_ = false;
182   url::Origin caller_origin_;
183   std::string relying_party_id_;
184   scoped_refptr<WebAuthRequestSecurityChecker> security_checker_;
185   std::unique_ptr<base::OneShotTimer> timer_;
186   base::Optional<device::AuthenticatorSelectionCriteria>
187       authenticator_selection_criteria_;
188   base::Optional<std::string> app_id_;
189   base::Optional<device::CtapMakeCredentialRequest>
190       ctap_make_credential_request_;
191   base::Optional<device::CtapGetAssertionRequest> ctap_get_assertion_request_;
192   // awaiting_attestation_response_ is true if the embedder has been queried
193   // about an attestsation decision and the response is still pending.
194   bool awaiting_attestation_response_ = false;
195   blink::mojom::AuthenticatorStatus error_awaiting_user_acknowledgement_ =
196       blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
197 
198   base::WeakPtrFactory<AuthenticatorCommon> weak_factory_{this};
199 
200   DISALLOW_COPY_AND_ASSIGN(AuthenticatorCommon);
201 };
202 
203 }  // namespace content
204 
205 #endif  // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
206