MicrosoftEdge/WebView2Feedback

Support for intercepting (or querying) the selected client certificate

MichaelKetting opened this issue ยท 38 comments

I looked at the API docs (https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2/reference/iwebview2webview) but didn't see find a matching API, so here's the feature request:

It would be great to be able to either intercept (or at least query the selected) client certificate when a web site requires certificate-based authentication.

SSLStream has this option via the https://docs.microsoft.com/en-us/dotnet/api/system.net.security.localcertificateselectioncallback.

AB#21927323

Thanks, great feature request. I'll open a task to investigate adding that.

Can you elaborate on your app scenario that would use this feature?

@david-risney thank you for looking into this! The case is a special case of #4, just with certificate-based authentication instead of cookies.

The practical examples a bit rarer than the cookie-authentication, but you will find these scenarios with line-of-business applications that consist of webserver and desktop components when building software for large corporations or in the public sector.

Without the option of re-using the certificate selection, the user is essentially required to chose the correct certificate twice, once for the web site and once when performing the first out-of-band request.

Upon further review, the option for additionally setting the certificate to be used would also be great. The scenario for this is that you already know which certificate is required (due to a previous selection) and want to show the user a web page to interact with.

@MichaelKetting -- I'm interested to know whether your feature request includes an ability for apps to override WebView2's validation/acceptance of the certificate. When you tell WebView2 which certificate to use, should WebView2 immediately treat the certificate as validated/accepted or should WebView2 proceed to validate the Certification Authority (CA), and certificate expiration date, etc?

For example, if you have a self-issued certificate that was created by an Active Directory Domain Controller, then the CA is unknown/untrusted outside of that Active Directory and WebView2 would normally reject the certificate or warn the user and ask whether to proceed. In your feature request, would it be possible to instruct WebView2 to use the certificate without rejecting or warning about unknown/untrusted CA's?

@verelpode I haven't actually tried using a non-trusted certificate before when setting up client certificate-based authentication. Interesting to know that the browser will normally make a ruckus when you try to authenticate using a non-trusted certificate.

As for your question: I don't have a preference, I think. The intention is to simply implement the certificate selection inside my own code but with the mission statement of emulating the browser's original behavior.

From a security point of view, it might be in Mircosoft's interest to only allow trusted certificates to be injected into the WebView2 and that would be fine with me.

From a point of flexibility, being able to use any certificate (trusted or untrusted) on the client side so long as it's trusted by the server could open up additional scenarios for some developers.

Do you happen to know what .NET does when you set the client certificate of HttpClient etc to a certificate that's untrusted by the client? I would recommend choosing the option that's symmetrical with the rest of the ecosystem.

Do you happen to know what .NET does when you set the client certificate of HttpClient etc to a certificate that's untrusted by the client?

Although I'm no expert in the use of self-issued or DC-issued certificates, I believe it's easier to make Windows.Web.Http.HttpClient accept the certificate than the older System.Net.Http.HttpClient.

var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired);
var testClient = new Windows.Web.Http.HttpClient(filter);

I would recommend choosing the option that's symmetrical with the rest of the ecosystem.

In that case, the feature request can be to make WebView2 support the same certificate options as HttpBaseProtocolFilter. WebView2 would have settings the same as the following members of HttpBaseProtocolFilter:

public Windows.Security.Cryptography.Certificates.Certificate ClientCertificate { get; set; }
public IList<Windows.Security.Cryptography.Certificates.ChainValidationResult> IgnorableServerCertificateErrors { get; }
public event TypedEventHandler<HttpBaseProtocolFilter,HttpServerCustomValidationRequestedEventArgs> ServerCustomValidationRequested;

The same certificate-related members (with exact same names) also exist in StreamWebSocketControl and StreamWebSocket.

Sounds good to me from what I can gather.

var filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Untrusted);
filter.IgnorableServerCertificateErrors.Add(Windows.Security.Cryptography.Certificates.ChainValidationResult.Expired);
var testClient = new Windows.Web.Http.HttpClient(filter);

