mahmoudOmar
New Contributor

Problem With 2 Way SSL

when used postman for HelloWorld API get 

{
"timestamp": "2021-07-22T13:15:47",
"message": "helloworld"
}
 
but when used it's inside java code get 

{"responseStatus":{"status":400,"code":"9123","severity":"ERROR","message":"Expected input credential was not present","info":""}}

 

I flow the steps - create a new project with my own CSR and insert root & project & CA into keystore 

 

and using code as below 

 

@GetMapping("/HelloWorld")
public String helloworld() throws IOException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

String PRIVATE_KEY_PASSWORD = "test";
String KEY_STORE_PASSWORD = "test";
String KEY_STORE_PATH = "/Users/mahmoud/Certificate/New Project/keyStore";
String user = "Userid";
String password = "password";

try {
// Load client certificate into key store
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(new File(KEY_STORE_PATH), KEY_STORE_PASSWORD.toCharArray(),
PRIVATE_KEY_PASSWORD.toCharArray())
.loadTrustMaterial(new File(KEY_STORE_PATH), KEY_STORE_PASSWORD.toCharArray())
.build();


CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials( user, password );
provider.setCredentials( AuthScope.ANY, credentials );
// Allow TLSv1.2 protocol only
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

CloseableHttpClient httpClient = HttpClientBuilder.create()//.setDefaultCredentialsProvider(provider)
.setSSLSocketFactory(sslSocketFactory).build();


System.out.println("-------------->xx");


HttpGet httpGet = new HttpGet("https://sandbox.api.visa.com/vdp/helloworld");





String credential = Base64.getEncoder().encodeToString((user + ":" + password).getBytes("UTF-8"));
httpGet.setHeader("Authorization", "Basic " + credential.substring(0, credential.length()-1));
httpGet.setHeader("Accept", "*/*");

System.out.println("------->"+httpGet.getMethod());

Header[] hM = httpGet.getAllHeaders();
for (Header header : hM) {
System.out.println("----->"+header.getName()+"------>"+header.getValue());

}


CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
System.out.println("GET Response Status:: "
+ httpResponse.getStatusLine().getStatusCode());

BufferedReader reader = new BufferedReader(new InputStreamReader(
httpResponse.getEntity().getContent()));

String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = reader.readLine()) != null) {
response.append(inputLine);
}
reader.close();

// print result
System.out.println(response.toString());
httpClient.close();


} catch (Exception e) {
e.printStackTrace();
}


System.out.println("Hello World");
return "Hello World";
}
MahmoudOmar
7 REPLIES 7
SLi
Visa Dev Moderator
Visa Dev Moderator

Re: Problem With 2 Way SSL

Hi @mahmoudOmar,

 

Please refer to the below link for step by step instructions on how to run Java Sample Code using the Hello World API and Mutual SSL.

https://community.developer.visa.com/t5/Tutorials/HelloWorld-java-How-to-run-Java-Sample-Code-using-...

 

If you are still facing error, please share following to help troubleshoot further.
1. Endpoint
2. Request Header
3. Request Body
4. Response Body
5. X-Correlation-ID from response header.

 


Best,
Stacey

Was your question answered? Don't forget to click on "Accept as Solution" to help other devs find the answer to the same question.
mahmoudOmar
New Contributor

Re: Problem With 2 Way SSL

Hi Thanks for the advice but I flow the steps with the same problem

Screen Shot 2021-07-23 at 10.39.37 AM.png

package eg.com.khales.testvisa.controller;


import org.apache.http.Header;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.Enumeration;

import static org.apache.http.HttpHeaders.*;
import static org.springframework.http.HttpHeaders.encodeBasicAuth;


@RestController
@RequestMapping("/TestVisaApi")
public class TestVisaApi {


@GetMapping("/HelloWorld")
public String helloworld() throws IOException, UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {

String PRIVATE_KEY_PASSWORD = "test";
String KEY_STORE_PASSWORD = "test";
String KEY_STORE_PATH = "/Users/mahmoud/Certificate/New Project2/keyStore.jks";
String user = "OEMCDKWLTCFWU8647IQ421h-adQpq9PTCFr_nK_uJzr-wjnVA";
String password = "LcVLjcZY7tDTFsPn4gwqC8UsYYNBHG7r";

try {
// Load client certificate into key store
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(new File(KEY_STORE_PATH), KEY_STORE_PASSWORD.toCharArray(),
PRIVATE_KEY_PASSWORD.toCharArray())
.loadTrustMaterial(new File(KEY_STORE_PATH), KEY_STORE_PASSWORD.toCharArray())
.build();


CredentialsProvider provider = new BasicCredentialsProvider();
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials( user, password );
provider.setCredentials( AuthScope.ANY, credentials );
// Allow TLSv1.2 protocol only
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

CloseableHttpClient httpClient = HttpClientBuilder.create()//.setDefaultCredentialsProvider(provider)
.setSSLSocketFactory(sslSocketFactory).build();


System.out.println("-------------->xx");


HttpGet httpGet = new HttpGet("https://sandbox.api.visa.com/vdp/helloworld");





String credential = Base64.getEncoder().encodeToString((user + ":" + password).getBytes("UTF-8"));
httpGet.setHeader("Authorization", "Basic " + credential.substring(0, credential.length()-1));
httpGet.setHeader("Accept", "*/*");

System.out.println("------->"+httpGet.getMethod());

Header[] hM = httpGet.getAllHeaders();
for (Header header : hM) {
System.out.println("----->"+header.getName()+"------>"+header.getValue());

}


CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
System.out.println("GET Response Status:: "
+ httpResponse.getStatusLine().getStatusCode());

BufferedReader reader = new BufferedReader(new InputStreamReader(
httpResponse.getEntity().getContent()));

String inputLine;
StringBuffer response = new StringBuffer();

while ((inputLine = reader.readLine()) != null) {
response.append(inputLine);
}
reader.close();

// print result
System.out.println(response.toString());
httpClient.close();


} catch (Exception e) {
e.printStackTrace();
}


System.out.println("Hello World");
return "Hello World";
}


@GetMapping("/H1")
public void hellowWorld1() throws Exception {


String KEY_STORE_PATH = "/Users/mahmoud/Certificate/New Project2/keyStore.jks";
String user = "OEMCDKWLTCFWU8647IQ421h-adQpq9PTCFr_nK_uJzr-wjnVA";
String password = "LcVLjcZY7tDTFsPn4gwqC8UsYYNBHG7r";

System.out.println("START Sample Code for Two-Way (Mutual) SSL");
URL url = new URL("https://sandbox.api.visa.com/vdp/helloworld");

HttpURLConnection con = (HttpURLConnection) url.openConnection();

// THIS IS EXAMPLE ONLY how will cert and key look like
// keystorePath = "visa.jks"
// keystorePassword = "password"

String keystorePath = "/Users/mahmoud/Certificate/New Project2/keyStore.jks";
String keystorePassword = "test";
// Make a KeyStore from the PKCS-12 file
KeyStore ks = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream(keystorePath)) {
ks.load(fis, keystorePassword.toCharArray());
}

// Make a KeyManagerFactory from the KeyStore
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keystorePassword.toCharArray());

