I am trying to Authenticate in discogs:
https://www.discogs.com/developers/#page:authentication,header:authentication-oauth-flow
on the Point 2: SEND A GET REQUEST TO THE DISCOGS REQUEST TOKEN URL, I get this:
oauth_token=tnMYYwCBsvoecGyBsANXyVKQtICTdDnnzRPeGUfa oauth_token_secret=xwHpnTRYNJIpdkkTJLMsfXECdHgXeQUrDjzmktPw oauth_callback_confirmed=true
on the POINT 3: REDIRECT YOUR USER TO THE DISCOGS AUTHORIZE PAGE,
I’ve created this piece of code:
private static void redirectUserToAuthorizePage(String consumerKey) throws IOException { String yourUrl = "https://discogs.com/oauth/authorize?oauth_token=" + consumerKey; URL url = new URL(yourUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoOutput(true); conn.setRequestMethod("GET"); int statusCode = conn.getResponseCode(); System.out.println("Status Code: " + statusCode); conn.disconnect(); }
But I got this error:
but I get this error:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
Advertisement
Answer
The error provided indicates that your application is unable to establish a SSL secure communication with the remote server, discogs.com
, because it is unable to find a valid certificate for that server among the ones configured to trust.
Under the hood, HttpURLConnection
will use Java Secure Socket Extension for establishing secure SSL communications.
In order to solve the problem you have several options, mainly:
- Run your application with the
javax.net.ssl.trustStore
andjavax.net.ssl.trustStorePassword
system properties pointing to a keystore and respectively password that contains your server certificates. - Include the server certificate in a trusted, default, keystore, one of:
<java-home>/lib/security/jssecacerts
<java-home>/lib/security/cacerts
No matter the chosen mechanism, be sure that the desired keystore contains all the necessary certificates to trust the remote server, not only the SSL certificate itself, but all the certificates in the certificate chain.
openssl
provides an useful command that allows you to obtain all the certificates used in the SSL connection. In this case, it will provide the following information, among other:
depth=0 O = Acme Co, CN = Kubernetes Ingress Controller Fake Certificate verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 O = Acme Co, CN = Kubernetes Ingress Controller Fake Certificate verify error:num=21:unable to verify the first certificate verify return:1 --- Certificate chain 0 s:/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate i:/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate -----BEGIN CERTIFICATE----- MIIDcDCCAligAwIBAgIRALyiewLACTbxSO/mUgPt2z8wDQYJKoZIhvcNAQELBQAw SzEQMA4GA1UEChMHQWNtZSBDbzE3MDUGA1UEAxMuS3ViZXJuZXRlcyBJbmdyZXNz IENvbnRyb2xsZXIgRmFrZSBDZXJ0aWZpY2F0ZTAeFw0yMTAzMTYyMjQ5MDVaFw0y MjAzMTYyMjQ5MDVaMEsxEDAOBgNVBAoTB0FjbWUgQ28xNzA1BgNVBAMTLkt1YmVy bmV0ZXMgSW5ncmVzcyBDb250cm9sbGVyIEZha2UgQ2VydGlmaWNhdGUwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxBj7SvSJpus5+2s4HLhheJhmKEmcV MTFIVf3xRDfGpVFeYKAc/o8oB3/OXrqr16kuv2g+bE2d59qVri1uTXX/CRHM6G0E St/gEdUsGiO1e3VueYGkdgr//s7idEMD0tBHp9ITiR0XUFK75YdWCT6H24fetNzp bOSMImEeSQsRexKqwcCvM6l4rNshJQ1BVD7NOYPBO9BJuEKU0wCd8yDF20Ig6Qwh D8B6kRIfNIR1jaQbXGwsvowx4ZHtE4ETd5ftPvKFLfjTMRNFOenJMOeA9te3f2vA f4jm8furOytI7+sQhZqstxbwPV9OI96rilq4P+ZjP3CW9bfubdyE8ccHAgMBAAGj TzBNMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMB Af8EAjAAMBgGA1UdEQQRMA+CDWluZ3Jlc3MubG9jYWwwDQYJKoZIhvcNAQELBQAD ggEBADFd9W49IsGKTm6WBSsSPLuKn1NFlQmfuRljcZyB01seN7N8fvX4OG/fD+/A g1nogwDbTl3g1AAyiU6iCKerZevolS2akLdbKwxg/olFRjgwdTN5668Dbz4o3MVY 21AJJ9qO14Oxdu5x+3VhMnsuQdcOzdpwVPmNWIOGQMPD+sOZ8d1hqFp6+3gFQpIL 4kEs2RhjZqwySYoQmBnURx8kbyrs3s/sH06v+CzJwVomf7amOaywJ/VuxmkF9JPp pxxmlHfbSzlWZGRC4K0ij1+91r6EALVUGgonQGY3FsN2+JTTfg8J9FGqvjb7F+BO PMPqU/pmCW5h8ej8eyNflagzLFE= -----END CERTIFICATE----- --- Server certificate subject=/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate issuer=/O=Acme Co/CN=Kubernetes Ingress Controller Fake Certificate ---
In this case, it seems that the server is using a self-signed certificate to identify itself. You new to configure Java to trust that certificate.
Copy and paste the certificate text outputted in the command, including —–BEGIN CERTIFICATE—–
and —–END CERTIFICATE—–
, and save to a new file, discogs.pem
, for example.
In order to be imported in a Java keystore, it should be converted to DER format first. You can do that with openssl
as well:
openssl x509 -outform der -in discogs.pem -out discogs.der
Then, import the certificate in a keystore. As indicated, you can import it in the default JVM kystore, or in a new one. Let’s consider the later case and create a new keystore named, for example, discogs
:
keytool -import -keystore discogs -file discogs.der
Provide a password of your convenience, let’s assume changeme
for example.
Now, run the application with the above-mentioned system properties:
java -Djavax.net.ssl.trustStore=discogs -Djavax.net.ssl.trustStorePassword=changeme your.Application
If necessary, in order to troubleshoot the problem, you can use the javax.net.debug
system property with an appropriate value, all
or ssl
:
java -Djavax.net.debug=ssl -Djavax.net.ssl.trustStore=discogs -Djavax.net.ssl.trustStorePassword=password your.Application
Please, consider review this related SO question, it may be of help.