-
-
Notifications
You must be signed in to change notification settings - Fork 14
Capacitor Plugin for HTTP requests with self signed SSL certificates
Aymeric edited this page Oct 30, 2021
·
2 revisions
I'm using CapacitorJS for easy development with Android. I needed a way to do an HTTPS request to a box that uses self-signed SSL certificate. To accomplish it, I created my own capacitor plugin.
First, we need okhttp. To install it, open your build.gradle
file in Android Studio, and in the dependencies section we add the below:
dependencies {
[…other implementation…]
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.okhttp3:okhttp-tls:4.9.2'
implementation 'com.google.code.gson:gson:2.8.8'
}
Then, in the project structure, below java/path.to.your.project/
we create a file called HttpClientPlugin.java
with the below content:
package path.to.your.project;
import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
import java.io.IOException;
import java.security.cert.X509Certificate;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.tls.Certificates;
import okhttp3.tls.HandshakeCertificates;
// source: https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java
@CapacitorPlugin(name = "HttpClient")
public class HttpClientPlugin extends Plugin {
final X509Certificate freeboxCertificateAuthority = Certificates.decodeCertificatePem(""
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIFmjCCA4KgAwIBAgIJAKLyz15lYOrYMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV\n"
+ "BAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAMBgNVBAcMBVBhcmlzMRAwDgYDVQQK\n"
+ "DAdGcmVlYm94MRgwFgYDVQQDDA9GcmVlYm94IFJvb3QgQ0EwHhcNMTUwNzMwMTUw\n"
+ "OTIwWhcNMzUwNzI1MTUwOTIwWjBaMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGRnJh\n"
+ "bmNlMQ4wDAYDVQQHDAVQYXJpczEQMA4GA1UECgwHRnJlZWJveDEYMBYGA1UEAwwP\n"
+ "RnJlZWJveCBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\n"
+ "xqYIvq8538SH6BJ99jDlOPoyDBrlwKEp879oYplicTC2/p0X66R/ft0en1uSQadC\n"
+ "sL/JTyfgyJAgI1Dq2Y5EYVT/7G6GBtVH6Bxa713mM+I/v0JlTGFalgMqamMuIRDQ\n"
+ "tdyvqEIs8DcfGB/1l2A8UhKOFbHQsMcigxOe9ZodMhtVNn0mUyG+9Zgu1e/YMhsS\n"
+ "iG4Kqap6TGtk80yruS1mMWVSgLOq9F5BGD4rlNlWLo0C3R10mFCpqvsFU+g4kYoA\n"
+ "dTxaIpi1pgng3CGLE0FXgwstJz8RBaZObYEslEYKDzmer5zrU1pVHiwkjsgwbnuy\n"
+ "WtM1Xry3Jxc7N/i1rxFmN/4l/Tcb1F7x4yVZmrzbQVptKSmyTEvPvpzqzdxVWuYi\n"
+ "qIFSe/njl8dX9v5hjbMo4CeLuXIRE4nSq2A7GBm4j9Zb6/l2WIBpnCKtwUVlroKw\n"
+ "NBgB6zHg5WI9nWGuy3ozpP4zyxqXhaTgrQcDDIG/SQS1GOXKGdkCcSa+VkJ0jTf5\n"
+ "od7PxBn9/TuN0yYdgQK3YDjD9F9+CLp8QZK1bnPdVGywPfL1iztngF9J6JohTyL/\n"
+ "VMvpWfS/X6R4Y3p8/eSio4BNuPvm9r0xp6IMpW92V8SYL0N6TQQxzZYgkLV7TbQI\n"
+ "Hw6v64yMbbF0YS9VjS0sFpZcFERVQiodRu7nYNC1jy8CAwEAAaNjMGEwHQYDVR0O\n"
+ "BBYEFD2erMkECujilR0BuER09FdsYIebMB8GA1UdIwQYMBaAFD2erMkECujilR0B\n"
+ "uER09FdsYIebMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqG\n"
+ "SIb3DQEBCwUAA4ICAQAZ2Nx8mWIWckNY8X2t/ymmCbcKxGw8Hn3BfTDcUWQ7GLRf\n"
+ "MGzTqxGSLBQ5tENaclbtTpNrqPv2k6LY0VjfrKoTSS8JfXkm6+FUtyXpsGK8MrLL\n"
+ "hZ/YdADTfbbWOjjD0VaPUoglvo2N4n7rOuRxVYIij11fL/wl3OUZ7GHLgL3qXSz0\n"
+ "+RGW+1oZo8HQ7pb6RwLfv42Gf+2gyNBckM7VVh9R19UkLCsHFqhFBbUmqwJgNA2/\n"
+ "3twgV6Y26qlyHXXODUfV3arLCwFoNB+IIrde1E/JoOry9oKvF8DZTo/Qm6o2KsdZ\n"
+ "dxs/YcIUsCvKX8WCKtH6la/kFCUcXIb8f1u+Y4pjj3PBmKI/1+Rs9GqB0kt1otyx\n"
+ "Q6bqxqBSgsrkuhCfRxwjbfBgmXjIZ/a4muY5uMI0gbl9zbMFEJHDojhH6TUB5qd0\n"
+ "JJlI61gldaT5Ci1aLbvVcJtdeGhElf7pOE9JrXINpP3NOJJaUSueAvxyj/WWoo0v\n"
+ "4KO7njox8F6jCHALNDLdTsX0FTGmUZ/s/QfJry3VNwyjCyWDy1ra4KWoqt6U7SzM\n"
+ "d5jENIZChM8TnDXJzqc+mu00cI3icn9bV9flYCXLTIsprB21wVSMh0XeBGylKxeB\n"
+ "S27oDfFq04XSox7JM9HdTt2hLK96x1T7FpFrBTnALzb7vHv9MhXqAT90fPR/8A==\n"
+ "-----END CERTIFICATE-----");
// Only the "Intermediate CA" certificate worked… It's defined below
// To get it, open the website in Chrome
// then click to the "lock" icon to see certificates details
// then in "Certificates", go to "Certificate Path"
// then export to Base64 .cer
final X509Certificate freeboxIntermediateCertificateAuthority = Certificates.decodeCertificatePem(""
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIICTjCCAdOgAwIBAgICEzcwCgYIKoZIzj0EAwIwYTELMAkGA1UEBhMCRlIxDzAN\n"
+ "BgNVBAgMBkZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxEzARBgNVBAoMCkZyZWVib3gg\n"
+ "U0ExHDAaBgNVBAMME0ZyZWVib3ggRUNDIFJvb3QgQ0EwHhcNMTUwOTAxMTgwODI3\n"
+ "WhcNMjUwODI5MTgwODI3WjBZMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGRnJhbmNl\n"
+ "MRMwEQYDVQQKDApGcmVlYm94IFNBMSQwIgYDVQQDDBtGcmVlYm94IEVDQyBJbnRl\n"
+ "cm1lZGlhdGUgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASZh/Apn56RulcNKDqV\n"
+ "gVqTDusvVQK9kIgJD39MzpnbsxMWv16RKs5JXGNb21z5QsmDnKcjZt9TE+BPh4l0\n"
+ "KDmMtAL5q+I/r0lFuJE7JohWN47rPWb7hOl2N9RDY+6HqQyjZjBkMB0GA1UdDgQW\n"
+ "BBT6m56/7eLixv5eBCT7XHDeHaItXTAfBgNVHSMEGDAWgBTIB3c2GlbV6EIh2ErE\n"
+ "MJvFxMz/QTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAKBggq\n"
+ "hkjOPQQDAgNpADBmAjEA50+k9U6+hCSgpX53vBiiaZosuqViMTMB03VDsclTfDh7\n"
+ "PzhplpUmHnXp6G4FQfHqAjEAyJQABAn6zMxFbqrIjEFl8hR+BfbMXwtI0vcrlSzo\n"
+ "SOza2d0EaD2163o50tkZm4g6\n"
+ "-----END CERTIFICATE-----");
private final OkHttpClient client;
public HttpClientPlugin() {
HandshakeCertificates certificates = new HandshakeCertificates.Builder()
.addTrustedCertificate(freeboxCertificateAuthority)
.addTrustedCertificate(freeboxIntermediateCertificateAuthority)
.addPlatformTrustedCertificates() // to allow all the other regular certificates
.build();
client = new OkHttpClient.Builder()
.sslSocketFactory(certificates.sslSocketFactory(), certificates.trustManager())
.build();
}
@PluginMethod()
public void get(PluginCall call) {
String url = call.getString("url");
JSObject ret = new JSObject();
ret.put("body", "ERROR");
ret.put("code", 0);
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
String body = response.body().string();
//System.out.println("[FREEBOX] "+ body);
int responseCode = response.code();
ret.put("body", body);
ret.put("code", responseCode);
} catch(IOException err) {
System.out.println("[FREEBOX] "+ err);
ret.put("body", err);
}
call.resolve(ret);
}
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
@PluginMethod()
public void post(PluginCall call) {
String url = call.getString("url");
JSObject jsonData = call.getObject("data");
RequestBody postBody = RequestBody.Companion.create(jsonData.toString(), JSON);
JSObject ret = new JSObject();
ret.put("body", "ERROR");
ret.put("code", 0);
Request request = new Request.Builder()
.url(url)
.post(postBody)
.build();
try (Response response = client.newCall(request).execute()) {
String body = response.body().string();
int responseCode = response.code();
//System.out.println("[FREEBOX] Code "+ responseCode);
ret.put("body", body);
ret.put("code", responseCode);
} catch(IOException err) {
System.out.println("[FREEBOX] "+ err);
ret.put("body", err);
}
call.resolve(ret);
}
}
Register the plugin in MainActivity.java
(see the documentation).
In our JavaScript web app, we create a file called HttpClient.js
:
import { registerPlugin } from '@capacitor/core';
const HttpClient = registerPlugin('HttpClient');
export default HttpClient;
We can finally call it in our main JavaScript web app:
import HttpClient from './components/HttpClient.js'
[…]
// GET Request
let { body, code } = await HttpClient.get({ url: 'https://web.site' });
body = JSON.parse(body);
// POST request
let { body, code } = await HttpClient.post({ url: 'https://web.site', data:{hello:'world'}});
body = JSON.parse(body);