|
| 1 | +<!-- USAGE |
| 2 | + * Fill in each of the sections (like Background) below |
| 3 | + * Wrap code with `single line of code` or ```code block``` |
| 4 | + * Before submitting, delete all <!-- TEMPLATE marked comments in this file, |
| 5 | + and the following quote banner: |
| 6 | +--> |
| 7 | +> See comments in Markdown for how to use this spec template |
| 8 | +
|
| 9 | +<!-- TEMPLATE |
| 10 | + The purpose of this spec is to describe a new WebView2 feature and its APIs. |
| 11 | +
|
| 12 | + There are two audiences for the spec. The first are people |
| 13 | + that want to evaluate and give feedback on the API, as part of |
| 14 | + the submission process. When it's complete |
| 15 | + it will be incorporated into the public documentation at |
| 16 | + docs.microsoft.com (https://docs.microsoft.com/en-us/microsoft-edge/webview2/). |
| 17 | + Hopefully we'll be able to copy it mostly verbatim. |
| 18 | + So the second audience is everyone that reads there to learn how |
| 19 | + and why to use this API. |
| 20 | +--> |
| 21 | + |
| 22 | + |
| 23 | +# Background |
| 24 | +By default HTTP basic authentication requests inside WebView2 show the authentication UI, which is a dialog prompt in which the user can type in user name and password credentials just like in the Edge browser. We have been requested by WebView2 app developers to provide finer granularity for managing HTTP Basic authentications inside WebView2, including the ability to hide the login UI and provide credentials. |
| 25 | + |
| 26 | + |
| 27 | +# Description |
| 28 | +We propose a new event for WebView2, CoreWebView2WebAuthenticationRequested that will allow developers to listen on and override the HTTP Basic authentication requests in WebView2. When there is a HTTP Basic authentication request in WebView2, the developer will have a choice to: |
| 29 | + 1) Provide credentials |
| 30 | + 2) Cancel the login altogether |
| 31 | + 3) Ask the user for credentials via the default login prompt |
| 32 | +We also propose CoreWebView2StagingWebAuthenticationResponse, the runtime class that represents the app's response with credentials to the basic authentication request. |
| 33 | + |
| 34 | +# Examples |
| 35 | +## Basic usage |
| 36 | +CoreWebView2WebAuthenticationRequestedEvent follows the same event handling pattern as any other WebView2 event. |
| 37 | + |
| 38 | +To add event handler: |
| 39 | +```cpp |
| 40 | +webviewStaging2->add_WebAuthenticationRequested( |
| 41 | + Callback<ICoreWebView2StagingWebAuthenticationRequestedEventHandler>( |
| 42 | + [this]( |
| 43 | + ICoreWebView2Staging2* sender, |
| 44 | + ICoreWebView2StagingWebAuthenticationRequestedEventArgs* args) { |
| 45 | + // Handler code |
| 46 | + return S_OK; |
| 47 | + }) |
| 48 | + .Get(), |
| 49 | + &m_webAuthenticationRequestedToken)); |
| 50 | +``` |
| 51 | +
|
| 52 | +```c# |
| 53 | +public OnWebAuthenticationRequested(object sender, CoreWebView2WebAuthenticationRequestedEventArgs args) |
| 54 | +{ |
| 55 | + // Handler code |
| 56 | +}; |
| 57 | +webView.CoreWebView2.WebAuthenticationRequested += OnWebAuthenticationRequested; |
| 58 | +``` |
| 59 | + |
| 60 | +To remove event handler: |
| 61 | +```cpp |
| 62 | +webViewStaging2->remove_WebAuthenticationRequested(m_webAuthenticationRequestedToken); |
| 63 | +``` |
| 64 | +
|
| 65 | +```c# |
| 66 | +webView.CoreWebView2.WebAuthenticationRequested -= OnWebAuthenticationRequested; |
| 67 | +``` |
| 68 | + |
| 69 | +## Provide credentials |
| 70 | +The developer can provide the authentication credentials on behalf of the user when it encounters the Basic authentication request. In this case, the login dialog prompt will no longer be shown to the user. If the developer provided credentials are wrong, the server may keep responding with Unauthorized, which will lead to an infinite loop so the developer should pay attention to this. |
| 71 | + |
| 72 | +```cpp |
| 73 | + webviewStaging2->add_WebAuthenticationRequested( |
| 74 | + Callback<ICoreWebView2StagingWebAuthenticationRequestedEventHandler>( |
| 75 | + [this]( |
| 76 | + ICoreWebView2Staging2* sender, |
| 77 | + ICoreWebView2StagingWebAuthenticationRequestedEventArgs* args) { |
| 78 | + wil::com_ptr<ICoreWebView2StagingEnvironment> webviewEnvironmentStaging; |
| 79 | + m_appWindow->GetWebViewEnvironment()->QueryInterface( |
| 80 | + IID_PPV_ARGS(&webviewEnvironmentStaging)); |
| 81 | + wil::com_ptr<ICoreWebView2StagingWebAuthenticationResponse> webAuthenticationResponse; |
| 82 | + webviewEnvironmentStaging->CreateWebAuthenticationResponse( |
| 83 | + L"userName", L"password" , &webAuthenticationResponse); |
| 84 | + args->put_Response(webAuthenticationResponse.get()); |
| 85 | + |
| 86 | + return S_OK; |
| 87 | + }) |
| 88 | + .Get(), |
| 89 | + &m_webAuthenticationRequestedToken)); |
| 90 | +``` |
| 91 | +
|
| 92 | +```c# |
| 93 | +webView.CoreWebView2.WebAuthenticationRequested += delegate (object sender, CoreWebView2WebAuthenticationRequestedEventArgs args) |
| 94 | +{ |
| 95 | + CoreWebView2WebAuthenticationResponse response = _coreWebView2Environment.CreateWebAuthenticationResponse( |
| 96 | + "User", "Pass"); |
| 97 | + args.Response = response; |
| 98 | +}; |
| 99 | +``` |
| 100 | + |
| 101 | +## Cancel authentication prompt |
| 102 | +The developer can block the authentication request. In this case, the login dialog prompt will no longer be shown to the user and the server will respond as if the user clicked cancel. |
| 103 | + |
| 104 | +```cpp |
| 105 | + webviewStaging2->add_WebAuthenticationRequested( |
| 106 | + Callback<ICoreWebView2StagingWebAuthenticationRequestedEventHandler>( |
| 107 | + [this]( |
| 108 | + ICoreWebView2Staging2* sender, |
| 109 | + ICoreWebView2StagingWebAuthenticationRequestedEventArgs* args) { |
| 110 | + args->put_Cancel(true); |
| 111 | + |
| 112 | + return S_OK; |
| 113 | + }) |
| 114 | + .Get(), |
| 115 | + &m_webAuthenticationRequestedToken)); |
| 116 | +``` |
| 117 | +
|
| 118 | +```c# |
| 119 | +webView.CoreWebView2.WebAuthenticationRequested += delegate (object sender, CoreWebView2WebAuthenticationRequestedEventArgs args) |
| 120 | +{ |
| 121 | + args.Cancel = true; |
| 122 | +}; |
| 123 | +``` |
| 124 | + |
| 125 | +## Read authorization challenge string |
| 126 | +Developer can read the authorization challenge string sent by server. Note that if the developer doesn't cancel or provide a response, the login dialog prompt will be shown to the user. |
| 127 | + |
| 128 | +```cpp |
| 129 | +webviewStaging2->add_WebAuthenticationRequested( |
| 130 | + Callback<ICoreWebView2StagingWebAuthenticationRequestedEventHandler>( |
| 131 | + [this]( |
| 132 | + ICoreWebView2Staging2* sender, |
| 133 | + ICoreWebView2StagingWebAuthenticationRequestedEventArgs* args) { |
| 134 | + args->get_Challenge(&challenge); |
| 135 | + if (wcsncmp(challenge.get(), L"Expected login credentials") != 0) { |
| 136 | + args->put_Cancel(true); |
| 137 | + } |
| 138 | + return S_OK; |
| 139 | + }) |
| 140 | + .Get(), |
| 141 | + &m_webAuthenticationRequestedToken)); |
| 142 | +``` |
| 143 | +
|
| 144 | +```c# |
| 145 | +webView.CoreWebView2.WebAuthenticationRequested += delegate (object sender, CoreWebView2WebAuthenticationRequestedEventArgs args) |
| 146 | +{ |
| 147 | + if (args.Challenge.Equals("Expected login credentials")) { |
| 148 | + args.Cancel = true; |
| 149 | + } |
| 150 | +}; |
| 151 | +``` |
| 152 | + |
| 153 | +# Remarks |
| 154 | + |
| 155 | + |
| 156 | +# API Notes |
| 157 | + |
| 158 | + |
| 159 | +# API Details |
| 160 | +```idl |
| 161 | +/// This is the ICoreWebView2 Staging interface. |
| 162 | +[uuid(9EAFB7D0-88C3-4450-BBFB-C05A46C40C72), object, pointer_default(unique)] |
| 163 | +interface ICoreWebView2Staging2 : IUnknown { |
| 164 | + /// Add an event handler for the WebAuthenticationRequested event. |
| 165 | + /// WebAuthenticationRequested event fires when WebView encountered a Basic HTTP |
| 166 | + /// Authentication request. |
| 167 | + /// |
| 168 | + /// The host can provide a response with credentials for the authentication or |
| 169 | + /// cancel the request. If the host doesn't handle the event, WebView will show |
| 170 | + /// the authorization challenge dialog prompt to user. |
| 171 | + /// |
| 172 | + HRESULT add_WebAuthenticationRequested( |
| 173 | + [in] ICoreWebView2StagingWebAuthenticationRequestedEventHandler* eventHandler, |
| 174 | + [out] EventRegistrationToken* token); |
| 175 | + /// Remove an event handler previously added with add_WebResourceRequested. |
| 176 | + HRESULT remove_WebAuthenticationRequested( |
| 177 | + [in] EventRegistrationToken token); |
| 178 | +} |
| 179 | +
|
| 180 | +/// This is the CoreWebView2WebAuthenticationRequestedEventHandler Staging interface |
| 181 | +[uuid(f87e5d35-3248-406b-81dd-1c36aab8081d), object, pointer_default(unique)] |
| 182 | +interface ICoreWebView2StagingWebAuthenticationRequestedEventHandler : IUnknown |
| 183 | +{ |
| 184 | + /// Called to provide the implementer with the event args for the |
| 185 | + /// corresponding event. |
| 186 | + HRESULT Invoke( |
| 187 | + [in] ICoreWebView2Staging2* sender, |
| 188 | + [in] ICoreWebView2StagingWebAuthenticationRequestedEventArgs* args); |
| 189 | +} |
| 190 | +
|
| 191 | +/// Represents a Basic HTTP authentication response that contains a user name |
| 192 | +/// and a password as according to RFC7617 (https://tools.ietf.org/html/rfc7617) |
| 193 | +[uuid(bc9cfd60-29c4-4943-a83b-d0d2f3e7df03), object, pointer_default(unique)] |
| 194 | +interface ICoreWebView2StagingWebAuthenticationResponse : IUnknown |
| 195 | +{ |
| 196 | + /// User name provided for authorization. |
| 197 | + [propget] HRESULT UserName([out, retval] LPWSTR* userName); |
| 198 | + /// Set user name property |
| 199 | + [propput] HRESULT UserName([in] LPCWSTR userName); |
| 200 | +
|
| 201 | + /// Password provided for authorization |
| 202 | + [propget] HRESULT Password([out, retval] LPWSTR* password); |
| 203 | + /// Set password property |
| 204 | + [propput] HRESULT Password([in] LPCWSTR password); |
| 205 | +} |
| 206 | +
|
| 207 | +/// Event args for the WebAuthorizationRequested event. Will contain the |
| 208 | +/// request that led to the HTTP authorization challenge, the challenge |
| 209 | +/// and allows the host to provide authentication response or cancel the request. |
| 210 | +[uuid(51d3adaa-159f-4e48-ad39-a86beb2c1435), object, pointer_default(unique)] |
| 211 | +interface ICoreWebView2StagingWebAuthenticationRequestedEventArgs : IUnknown |
| 212 | +{ |
| 213 | + /// The web resource request that led to the authorization challenge |
| 214 | + [propget] HRESULT Request([out, retval] ICoreWebView2WebResourceRequest** request); |
| 215 | +
|
| 216 | + /// The authorization challenge string |
| 217 | + [propget] HRESULT Challenge([out, retval] LPWSTR* challenge); |
| 218 | +
|
| 219 | + /// Response to the authentication request with credentials. |
| 220 | + [propget] HRESULT Response([out, retval] ICoreWebView2StagingWebAuthenticationResponse** response); |
| 221 | + /// Set the Response property. |
| 222 | + [propput] HRESULT Response([in] ICoreWebView2StagingWebAuthenticationResponse* response); |
| 223 | +
|
| 224 | + /// Cancel the authentication request. False by default. |
| 225 | + /// If set to true, Response will be ignored. |
| 226 | + [propget] HRESULT Cancel([out, retval] BOOL* cancel); |
| 227 | + /// Set the Cancel property. |
| 228 | + [propput] HRESULT Cancel([in] BOOL cancel); |
| 229 | +} |
| 230 | +
|
| 231 | +[uuid(0cec3e32-36aa-4859-9bbe-f9c116ad4721), object, pointer_default(unique)] |
| 232 | +interface ICoreWebView2StagingEnvironment : IUnknown { |
| 233 | + /// Create a WebAuthenticationResponse object used to provide credentials for |
| 234 | + /// WebAuthenticationRequested event |
| 235 | + HRESULT CreateWebAuthenticationResponse( |
| 236 | + [in] LPCWSTR userName, |
| 237 | + [in] LPCWSTR password, |
| 238 | + [out, retval] ICoreWebView2StagingWebAuthenticationResponse** response); |
| 239 | +} |
| 240 | +
|
| 241 | +``` |
| 242 | + |
| 243 | +```c# |
| 244 | +namespace Microsoft.Web.WebView2.Core |
| 245 | +{ |
| 246 | + runtimeclass CoreWebView2Environment |
| 247 | + { |
| 248 | + ... |
| 249 | + |
| 250 | + /// Create a WebAuthenticationResponse object used to provide credentials for |
| 251 | + /// WebAuthenticationRequested event |
| 252 | + public CoreWebView2WebAuthenticationResponse CreateWebAuthenticationResponse( |
| 253 | + String userName, |
| 254 | + String password); |
| 255 | + } |
| 256 | + |
| 257 | + /// Event args for the WebAuthorizationRequested event. Will contain the |
| 258 | + /// request that led to the HTTP authorization challenge, the challenge |
| 259 | + /// and allows the host to provide authentication response or cancel the request. |
| 260 | + runtimeclass CoreWebViewWebAuthenticationRequestedEventArgs |
| 261 | + { |
| 262 | + /// The web resource request that led to the authorization challenge |
| 263 | + CoreWebView2WebResourceRequest Request { get; }; |
| 264 | + |
| 265 | + /// The HTTP basic authorization challenge string |
| 266 | + String Challenge { get; }; |
| 267 | + |
| 268 | + /// Cancel the authentication request. False by default. |
| 269 | + /// If set to true, Response will be ignored. |
| 270 | + bool Cancel { get; set; }; |
| 271 | + |
| 272 | + /// Response to the authentication request with credentials. |
| 273 | + CoreWebView2WebAuthenticationResponse Response { get; set; }; |
| 274 | + } |
| 275 | + |
| 276 | + /// Represents a Basic HTTP authentication response that contains a user name |
| 277 | + /// and a password as according to RFC7617 (https://tools.ietf.org/html/rfc7617) |
| 278 | + runtimeclass CoreWebView2WebAuthenticationResponse |
| 279 | + { |
| 280 | + /// User name provided for authorization. |
| 281 | + String UserName { get; set; } |
| 282 | + |
| 283 | + /// Password provided for authorization |
| 284 | + String Password { get; set; }; |
| 285 | + } |
| 286 | + |
| 287 | + runtimeclass CoreWebView2 |
| 288 | + { |
| 289 | + ... |
| 290 | + |
| 291 | + /// Add an event handler for the WebAuthenticationRequested event. |
| 292 | + /// WebAuthenticationRequested event fires when WebView encountered a Basic HTTP |
| 293 | + /// Authentication request. |
| 294 | + /// |
| 295 | + /// The host can provide a response with credentials for the authentication or |
| 296 | + /// cancel the request. If the host doesn't handle the event, WebView will show |
| 297 | + /// the authorization challenge dialog prompt to user. |
| 298 | + /// |
| 299 | + event Windows.Foundation.TypedEventHandler<CoreWebView2, CoreWebViewWebAuthenticationRequestedEventArgs> WebAuthenticationRequested; |
| 300 | + } |
| 301 | +} |
| 302 | +``` |
0 commit comments