Your sample uses IgnorableServerCertificateErrors which I would assume refers to the server certificates sent to the client. Unless the member is repurposed to deal with untrusted client certificates as well, that's not affecting the behavior of untrusted client certificates.

In StreamWebSocketControl, the ClientCertificate property is documented as get-only but implemented with a getter and a setter. I'm assuming the documentation is wrong that you can use the StreamWebSocketControl.ClientCertificate to assign the certificate to be used for authenticating the client.

Good point. I did overlook the fact that it is named IgnorableServerCertificateErrors not IgnorableClientCertificateErrors. In order to say exactly how it behaves, I'd have to run tests, as I'm no expert in certificates. Ideally it would be useful to have the ability to configure it in both directions. Maybe it already behaves practically equivalent to both directions despite the name but I don't know.

@verelpode @david-risney Is there any way to override the WebView2's validation/acceptance of the certificates in the code?
Example: suppose I open a URL in webview2 that requires certificate authentication . It prompts a 'Select a certificate popup..' before loading a content. When i click on Ok, it loads the page.
But my requirement is to do this validation/acceptance part in my code itself without showing this popup on the page. Is there any possible way to do it?

@verelpode @david-risney

Is there any way to override the WebView2's validation/acceptance of the certificates in the code?
[...]
But my requirement is to do this validation/acceptance part in my code itself without showing this popup on the page. Is there any possible way to do it?

I have come across the same requirement for a business application: I need to accept the certificate programmatically if it is still valid.

I would like to add my interest for this request.

In a Web Browser when a user logs into the target website they are required to log in with a certificate stored in a smartcard. Once logged in the person can remove the smartcard and the website continues to work.

I wish to add a feature to my hybrid app where it tracks the removal of the smartcard. If the smartcard contains the certificate that was used to log in, I intend to put some kind of overlay over my hybrid app to stop it being used. Once the smart card with the already used certificate is re-inserted then the overlay will be removed.

I therefore want to know at least which X509Certificate2 webview2 will use.

Thanks everyone for the comments and discussion. We are working on designing the ClientCertificate API in webview2 now. At a very high level this might include a CertificateRequest event being fired in lieu of the 'select a certificate for authentication' popup, which devs could intercept, query, and select a certificate.

A couple questions that would help us:

  1. Are there any hard-requests for custom certs (would not having custom-certs be a blocker for you)?
  • The concern here is that there is currently no way to create app-only custom certificates. What I mean by this is that certificates are shared per user/ per system, and NOT per app.
  1. Is there a need to set a default or one-off certificate WITHOUT the CertificateRequest Event being fired? In comparison to the browser, would your app need to set the clientcert without the select cert popup being shown?

Please let me know if these questions don't make sense, would gladly expand. Thanks.

Hi, I honestly have no experience on certificates other than they exist and in my case exist are located on an id card inserted in the pc.

Answering your questions for my use case;

  1. no.
  2. no.

Hi,

I would like to know if webview2 can allow to select an appropriate valid certificate programmatically. In case of IE based implementation, we were able to achieve this by implementing IHttpNegotiate3 and passing the info in a cookie to prevent IE from prompting when there are multiple certificates. Now we need similar functionality to work with webview2.

Example : End user can have multiple certificates installed on their browser. I would like WebView to identify and validate certificate based on some input and allow user to pass through the login process without showing them a 'Select a certificate' pop up. In case of failure it should throw an error."

Here are my answers for your questions

  1. No
  2. Yes, we need our application to set the clientcert without the select cert popup being shown?

@jasonstephen15

ad 1) not having per-app certificates sounds fine to me.

ad 2) for me, it's okay to get the event, I can always set it up to supply the default certificate.

To summarize: I get the event if the website actually requests a certificate same way I would only get a certificate prompt if the website requests a certificate. And in the event arguments I get the list of valid certificate authorities the server would accept so I can filter the certificate selection based on these authorities. Then I select (via my own implementation detail) the certificate to use, put that in the event arguments and let the browser do its thing. If the selected certificate doesn't work, the event is displayed again.

Sounds good to me.

