Hello,
When connecting to a Bitwarden server that's behind an nginx proxy that requires a client cert, the app just crashes when pressing the Log In button. The same server works fine on Firefox, requesting access to my certificate as expected, and when I disable the requirement to have client authentication through my reverse proxy, the app works fine too.
I see this is a known issue based on a few forum posts (https://community.bitwarden.com/t/client-certificates/427, https://community.bitwarden.com/t/mobile-app-cant-access-server-behind-reverse-proxy-with-client-cert-authentification/2071 etc) so thought I'd raise an issue.
Hi, I have the same use case and a similar experience that you have @codingJWilliams. It would be a nice addition to the mobile app to support TLS client authentication. The added security would be beneficial for on-premise deployments.
Perhaps we can join forces and come up with an implementation that could be merged into mainline?
@kspearrin Could you give your opinion on this and maybe some pointers on where to start?
All server communication happens with httpclient here: https://github.com/bitwarden/mobile/blob/master/src/Core/Services/ApiService.cs
I am not sure what is needed to support client certificates.
Thanks for your quick answer and the pointer. I'll have a stab at it, but first I'll need to setup a C# dev environment on Linux. I'm quite new to C# development, so if anyone has any experience to share, I'd be much obliged. My first bet is Rider from Jetbrains, let's hope this works :crossed_fingers:.
Unfortunately, there is no Xamarin support on Linux that I know of.
It seems to be one of the advertised features of Rider: https://www.jetbrains.com/rider/features/
I'll let you know if it works out.
Hello,
Thank you for the very kind offer @agboom but I'm rather hopeless at C#!
I did some basic research and this does seem to be possible with the System.Net.HttpClient but I wouldn't know where to start with implementing this - if you need any help testing or similar, however, please let me know.
I will take a shot however this does seem to be outside of my comfort zone.
Thanks @codingJWilliams I'll give a shout if there's something to test or otherwise.
My main challenge right now is to get the dev environment working on Linux which is new to me for C#. The Jetbrains Rider IDE requires a paid license which is a bummer, because it's currently my only chance of Xamarin development on Linux AFAIK. Jetbrains does offer free licenses to open source project contributors, so maybe hope @kspearrin?
Hello,
I've been able to make some progress on this - it's rather crude and doesn't use the system certificate selection dialog but I have at least been able to get the app to connect. Inside the ApiService.cs I have modified the HttpClient definition to the following: https://paste.voidcrafted.me/asogiyijev.cs
Then, I added the modernhttpclient-updated NuGet package and built the app, which was then able to connect to my server.
One thing I would note is that I'm not quite sure of the implications of DangerousAcceptAnyServerCertificateValidator = true however without this I could not get the HttpClient to accept my server's certificate - even explicitly adding the certificate as described by https://libraries.io/nuget/modernhttpclient-updated. Will make an issue on their end to look into this - could be because I use a wildcard *.voidcrafted.me SSL certificate.
It's hacky, but works, so possibly a good starting point. I would ideally like this to be able to use certificates installed on the system rather than needing access to the pfx file though.
Thanks for picking this up @codingJWilliams, I've been out of luck with Xamarin on Linux. Although I could start a trail period with Jetbrains Rider, the Xamarin SDK did not work out of the box and requires some packages that failed to install on my system.
Great that you got it working! My guess for the implications of DangerousAcceptAnyServerCertificateValidator is that the client possibly accepts certs from any certificate authority, similar to where you would add an exception for an unknown cert in Firefox or Chrome, except in this case all certs are accepted. If that's the case the Dangerous prefix is appropriate, since it defeats the purpose of having TLS.
If the HttpClient indeed does accept your server certificate that could be a bug. Just thinking out loud here: did you try to add the CA cert?
Not sure how the system certificates could be used, but I agree that it is the desired functionality.
Is there any development continuing on this? This is something I am very interested in
Unfortunately, I am also not at all a C# developer nor have I done any mobile platform development before, so I don't think I would be very helpful either, unless someone can point me towards how to set up a Linux development environment.
I can't imagine the code would be that complicated, seems the UI portion would be more work than the logic. The way I would expect the UI to work would be to have an option/dialog for "Identity" where installed client certificates could be selected from, much in the way that iPhone EAP-TLS functions
I can try to get a simple environment up that will allow me to at least write a bare bones "tls_connect" function with an optional client certificate, but I would have to pass that off to someone familiar with the UI portion, and familiar with the iOS/Android APIs for selecting the certificates from the device
EDIT: https://thomasbandt.com/certificate-and-public-key-pinning-with-xamarin seems to be a useful resource
@codingJWilliams I agree that using an "installed" system certificate would be ideal, but I would be happy with the .pfx/.p12 as a start (and I think that's a reasonable way to implement it, so long as it doesn't get in the way of the UI options most commonly used)
@kspearrin is TLS client certificate authentication something you are willing to support? This would be great for hosted instances
EDIT: Currently TLS client certificate auth works fine with BitWarden via web browser. It is just the iOS application I am talking about here!
I'm sorry to hijack the thread here, but I tried to organize some thoughts about it, hoping you would be willing to listen and consider. If you prefer this in a separate issue, or communication via another medium, please let me know!
First, there is _not_ a problem with the authentication mechanisms of BitWarden for users. It currently supports very strong methods of authentication, which protect users from account takeovers. These work very well to accomplish what they set out to do
However, some users and organizations would like a way to proactively protect a hosted BitWarden server from pre-authentication attacks on the BitWarden HTTP based application. A successful attack making use of a vulnerability in BitWarden could be disastrous for an organization, due to the nature of the product. While secrets are encrypted on the server, an attacker who compromised the web infrastructure could very easily capture login credentials from users and then... well, you know.
There are some other options users and organizations have (VPNs, Firewalls, Layer 7 filters/controls, etc) but none are as simple or elegant as mutually authenticated TLS for solving this problem. Especially in the age of MDM, where many organizations have the ability to push "identity" certificates to managed devices, TLS client authentication becomes something that is available "for free"
Assuming this discussion is worth having, here are some thoughts on implementation approaches. I see two ways to do this without making it into an unnecessarily large project, and without impacting existing UX
The second approach is obviously better as it's less work and does not disturb workflow or UX for users that do not require this feature. The amount of development involved seems to me to be relatively small, unless the framework(s) being used are terribly flawed in facilitating this functionality
Because I do not know what the APIs provide you with, I can give a quick low-level summary of what happens in the connection when a client certificate is required, in case you are not familiar with the SSL/TLS handshake. This should give you an idea of what you would need from an API
TLS Client HelloServer Hello, Certificate, Server Key Exchange and Certificate Request [1]Certificate response to the Certificate Request from the server[1] For a "normal" HTTPS server, the Certificate Request message would only flow from client to server. This is what allows the API to know it needs to present a certificate during the handshake
Thanks for reading through this, I'm happy to help out any way I can. Especially if that means writing this in shorter form :>
@mzpqnxow I don't doubt that this would be a good idea to add, however, priorities don't align for me to look into this further at the moment. I've added the "help wanted" tag here if someone wants to contribute to the feature. Ideally we'd somehow use a a cert on the device without having to prompt a user to pick it.
Fair enough, thank you. And I agree with that approach.
@agboom , @codingJWilliams any interest/time in picking this up again? Any luck on getting a no-cost dev environment up in Linux so that I might be able to help?
I started to look at the android implementation. Unfortunately, I'm better with SSL in C# than java so I didn't find a way to use device's certificates without prompting the user to choose one.
I made some tests with pfx protected certificate, when the api call fails with ssl errors, it asks the user for a certificate. The certificate is then installed on device KeyChain so we can reuse it next time without having to ask the certificate credentials again (screenshots of the flow at the end)
You can take a look at the code here : https://github.com/MrLuje/mobile/tree/android-tls-auth
https://user-images.githubusercontent.com/632075/71647255-4f29c000-2cf4-11ea-995f-379df82fb8de.png
https://user-images.githubusercontent.com/632075/71647256-5650ce00-2cf4-11ea-82bc-ddbfc00001a7.png
https://user-images.githubusercontent.com/632075/71647258-5650ce00-2cf4-11ea-91b2-9d659c8e9f5f.png
https://user-images.githubusercontent.com/632075/71647259-56e96480-2cf4-11ea-9aac-504928c7b629.png
Hello,
Sorry for dropping this, I didn't see the email about this. I think that's all very promising progress, and your implementation does look good @MrLuje , thanks for the hard work on that. From a UX standpoint your implementation looks good as well, essentially just the normal dialog that chrome prompts with. Once I'm back at my desktop tomorrow I'll test your build of that.
Thanks for being interested in implementing this guys, best open source contributors <3
For Android, in order to avoid the cert prompting, you need to specify your own KeyManager to SSLContext. The KeyManager - which could be derived from X509ExtendedKeyManager - needs to have the key pair alias and private key entry (KeyStore.PrivateKeyEntry) set in it, so that the alias can be returned by "chooseClientAlias", and the private key entry can be used for "getPrivateKey" and "getCertificateChain". I can provide a Java sample of the if you are interested.
I really appreciate the time you put into this @MrLuje
I see you put clean stubs in for iOS. I'm not experienced at all with Xamarin/.NET so wanted to ask if it is correct to assume that the iOS implementation will need to be mostly/completely different for this? I know Xamarin provides abstraction, but maybe that's less relevant when it comes to crypto features, which I assume aren't quite 1:1 on Android vs iOS
I see you put clean stubs in for iOS. I'm not experienced at all with Xamarin/.NET so wanted to ask if it is correct to assume that the iOS implementation will need to be mostly/completely different for this?
I'm not experienced enough with iOS to tell (and I have no device to build/test it), I have a rough idea about how to implement the http client part, but I don't know what is possible to do with iOS regarding certificates. That's also why I'm not pushing the android version further (except if we can have feature-discrepancy between iOS & Android)
@MrLuje I see.. thanks.
FWIW to those on this issue, I'm willing to offer a small bounty for anyone who will implement the iOS support (and actually get a PR accepted upstream and into the AppStore build) .. maybe $500USD? Any takers? ;)
Hey,
just want to give this a push.
Would be a very nice feature for Android and iOS
I hereby increase the bounty to... $501USD!
Most helpful comment
@kspearrin is TLS client certificate authentication something you are willing to support? This would be great for hosted instances
EDIT: Currently TLS client certificate auth works fine with BitWarden via web browser. It is just the iOS application I am talking about here!
I'm sorry to hijack the thread here, but I tried to organize some thoughts about it, hoping you would be willing to listen and consider. If you prefer this in a separate issue, or communication via another medium, please let me know!
The Problem
First, there is _not_ a problem with the authentication mechanisms of BitWarden for users. It currently supports very strong methods of authentication, which protect users from account takeovers. These work very well to accomplish what they set out to do
However, some users and organizations would like a way to proactively protect a hosted BitWarden server from pre-authentication attacks on the BitWarden HTTP based application. A successful attack making use of a vulnerability in BitWarden could be disastrous for an organization, due to the nature of the product. While secrets are encrypted on the server, an attacker who compromised the web infrastructure could very easily capture login credentials from users and then... well, you know.
There are some other options users and organizations have (VPNs, Firewalls, Layer 7 filters/controls, etc) but none are as simple or elegant as mutually authenticated TLS for solving this problem. Especially in the age of MDM, where many organizations have the ability to push "identity" certificates to managed devices, TLS client authentication becomes something that is available "for free"
TLS Client-Certificate Authentication Support - The Benefits
The Use Cases
Suggested Implementation
Assuming this discussion is worth having, here are some thoughts on implementation approaches. I see two ways to do this without making it into an unnecessarily large project, and without impacting existing UX
Effort Involved
The second approach is obviously better as it's less work and does not disturb workflow or UX for users that do not require this feature. The amount of development involved seems to me to be relatively small, unless the framework(s) being used are terribly flawed in facilitating this functionality
Because I do not know what the APIs provide you with, I can give a quick low-level summary of what happens in the connection when a client certificate is required, in case you are not familiar with the SSL/TLS handshake. This should give you an idea of what you would need from an API
TLS Client HelloServer Hello,Certificate,Server Key ExchangeandCertificate Request[1]Certificateresponse to theCertificate Requestfrom the server[1] For a "normal" HTTPS server, the
Certificate Requestmessage would only flow from client to server. This is what allows the API to know it needs to present a certificate during the handshakeThanks for reading through this, I'm happy to help out any way I can. Especially if that means writing this in shorter form :>