 Java, Spring and Web Development tutorials  1. Introduction
In this article, we’ll take a look at using REST Assured to make HTTPS calls to HTTPS server URLs. In particular, we’ll see how to write tests when our system doesn’t trust the server’s SSL certificate. For example, because it’s a self-signed certificate.
2. Failing tests with untrusted SSL certificates
We can use REST Assured to make calls to our server as follows:
given()
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
When we’re testing a non-HTTPS URL or a URL with a valid SSL certificate, a test like this will work perfectly fine.
However, if we’re testing an HTTPS URL that has an untrusted SSL certificate, REST Assured will throw an exception:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:130)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:378)
... 57 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:388)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:271)
... 123 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:148)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:129)
... 126 more
In many cases, this is desirable behaviour. If we’re running tests against a website with a bad SSL certificate, we normally want the test to fail.
However, in some cases, we need to be able to test such sites. For example, we might be testing a pre-release version of our application that doesn’t have a valid certificate yet.
3. Relaxed HTTPS Validation
The easiest way to solve this issue is to enable relaxed HTTPS validation on our test calls. We can do this by including the call relaxedHTTPSValidation() in our call chain:
given()
.relaxedHTTPSValidation()
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
This is a shorthand for providing SSL config that has relaxed validation enabled:
given()
.config(config().sslConfig(sslConfig().relaxedHTTPSValidation()))
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
This is very simple and may well be all that we need. However, we need to be aware that this will accept any SSL certificate for our call, regardless of the reason it’s invalid. This includes if it’s untrusted, but also things such as if it’s expired or even if it’s defined for the wrong domain. It will also accept any SSL certificate for any website, not just the one that we’re interested in.
4. Trusting Certificates
Instead of configuring our client to just accept any SSL certificate, the alternative is to provide the actual SSL certificate for our website. This will allow us to trust the certificate, but without the extra baggage that comes with it – trusting other certificates too, and accepting certificates that are otherwise invalid.
4.1. Creating a Truststore
The first thing we need to do is create a Java Truststore containing the appropriate certificate.
We first need to get a copy of the certificate. We can download this directly from the server using the openssl command-line tool:
$ echo -n | openssl s_client -connect self-signed.badssl.com:443
The output of this will include, amongst a lot of other details, the actual certificate. We can find this between “—–BEGIN CERTIFICATE—–” and “—–END CERTIFICATE—–” lines:
-----BEGIN CERTIFICATE-----
MIIDeTCCAmGgAwIBAgIJAPUiQDKMrnL3MA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV
BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp
c2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTAeFw0y
NTA5MDkyMTAwMjZaFw0yNzA5MDkyMTAwMjZaMGIxCzAJBgNVBAYTAlVTMRMwEQYD
VQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQK
DAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2
PmzAS2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMW
hyefdOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3A
xPxTuW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqve
ww9HdFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SY
QCeFxxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaMyMDAwCQYDVR0T
BAIwADAjBgNVHREEHDAaggwqLmJhZHNzbC5jb22CCmJhZHNzbC5jb20wDQYJKoZI
hvcNAQELBQADggEBACWqo3kJfTMrXjn0w3eUDDUbx18hcvKFGgqkB3V3wnghNJov
WKVaSgkLvWoiDATFZrPIo20cKQ+f0tAMmOvQLo4X5LEPvW+rRJXOLGVPrxlN8Rqc
sOC1oVCATFcXLEHkA0hKdeeh4+GtKavnmYFJuG2OuSW4F1QPLJzFTagn5P1UftR8
ARpYqWhQhncPY+sh2R8Bg+Mqxc+Iu8LlNzUc2P4ZqcmTEhClr9nKzz7ZJGmI61o2
BrX810+j3oZ28VlLvh5TxbD58wkCpF6EW1A+xPZhMoTmRWGvYijTfj6EeiZNg7/N
r42vdJjW11p8FXlJEaIkczUjdxiJsfmZAVqIe5Y=
-----END CERTIFICATE-----
We then need to write this into a file – for example, badssl.crt. Once we’ve done that, we can create a Java keystore from it:
$ keytool -import -trustcacerts -keystore badssl.jks -storepass changeit -noprompt -alias badssl -file badssl.crt
Certificate was added to keystore
This creates a file called badssl.jks with a password of changeit, in which we’ve stored the certificate found in badssl.crt.
Once we’ve done this, we should then verify the keystore to make sure it’s correct:
$ keytool -list -v -keystore badssl.jks -storepass changeit
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: badssl
Creation date: 12 Sept 2025
Entry type: trustedCertEntry
Owner: CN=*.badssl.com, O=BadSSL, L=San Francisco, ST=California, C=US
Issuer: CN=*.badssl.com, O=BadSSL, L=San Francisco, ST=California, C=US
Serial number: f52240328cae72f7
Valid from: Tue Sep 09 22:00:26 BST 2025 until: Thu Sep 09 22:00:26 BST 2027
Certificate fingerprints:
SHA1: 9C:F3:00:1D:37:04:A9:3D:94:0E:24:0D:72:72:4E:F6:1B:D8:86:2E
SHA256: CE:1F:57:5F:E6:4E:D2:D5:18:8B:B4:05:DD:D8:AE:E1:1A:00:18:35:FD:F5:1A:3C:6F:54:CC:43:65:96:C9:54
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
At this point, we’re ready to use the certificate in our tests.
4.2. Using the Truststore Per Request
We can configure REST Assured to use our truststore for a single request. We do this in a very similar way to how we enabled relaxed HTTPS validation. We provide an SSL config which knows about the truststore:
given()
.config(config().sslConfig(sslConfig().trustStore("/badssl.jks", "changeit")))
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
Our badssl.jks file needs to be in the appropriate place on the classpath, and changeit is the store password that we defined earlier.
At this point, our test will pass correctly for any certificates in this truststore, but reject any others that are invalid.
4.3. Using the Truststore Globally
Instead of configuring the truststore on each individual request, we can configure REST Assured to globally support our truststore:
RestAssured.config = RestAssured.config().sslConfig(SSLConfig.sslConfig().trustStore("/badssl.jks", "changeit"));
This is the exact same configuration that we used before, but we’re updating the global configuration instead of specifying it on the single request. From this point on, all requests that we make will know about this truststore, and therefore will trust this SSL certificate:
given()
.baseUri("https://self-signed.badssl.com")
.when()
.get("/")
.then()
.statusCode(200);
Here we’re doing nothing specific to trust the SSL certificate, but this time the test will pass. This is because the global configuration already knows about our truststore, and so the system trusts this certificate on every REST Assured call we make.
5. Summary
In this article, we looked at how to configure REST Assured to accept untrusted SSL certificates. This allows us to test websites that might be using self-signed or otherwise invalid certificates. Next time you need to test websites like this, why not give it a go?
As usual, all of the examples from this article are available over on GitHub. The post Making HTTPS Calls to Untrusted SSL Servers With REST Assured first appeared on Baeldung.
Content mobilized by FeedBlitz RSS Services, the premium FeedBurner alternative. |