At a very high level this might include a CertificateRequest event being fired in
lieu of the 'select a certificate for authentication' popup, which devs could intercept,
query, and select a certificate.

Nice!

Are there any hard-requests for custom certs (would not having custom-certs be a blocker for you)?

No.

Is there a need to set a default or one-off certificate WITHOUT the CertificateRequest Event being fired?

No.

Hi,

I would like to know if webview2 can allow to select an appropriate valid certificate programmatically. In case of IE based implementation, we were able to achieve this by implementing IHttpNegotiate3 and passing the info in a cookie to prevent IE from prompting when there are multiple certificates. Now we need similar functionality to work with webview2.

Example : End user can have multiple certificates installed on their browser. I would like WebView to identify and validate certificate based on some input and allow user to pass through the login process without showing them a 'Select a certificate' pop up. In case of failure it should throw an error."

Here are my answers for your questions

  1. No
  2. Yes, we need our application to set the clientcert without the select cert popup being shown?

@rgup63 - I believe the current proposal covers this. Yes, when the CertificatRequest event is fired, you'd be able to intercept it programmatically. Regarding #2, this api will come with a way to disable the popup. My question was trying to ask WHEN you'd want to set a client cert. Is it only when the CertificateRequest event is fired, or at any other time. Sounds like most of the responses here are saying setting cert only when the event is fired is fine.

Good question though, hope this clarification makes sense.

Seems like the proposal sounds good for most, will follow up here after we have designed the api, and we can review it further together! Thanks.

Hi all, wanted to try and gather feedback about certificates that need strong private key protection. (Pictured in screenshot below). This pop-up and workflow is handled via a Windows API, separate from the browser/webview2. Because of this, we may not be able to handle this case programmatically in the upcoming client cert api. Was wondering if this was a common use case for folks here. Thoughts/opinions?

(Note: this is an edge case... for other cert selections, our goal is to be able to handle it programmatically because there wont be a windows prompt.)

a157bd76-1de0-4992-bfb5-9af54eee7440

This is a great question and one I was really hoping you would ask.

I would very much love to see you provide a callback for this window.

Reasons / Use Case

  1. I have to put this as number 1. That "Window Security" window is ugly and does not fit with a modern looking WINUI/ UWP or even WPF application in 2021. This alone should be enough when you consider your design for WebView2 ๐Ÿ’ฏ
  2. Current browsers give no feedback on waiting for this window to appear. It can sometime take up to 20 seconds where I use this for the window to appear. (READ THIS WITH point No.5 below)
  3. The window runs in its own process/thread and thus sometimes does not come to the front of all windows. You are left with the (windows intentionally implemented) flashing icon in the toolbar to recognize that the window has come to life.
  4. With multiple screens the window sometimes appears on another window to your browser and also sometimes not in the middle of the screen.
  5. THE REAL PAIN is that when this window shows, you only have a certain amount of time to enter a pin and click ok otherwise the server waiting for an answer times out. This means you have to sit there and wait for this window and enter your pin, instead of getting on with things.

If Webview2 supplied a callback for this then we could avoid all of the above issues. It would also mean that the user would be able to complete the login process without the need to wait for windows and therefore create a smoother user experience. Oh and did I mention I think the above window is ugly?

Of Course there are the security concerns
It cannot go without saying that exposing this callback would mean that the application would have the opportunity of collecting the users pin/password. In my opinion please don't cripple Webview2 because of this. A hybrid app using Webview2 is a choice and thus users should know what they are doing. Further, users can use a browser instead if they don't like the hybrid app.

What did/do other .Net APIs do?
GeckFX (aka Firefox) had a PromptService class and nsIPrompt interface which had a number of callbacks for user names and passwords including one for this window. It has been a while but it looks like I used PromptPassword as the callback.
CefSharp does not supply a call back however this is because CEF does not expose one.

My summary of this is that it is possible to supply a password to that Widows API instead of using this window and that at least Gecko / Firefox developers saw it as a good idea.

By the way this is the window I see.

image

