It’s just plain hard to get true, real-time visibility into a running auth flow.

Parts of the process can be completely hidden from us; if the complete authorization process requires a redirect from a remote OAuth production server, then every debugging effort must go through the production server.

It’s practically unfeasible to debug this locally. There’s no way to reproduce the exact state and no way to inspect what is actually happening under the hood. Not ideal.

Knowing these types of challenges, we built Lightrun - a real-time production debugging tool - to allow you to understand complicated flows with code-level information. Add logs, take snapshots (virtual breakpoints), and instrument metrics without a remote debugger, without stopping the running service, and, most importantly - in real-time and without side effects.

Learn more with this 5-minute tutorial focused on debugging these kinds of scenarios using Lightrun:

>> Debugging Authentication and Authorization Using Lightrun

1. Overview

In this tutorial, we'll explain what a trust anchor is. Additionally, we'll show the default location of a TrustStore and the expected file format. Finally, we'll clarify the reasons for an error: “java.security.InvalidAlgorithmParameterException: trust anchors parameter must be non-empty”.

2. Trust Anchor Definition

Let's first explain what the trust anchor is. In cryptographic systems, a trust anchor defines the root entity for which trust is assumed and derived. In architectures like X.509, a root certificate is a trust anchor. Additionally, the root certificate guarantees trust for all other certificates in the chain.

3. TrustStore Location and Format

Let's now have a look at a TrustStore location and format in Java. First, Java looks for the TrustStore in two locations (in order):

  • $JAVA_HOME/lib/security/jssecacerts
  • $JAVA_HOME/lib/security/cacerts

We can overwrite the default location with the parameter -Djavax.net.ssl.trustStore.

Additionally, the parameter -Djavax.net.ssl.trustStorePassword allows us to provide a password to the TrustStore. Finally, the command looks like this:

java -Djavax.net.ssl.trustStore=/some/loc/on/server/ our_truststore.jks -Djavax.net.ssl.trustStorePassword=our_password -jar application.jar

Moreover, JKS is the default TrustStore format. The parameter -Djavax.net.ssl.trustStoreType allows overwriting the default TrustStore type.

Let's have a look at the output from the keytool utility in Java 16 executed for $JAVA_HOME/lib/security/cacerts:

$ keytool -list -cacerts
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 90 entries
....

As expected, the KeyStore type is JKS. Additionally, we got all 90 certificates stored in the file.

4. Reasons for the Exception

Let's now have a look at the exception “java.security.InvalidAlgorithmParameterException: trustAnchors parameter must be non-empty”.

First, the Java runtime creates the InvalidAlgorithmParameterException only in the PKIXParameters class, which is used for reading certificates from a KeyStore. The constructor of PKIXParameters collects trustAnchors from the KeyStore given as a parameter.

The exception is thrown when the provided KeyStore has no trustAnchors:

...
if (trustAnchors.isEmpty()) {
    throw new InvalidAlgorithmParameterException("the trustAnchors " +
        "parameter must be non-empty");
}
...

Let's try to reproduce the case. First, let's create an empty KeyStore:

private KeyStore getKeyStore() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException {
    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null, "changeIt".toCharArray());
    return ks;
}

Let's now test the instantiation of the PKIXParameters class:

@Test
public void whenOpeningTrustStore_thenExceptionIsThrown() throws Exception {
    KeyStore keyStore = getKeyStore();
    InvalidAlgorithmParameterException invalidAlgorithmParameterException =
      Assertions.assertThrows(InvalidAlgorithmParameterException.class, () -> new PKIXParameters(keyStore));
    Assertions.assertEquals("the trustAnchors parameter must be non-empty", invalidAlgorithmParameterException.getMessage());
}

That is to say, the constructor threw the exception as expected. In other words, it's not possible to create an instance of the PKIXParameters class when there are no trusted certificates in the given KeyStore.

5. Conclusion

In this short article, we described what a trust anchor is. Then, we showed a default TrustStore location and file format. Finally, we showed the reasons for the “trust anchors parameter must be non-empty” error.

As always, the source code of the example is available over on GitHub.

Security bottom

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security 5:

>> CHECK OUT THE COURSE
Security footer banner
Comments are closed on this article!