// Now make an SSL Context with our Key Manager and the default Trust Manager
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);
if (con instanceof HttpsURLConnection) {
((HttpsURLConnection) con).setSSLSocketFactory(sslContext.getSocketFactory());
}

con.setRequestMethod("GET");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");

// THIS IS EXAMPLE ONLY how will user_id and password look like
// userId = "1WM2TT4IHPXC8DQ5I3CH21n1rEBGK-Eyv_oLdzE2VZpDqRn_U";
// password = "19JRVdej9";


String auth = user + ":" + password;
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8));
String authHeaderValue = "Basic " + new String(encodedAuth);
con.setRequestProperty("Authorization", authHeaderValue);

int status = con.getResponseCode();
System.out.println("Http Status: " + status);

BufferedReader in;
if (status == 200) {
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else {
in = new BufferedReader(new InputStreamReader(con.getErrorStream()));
System.out.println("Two-Way (Mutual) SSL test failed");
}
String response;
StringBuffer content = new StringBuffer();
while ((response = in.readLine()) != null) {
content.append(response);
}
in.close();
con.disconnect();

System.out.println(content.toString());
System.out.println("END Sample Code for Two-Way (Mutual) SSL");
}









}

 

 

MahmoudOmar
SLi
Visa Dev Moderator
Visa Dev Moderator

Re: Problem With 2 Way SSL

Hi @mahmoudOmar,

 

The error "Expected input credential was not present" usually occurs when the credentials used are invalid. 

Please test the connectivity and credentials by following the Two-Way SSL (Mutual Authentication) guide:

https://developer.visa.com/pages/working-with-visa-apis/two-way-ssl

 

A few things to note:

1. Ensure Basic Authentication is sent in request header with user name and password base64 encoded and ‘Basic ‘ prefix

2. Ensure correct client certificate/private key used

 

We usually do not troubleshoot developer's code. We can help as best we can and provide some samples and testing with API clients in order to make sure the connection with VDP is working properly.

 

If you continue to get this issue, please provide us the correlation ID and we can further investigate the issue.

 


Best,
Stacey

Was your question answered? Don't forget to click on "Accept as Solution" to help other devs find the answer to the same question.
mahmoudOmar
New Contributor

Re: Problem With 2 Way SSL

Hello Sli

I think the connection works well I test with the postman and its work well that's for the first check for the second check 

 

Capture.PNG

 

When Call Same Steps from Code Get result below 

 

org.springframework.web.client.HttpClientErrorException$BadRequest: 400 : [{"responseStatus":{"status":400,"code":"9123","severity":"ERROR","message":"Expected input credential was not present","info":""}}]

 

Although it's using the same steps guide using same 

Header 'Authorization' = [Basic Vk42NVA4T1pVRloyMzhaSkpRU1AyMTBTdlpkN2hnYUk1bzJJT3oya3V2empHUzJ0YzoyZFAzWjREVjUzeTEzUjJ0MVB6Y05vT0g2b3lab3E3NmU=] 

with postman

MahmoudOmar
mahmoudOmar
New Contributor

Re: Problem With 2 Way SSL

Key: X-CORRELATION-ID Value: [1627160196_256_1576117993_l73c018_VDP_WS]

MahmoudOmar
SLi
Visa Dev Moderator
Visa Dev Moderator

Re: Problem With 2 Way SSL

Hi @mahmoudOmar,

 

Are you using the Hello World sample code that we provided for download? If not, please log in to your account, scroll down to the bottom of the page to download the zip package. It includes java sample code. Additionally, please check in the headers that "Content-Type" and "Accept" are set to "application/json".

 


Best,
Stacey

Was your question answered? Don't forget to click on "Accept as Solution" to help other devs find the answer to the same question.
mahmoudOmar
New Contributor

Re: Problem With 2 Way SSL

Hello @SLi 

Yes I mention in Comments Code which was published by Visa Using the same steps

MahmoudOmar