@jasonstephen15 I'm not sure about the strong-crypto window, but when I use a PIN-protected smartcard, I got the window referenced by @darbid. I did not yet try the smartcard experience with MS Edge / WebView2, so I'm not sure if that would trigger the strong-crypto window first and then the PIN window.

Anyhow, the PIN window is part of the standard experience for customers who rely on smartcards for authentication, so that's pretty much the standard usecase when using certificates for my applications.

@jasonstephen15

Thanks everyone for the comments and discussion. We are working on designing the ClientCertificate API in webview2 now. At a very high level this might include a CertificateRequest event being fired in lieu of the 'select a certificate for authentication' popup, which devs could intercept, query, and select a certificate.

Since it wasn't mentioned in the above spec: please include the list of trusted issues in the CertificateRequest event as transmitted to the client in the SSL handshake.

@jasonstephen15

Thanks everyone for the comments and discussion. We are working on designing the ClientCertificate API in webview2 now. At a very high level this might include a CertificateRequest event being fired in lieu of the 'select a certificate for authentication' popup, which devs could intercept, query, and select a certificate.

Since it wasn't mentioned in the above spec: please include the list of trusted issues in the CertificateRequest event as transmitted to the client in the SSL handshake.

@MichaelKetting Yes, we will include the list of trusted issuers/certificate authorities in the event. You can expect API review spec doc soon for the feedback

Hi all, We've completed our design for the Client Certificate Requested API! Please review the pull request and add any feedback about this API. We appreciate your input and support!

Hi all, we are wrapping up Client Certificate API soon and would appreciate feedback to make sure our design meets the request.

Theoretically it looks nice to me. Only comment I have is that I am not sure why you exposed a CoreWebView2ClientCertificate instead of a X509Certificate2. I hope I will be able to compare X509 with your CoreWebView2ClientCertificate.

@monica-ch Thank you, this looks good to me.

@darbid Thank you for the feedback. Converting CoreWebView2(eg CoreWebView2ClientCertificate) types to .NET types was difficult to get it working well and also maintaining object identity and using the correct CoreWebview2Environment. Instead we are going to add ToX509Certificate2() method to CoreWebView2ClientCertificate class. This will reflect in the design soon.

BUPA commented

just came across this issue when googling for the behaviour for Certificate Based Logon.

In the "normal" Edge there is a imho smart solution for such things as well by a group policy so a organisation can influence such things. As a App it may be hard to choose the correct certificate at all If it's deployed to several customers with several Logon mechanisms.
https://docs.microsoft.com/en-us/deployedge/microsoft-edge-policies#autoselectcertificateforurls

Thanks @BUPA for the comment. WebView2 doesn't use Edge browser policies though. We have our own WebView2-specific group policy, although limited because generally we want to enable app developers to create and manage their own policies.

Imagine IT admins for a specific company having to worry about Edge policy interactions with WebView2 (which they may or may not be even aware is apart of their company's app).

BUPA commented

As always there are two side of the medal.
I think as an App developer in a Business Scenario cannot foresee what my customer may do in terms of Certificate selection or Security guidelines. and therefore would simply be integrated into the policies already in place for the Edge itself.

This may differ if someone is in a non managed, private End-user scenario where it's crucial to keep as many complexitiy (and therefore errors/support) away from my users by doing special, custom stuff in this place.

Hi all! Client certificate API is in our pre-release package and is ready to be tried out in an experimental state. Try it out and let us know your feedback!

https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2experimental3?view=webview2-1.0.902-prerelease

does this new Certificate work with a WPF application?

When I tried the sample code I get errors about interface converation for experiment3 where do I get the latest runtime?

@juscla We recommend that you use the Canary channel when you develop using the prerelease packages, and the Evergreen WebView2 Runtime when you use the release packages.

https://docs.microsoft.com/en-us/microsoft-edge/webview2/release-notes#10902-prerelease

@monica-ch Can you please confirm if CoreWebView2.ClientCertificateRequested API has been released in the latest stable package? I installed webview2 1.0.902.49 but I don't see it.

@rgup63 It will be in the next stable package (beginning of September).