tls-alpn-01 Challenge

With the tls-alpn-01 challenge, you prove to the CA that you are able to control the web server of the domain to be authorized, by letting it respond to a request with a specific self-signed cert utilizing the ALPN extension. This challenge is specified in RFC 8737.

TlsAlpn01Challenge provides a byte array called acmeValidation:

TlsAlpn01Challenge challenge = auth.findChallenge(TlsAlpn01Challenge.class);
Identifier identifier = auth.getIdentifier();

byte[] acmeValidation = challenge.getAcmeValidation();

You need to create a self-signed certificate with the domain to be validated set as the only Subject Alternative Name. The acmeValidation must be set as DER encoded OCTET STRING extension with the object id It is required to set this extension as critical.

After that, configure your web server so it will use this certificate on an incoming TLS request having the SNI identifier and the ALPN protocol acme-tls/1.

The TlsAlpn01Challenge class does not generate a self-signed certificate for you, as it would require Bouncy Castle. However, there is a utility method in the acme4j-utils module for this use case:

KeyPair certKeyPair = KeyPairUtils.createKeyPair(2048);

X509Certificate cert = CertificateUtils.
    createTlsAlpn01Certificate(certKeyPair, identifier, acmeValidation);

Now use cert and certKeyPair to let your web server respond to TLS requests containing an ALPN extension with the value acme-tls/1 and a SNI extension containing your subject (identifier).


The request is sent to port 443 only. If your domain has multiple IP addresses, the CA randomly selects some of them. There is no way to choose a different port or a fixed IP address.

Your server should be able to handle multiple requests to the challenge. The ACME server may check your response multiple times, and from different IPs. Also keep your response available until the Authorization status has changed to VALID or INVALID.