I'm working on a native app for iOS and Android using React-Native. I have to hit a third-party REST API that uses https:// protocol. There is a staging server and a production server for the API.
I have success making requests to both servers on iOS. On Android, I can access staging, but not production. Requests to both servers are successful using Postman.
Requests to production on Android give me the infamous [TypeError: Network request failed] message. I looked around on this site and elsewhere, and learned that this is usually the result of a certificate trust issue (which is not something I'm super knowledgeable about). I used openssl to view the certificates and did see three certs when checking staging, and only two for production. I tried following the custom TrustManager example on the Android HTTPS and SSL page: https://developer.android.com/training/articles/security-ssl.html
As well as this tutorial for SSL pinning: https://medium.com/the-many/a-year-of-react-native-ssl-pinning-3801a973cbfe
No luck. I should probably mention that at no point have I seen any logcat messages referring to certificate trust errors, so I'm not even entirely sure this is my issue.. it's just the only thing that makes sense based on what I've been able to find out. I tried going to Android Studio Preferences > Tools > Server Certificates and enabled 'Accept non-trusted certificates automatically' as a sanity check for testing. Still no luck and no change in log messages.
The requests are formatted exactly the same in React-Native, and are successful in three out of four of my scenarios (iOS staging & prod, Android staging). What am I missing?
Related
Could you suggest how to add a self-signed certificate on Android (MIUI 12, Android 10).
There is a mobile app for Android, and a backend written in symfony. We have a bug that is very difficult to catch, and it is not clear whether it is a bug in the app or a problem in the backend. Currently, it is not known which endpoints in which order the mobile app calls. When I test my local backend through postman, everything works as expected (there is no bug). When I test on Android (which is directed to the stage), I can see a bug. Hence, it was decided to build the application directed to local backend by replacing the api-url with the hostname of my laptop. Then the requests would go over the local network to the local backend, where it would be possible to debug what exactly is happening. But once we've built the app, it turned out that it's not that simple to send requests to the local backend since a self-signed certificate is used. I tried to add this certificate to the android config, but nothing changed. Though, certificate shows up in the list. Maybe I made some mistakes when converting that certificate (because xiaomi doesn't allow to import a .crt file), or maybe it's backend that is configured incorrectly.
Can anyone who has encountered such a problem tell me how to set the environment up correctly. Maybe there is some guide on this topic.
PS. It is not an option to use Ngrok, because it will be necessary to distract the mobile team every time in order to build the application with the new url.
I have an Android app which communicates to a backend server via HTTP POST requests. I would like to upgrade it to HTTPS. The API I'm using is HttpLib.postRequest.
I'm finding that a direct connection to my Apache server works fine. But a connection via a load balancer doesn't work. My load balancer is from Aliyun. I've tried two different load balancers, both fail the same way. The direct symptom is that I get an "unknown_err" on the phone.
I can capture traffic with tcpdump, which proves that it's connecting to the correct place and attempting to negotiate. The session ends with the client sending an HTTPS error "Certificate Unknown (46)".
Normally this is caused by bad certificates or configuration. But I know that my certificates are all valid. Other browsers work fine connecting to the same server to load normal web pages. And the iOS version of the same app also works fine. Browsing to the web site on an Android phone works fine even when the app is failing to connect. The website is https://zaomengshe.com so you can check the certificate there. I also have a different setup with a load balancer and a certificate from Let's Encrypt.
I guess there is some peculiarity of Aliyun's load balancers and Android that's preventing a successful negotiation. Perhaps I need to enable support for some algorithm or key size or something. I did read that TLS 1.2 wasn't supported until API version 20, so I updated the minimum supported version to 20. That didn't help.
The report by SSLLabs for this domain clearly says:
This server's certificate chain is incomplete. Grade capped to B.
The reason for this problem is probably a messed up configuration at the load balancer: only the leaf certificate is served inside the TLS handshake but not the intermediate certificates needed to build the trust chain. Desktop browser usually try to work around such broken configurations but other applications usually don't.
This means that this is very likely the reason your application fails. And the issue need to be fixed at the load balancer by also configuring the intermediate certificates.
I created an app via cordova/PhoneGap is loaded and running successfully on PlayStore.
This app performs call in Ajax in https (with certificate).
A short time ago I renewed this certificate for my domain and from that moment the app stopped working.
I read this: https://developer.android.com/training/articles/security-ssl.html#Blacklisting
That Android can block my calls? I ended up in the blacklist? How do I check this?
NOTE: The same app for the iPhone has remained functional. For this reason I think it is the only cause.
The SSL Labs Server Test indicates that the server is sending an incomplete certificate chain for this domain. You can use What's My Chain Cert? to obtain the correct chain that needs to be sent by your server and Android apps should be able to validate trust.
As for why this worked in iOS and not in Android, check out this answer.
I'm developing an Android App which requests a server with https. So the server has a certificate. During development I've managed to trust all certificates to not care about that at this stage of the project.
As I'm preparing the production phase, I would like to know how do I use volley with https, by verifying the authenticity of the server. Should I import something in the App ? May someone explains me how it works ?
Please don't give me just a tutorial to follow, I've found some already but I'm facing difficulties to understand the process, some explanations would be great !
Thanks a lot !
As long as the certificate comes from a valid Certificate Authority (CA) it will work as is.
This is the same with all android https connections.
You do not need to install certificates etc on the android device.
(You should double check the CA you are using is valid on the android as there are some that may not be compatible this easily. Although the majority should be)
I have a backend server that is accessible on two ports - one with HTTP and another with HTTPS. It uses a self-signed certificate.
From my ionic/cordova hybrid app when I run using HTTP requests they all succeed. During first request I also include a basic authorization. However, the exact same requests fail when using HTTPS. For example
http://10.1.2.3:8000/hello.js <<< works like a charm
https://10.1.2.3:8100/hello.js <<<< this fails (but works in android browser after a warning page)
I wonder how to proceed. Do I need to register the self-signed certificate somewhere in config, or something else?
Thanks a lot.
I wonder if you have found your answer or not, but still want to post answer for others looking for the solution: Cordova doesn't allow https calls to Servers with untrusted ssl certificate installed on them. You can ignore this error and continue by making a small change in a cordova file.
Open “\cordova\platforms\android\CordovaLib\src\org\apache\cordova\ CordovaWebViewClient.java”. In 'onReceivedSslError' method, comment the else part and add handler.proceed() instead.