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 "base/timer/timer.h" 20 #include "content/common/content_export.h" 21 #include "content/public/browser/authenticator_request_client_delegate.h" 22 #include "content/public/browser/web_contents_observer.h" 23 #include "device/fido/authenticator_get_assertion_response.h" 24 #include "device/fido/authenticator_make_credential_response.h" 25 #include "device/fido/authenticator_selection_criteria.h" 26 #include "device/fido/client_data.h" 27 #include "device/fido/ctap_get_assertion_request.h" 28 #include "device/fido/ctap_make_credential_request.h" 29 #include "device/fido/fido_constants.h" 30 #include "device/fido/fido_transport_protocol.h" 31 #include "device/fido/make_credential_request_handler.h" 32 #include "services/data_decoder/public/cpp/data_decoder.h" 33 #include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h" 34 #include "url/origin.h" 35 36 namespace base { 37 class OneShotTimer; 38 } 39 40 namespace device { 41 42 class FidoRequestHandlerBase; 43 class FidoDiscoveryFactory; 44 45 enum class FidoReturnCode : uint8_t; 46 47 enum class GetAssertionStatus; 48 enum class MakeCredentialStatus; 49 50 } // namespace device 51 52 namespace url { 53 class Origin; 54 } 55 56 namespace content { 57 58 class BrowserContext; 59 class RenderFrameHost; 60 class WebAuthRequestSecurityChecker; 61 62 namespace client_data { 63 // These enumerate the possible values for the `type` member of 64 // CollectedClientData. See 65 // https://w3c.github.io/webauthn/#dom-collectedclientdata-type 66 CONTENT_EXPORT extern const char kCreateType[]; 67 CONTENT_EXPORT extern const char kGetType[]; 68 } // namespace client_data 69 70 enum class RequestExtension; 71 72 // Common code for any WebAuthn Authenticator interfaces. 73 class CONTENT_EXPORT AuthenticatorCommon { 74 public: 75 explicit AuthenticatorCommon(RenderFrameHost* render_frame_host); 76 virtual ~AuthenticatorCommon(); 77 78 // This is not-quite an implementation of blink::mojom::Authenticator. The 79 // first two functions take the caller's origin explicitly. This allows the 80 // caller origin to be overridden if needed. 81 void MakeCredential( 82 url::Origin caller_origin, 83 blink::mojom::PublicKeyCredentialCreationOptionsPtr options, 84 blink::mojom::Authenticator::MakeCredentialCallback callback); 85 void GetAssertion(url::Origin caller_origin, 86 blink::mojom::PublicKeyCredentialRequestOptionsPtr options, 87 blink::mojom::Authenticator::GetAssertionCallback callback); 88 void IsUserVerifyingPlatformAuthenticatorAvailable( 89 blink::mojom::Authenticator:: 90 IsUserVerifyingPlatformAuthenticatorAvailableCallback callback); 91 void Cancel(); 92 93 void Cleanup(); 94 95 void DisableUI(); 96 97 protected: 98 virtual std::unique_ptr<AuthenticatorRequestClientDelegate> 99 CreateRequestDelegate(); 100 101 std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_; 102 103 private: 104 friend class AuthenticatorImplTest; 105 106 // Enumerates whether or not to check that the WebContents has focus. 107 enum class Focus { 108 kDoCheck, 109 kDontCheck, 110 }; 111 112 // Replaces the current |request_| with a |MakeCredentialRequestHandler|, 113 // effectively restarting the request. 114 void StartMakeCredentialRequest(bool allow_skipping_pin_touch); 115 116 // Replaces the current |request_| with a |GetAssertionRequestHandler|, 117 // effectively restarting the request. 118 void StartGetAssertionRequest(bool allow_skipping_pin_touch); 119 120 bool IsFocused() const; 121 122 // Callback to handle the large blob being compressed before attempting to 123 // start a request. 124 void OnLargeBlobCompressed( 125 data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result); 126 127 // Callback to handle the large blob being uncompressed before completing a 128 // request. 129 void OnLargeBlobUncompressed( 130 device::AuthenticatorGetAssertionResponse response, 131 data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result); 132 133 // Callback to handle the async response from a U2fDevice. 134 void OnRegisterResponse( 135 device::MakeCredentialStatus status_code, 136 base::Optional<device::AuthenticatorMakeCredentialResponse> response_data, 137 const device::FidoAuthenticator* authenticator); 138 139 // Callback to complete the registration process once a decision about 140 // whether or not to return attestation data has been made. 141 void OnRegisterResponseAttestationDecided( 142 device::AuthenticatorMakeCredentialResponse response_data, 143 bool is_transport_used_internal, 144 bool attestation_permitted); 145 146 // Callback to handle the async response from a U2fDevice. 147 void OnSignResponse( 148 device::GetAssertionStatus status_code, 149 base::Optional<std::vector<device::AuthenticatorGetAssertionResponse>> 150 response_data, 151 const device::FidoAuthenticator* authenticator); 152 153 // Runs when timer expires and cancels all issued requests to a U2fDevice. 154 void OnTimeout(); 155 // Cancels the currently pending request (if any) with the supplied status. 156 void CancelWithStatus(blink::mojom::AuthenticatorStatus status); 157 // Runs when the user cancels WebAuthN request via UI dialog. 158 void OnCancelFromUI(); 159 160 // Called when a GetAssertion has completed, either because an allow_list was 161 // used and so an answer is returned directly, or because the user selected an 162 // account from the options. 163 void OnAccountSelected(device::AuthenticatorGetAssertionResponse response); 164 165 // Signals to the request delegate that the request has failed for |reason|. 166 // The request delegate decides whether to present the user with a visual 167 // error before the request is finally resolved with |status|. 168 void SignalFailureToRequestDelegate( 169 const device::FidoAuthenticator* authenticator, 170 AuthenticatorRequestClientDelegate::InterestingFailureReason reason, 171 blink::mojom::AuthenticatorStatus status); 172 173 void InvokeCallbackAndCleanup( 174 blink::mojom::Authenticator::MakeCredentialCallback callback, 175 blink::mojom::AuthenticatorStatus status, 176 blink::mojom::MakeCredentialAuthenticatorResponsePtr response = nullptr, 177 Focus focus_check = Focus::kDontCheck); 178 void InvokeCallbackAndCleanup( 179 blink::mojom::Authenticator::GetAssertionCallback callback, 180 blink::mojom::AuthenticatorStatus status, 181 blink::mojom::GetAssertionAuthenticatorResponsePtr response = nullptr); 182 183 BrowserContext* browser_context() const; 184 185 // Returns the FidoDiscoveryFactory for the current request. This may be a 186 // real instance, or one injected by the Virtual Authenticator environment, or 187 // a unit testing fake. InitDiscoveryFactory() must be called before this 188 // accessor. It gets reset at the end of each request by Cleanup(). 189 device::FidoDiscoveryFactory* discovery_factory(); 190 void InitDiscoveryFactory(); 191 192 RenderFrameHost* const render_frame_host_; 193 std::unique_ptr<device::FidoRequestHandlerBase> request_; 194 std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_; 195 device::FidoDiscoveryFactory* discovery_factory_testing_override_ = nullptr; 196 blink::mojom::Authenticator::MakeCredentialCallback 197 make_credential_response_callback_; 198 blink::mojom::Authenticator::GetAssertionCallback 199 get_assertion_response_callback_; 200 std::string client_data_json_; 201 // empty_allow_list_ is true iff a GetAssertion is currently pending and the 202 // request did not list any credential IDs in the allow list. 203 bool empty_allow_list_ = false; 204 bool disable_ui_ = false; 205 url::Origin caller_origin_; 206 std::string relying_party_id_; 207 scoped_refptr<WebAuthRequestSecurityChecker> security_checker_; 208 std::unique_ptr<base::OneShotTimer> timer_ = 209 std::make_unique<base::OneShotTimer>(); 210 base::Optional<std::string> app_id_; 211 base::Optional<device::CtapMakeCredentialRequest> 212 ctap_make_credential_request_; 213 base::Optional<device::MakeCredentialRequestHandler::Options> 214 make_credential_options_; 215 base::Optional<device::CtapGetAssertionRequest> ctap_get_assertion_request_; 216 base::Optional<device::CtapGetAssertionOptions> ctap_get_assertion_options_; 217 // awaiting_attestation_response_ is true if the embedder has been queried 218 // about an attestsation decision and the response is still pending. 219 bool awaiting_attestation_response_ = false; 220 blink::mojom::AuthenticatorStatus error_awaiting_user_acknowledgement_ = 221 blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR; 222 data_decoder::DataDecoder data_decoder_; 223 224 base::flat_set<RequestExtension> requested_extensions_; 225 226 base::WeakPtrFactory<AuthenticatorCommon> weak_factory_{this}; 227 228 DISALLOW_COPY_AND_ASSIGN(AuthenticatorCommon); 229 }; 230 231 } // namespace content 232 233 #endif // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_ 234