HTTPS request with client certificate
In Java to make an HTTPS request with a client certificate, for example to
facilitate mTLS authentication
for an OAuth client, requires the set up a custom
javax.net.ssl.SSLSocketFactory
.
Example how to do this in the SDK for mTLS with self_signed_tls_client_auth
for the OAuth 2.0 client credentials grant:
import java.net.*;
import java.security.*;
import java.security.cert.*;
import java.util.*;
import javax.net.ssl.*;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.gen.*;
import com.nimbusds.jwt.util.*;
import com.nimbusds.oauth2.sdk.*;
import com.nimbusds.oauth2.sdk.auth.*;
import com.nimbusds.oauth2.sdk.http.*;
import com.nimbusds.oauth2.sdk.id.*;
import com.nimbusds.oauth2.sdk.token.*;
import com.nimbusds.oauth2.sdk.util.*;
// Generate an RSA public / private key pair and store it securely.
// The public RSA key must be registered with the OAuth 2.0 server
// in the client's metadata
RSAKey rsaJWK = new RSAKeyGenerator(2048)
.keyIDFromThumbprint(true)
.generate();
// Generate a self-signed X.509 certificate and sign it with a private key
Date now = new Date();
Date exp = DateUtils.fromSecondsSinceEpoch(now.getTime() + 3600 * 24 * 30);
X509Certificate clientCert = X509CertificateUtils.generateSelfSigned(
new Issuer(clientInfo.getID()),
now,
exp,
rsaJWK.toRSAPublicKey(),
rsaJWK.toPrivateKey()
);
// Store the private key together with the certificate
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null); // init
ks.setKeyEntry("client-auth", rsaJWK.toPrivateKey(), new char[0], new Certificate[]{clientCert});
// Key manager factory for the SSL context
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, new char[0]);
// Trust manager factory for the SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null); // null here initialises the TMF with the default trust store.
// Create a new SSL context
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
// Some token request using mTLS self-signed client authentication
TokenRequest tokenRequest = new TokenRequest(
new URI("https://c2id.com/token"),
new SelfSignedTLSClientAuthentication(new ClientID("123"), clientCert),
new ClientCredentialsGrant(),
new Scope("read", "write")
);
// Make the HTTPS request and set the SSLSocketFactory
httpRequest = tokenRequest.toHTTPRequest();
httpRequest.setSSLSocketFactory(sslContext.getSocketFactory());
httpResponse = httpRequest.send();