In Two-Way SSL authentication, the client and server need to authenticate and validate each others identities. The authentication message exchange between client and server is called an SSL handshake, and it includes the following steps:

  • A client requests access to a protected resource.
  • The server presents its certificate to the client.
  • The client verifies the server's certificate.
  • If successful, the client sends its certificate to the server.
  • The server verifies the client’s credentials.
  • If successful, the server grants access to the protected resource requested by the client.
  • In step 5 (above), the server validates the client, which is the second part of the Two-Way SSL (Mutual Authentication) process. This is typically done by making sure that the client certificate is valid (non-expired and issued by a trusted Certificate Authority), as well as the client’s digital signature is valid. The digital signature is produced using the private key from the client. Anyone that has the public key can validate the digital signature. (However, only the client that has the private key can create a valid signature.)

    To establish a Two-Way SSL (Mutual Authentication) connection, you must have the following:

  • private key
  • client certificate
  • certificate authority root certificate, and
  • certificate authority intermediate certificates (Note: These certificates are optional for the Visa Developer sandbox)
  • The DigiCert Global Root CA certificate is available for download at https://dl.cacerts.digicert.com/DigiCertGlobalRootCA.crt .

    Once downloaded, you will need to convert the DigiCert Global Root CA certificate from Binary format to Base64 format. You can do this by using one of the following methods:

  • Double-click on the DigiCertGlobalRootCA.crt file to open it into the certificate display.
  • Select the Details tab, then select the Copy to file button.
  • Click Next on the Certificate Wizard.
  • Select Base-64 encoded X.509 (.CER) , then Next .
  • Select Browse (to locate a destination) and type in the filename DigiCertGlobalRootCA.
  • Click Save . You now have the file DigiCertGlobalRootCA.cer
  • The following sections explain how to obtain a private key, client certificate, and certificate authority root certificate. You will also learn about how to bundle the certificates into keystores, using Java keytool or OpenSSL.

    In order to obtain a valid client certificate from Visa Developer, you must submit a Certificate Signing Request (CSR). The CSR file contains client registration details (such as Organization Name and Locality ), as well as the public key from the client. The process of creating the CSR yields the CSR file itself and also a private key (which corresponds to a public key, which is encoded into the CSR file). There are multiple tools that you can use to create a CSR, such as Java keytool or OpenSSL. Both tools are available for free to download from the Internet for all major operating systems.

    Refer to one of the following sections on how to obtain a Two-Way SSL certificate.

  • Configuring a Two-Way SSL Keystore Using an Auto-generated CSR
  • Configuring Two-Way SSL Keystore Using Your Own CSR
  • Visa Developer creates the CSR file and submits the CSR to itself. The output of this process is the private key and the certificate of the client.

    Note: The auto generated CSR file is only available as an option in the Visa Developer sandbox when a project is created. For certification and production environments, you may choose to use the CSR Wizard tool that helps you create a Certificate Signing Request (CSR) for Two-Way SSL and Message Level Encryption by pre-filling most of the required fields with information from your project.

    To auto-generate the CSR:

  • On the dashboard, click on Create a New Project .
  • Specify your Project Name and Project Description , specify the APIs you are interested in using.
  • If you selected Mutual Authentication you will need to generate a CSR. Click on either Submit a Certificate Signing Request or Generate a CSR for Me.
    Visa Developer self-submits a certificate request and produces a .pem file with the private key of your certificate in it. This uses default values for Organization Name and Locality .
  • Download the private key and store it in a secure location.
  • In addition, you must download the ProjectCertificate and the Visa Developer Root Certificate (available in dashboard under Credentials -> Certificates section).
  • Note: Once you complete the project creation process, Visa Developer Platform (VDP) will provide you with the links of the certificates to download. In this case, Visa Developer provides a VDP CSR. Once you obtain the private key and the certificates, you can begin to create the key stores and start testing mutual SSL connectivity.

    The following steps include examples for context.

    Place your private key file (for example: privateKey.pem and your certificate file from VDP (for example: cert.pem in the same directory. Generate a keystore (for example: myProject_keyAndCertBundle.p12 ) file as shown below.
    Note: The myProject_keyAndCertBundle.p12 is only a placeholder file name. You may choose to name it anything else.

    OpenSSL is an open source software library that implements Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols, as well as provides basic cryptographic functions and various utilities.

    See below for a command-line utility, which is freely available for download from the Internet for all major operating systems.

    To generate a CSR and private key , run the command shown below from the command line. The command will prompt you for Country Name, State Name, Locality Name, Organization Name, Organization Unit Name, Common Name , and Email Address . For example, notice the output from the resulting files--one is the private key ( privateKey.pem ) and the other is the CSR ( certreq.csr ) .

    > openssl req -new -keyout privateKey.pem -out certreq.csr Generating a 2048 bit RSA private key Writing a new private key to ‘privatekey.pem’ Enter PEM pass phrase: <your_password> Verifying – Enter PEM pass phrase: <re-enter your password> You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called Distinguished Name or DN. For some fields there will be a default value. If you enter ‘.’, the field will be left blank Country Name (2 letter code): <country name> State or Province Name (full name):<state name> Locality Name (eg, city):<city name> Organization Name (eg, company):<organization name> Organizational Unit Name (eg, section):<department/section name> Common Name (eg, your name or your server`s hostname):<host name> Email Address []:<email address> Please enter the following 'extra' attributes to be sent with your certificate request A challenge password:. An optional company name: Description Common Name

    This field must be a fully qualified domain name and must identify the company. Format should be hostname.domainname.com. This cannot have wildcard characters for hostname and hostname should not be www.

    For example: services.company.com

    Organization Name

    Name of your organization.

    For example: Bank of USA

    Organizational Unit

    Name of your division within your organization.

    For example: Debit Card Processing Unit.

    Locality/City

    A valid city name. Spell out the name completely (do not abbreviate).

    For example: San Francisco

    State

    Name of the state or province where the server is located. Spell out the name completely (do not abbreviate).

    For example: California

    Country

    Two-letter International Standards Organization (ISO) 3166-1 country code.

    For example: US

    This should be the CSR Unique Id appended with ”-CERT” or “-PROD” to indicate the environment:

  • Certification environment: <UID>-CERT
  • Production environment: <UID>-PROD
  • To get the CSR Unique Id, go to the dashboard, select the Project Name for which you need to generate the CSR, and click on Settings.

    For Message Level Encryption (MLE) the CSR Unique Id will be the MLE KeyID.

  • MLE does not require to append “-CERT” or “-PROD” to indicate the environment the CSR is being generated for
  • CSR File Name Name of the CSR File

    Upload your CSR file to Visa Developer .
    In response, Visa Developer will create your client certificate and the Visa Developer CA Root Certificate. Download both the Visa Developer Certificate (Root CA) and certificate (client cert) to a local folder.
    Note: You should see both VDPCA-SBX.pem and cert.pem in your local folder.

    Create the PKCS12 (P12) Certificate Store Using OpenSSL .
    In order to invoke Two-Way SSL with a majority of the non-java platforms, you will need the PKCS12 keystore, which is described below. Check your SSL library documentation, as some platforms accept the key and the certificate directly. If this is the case, you can skip this step.
    Note: The PKCS12 (P12) files can be imported into the Windows keystore using the Windows certificate import utility. This action will be invoked automatically when you double-click a P12 file.

    Place your private key file (for example: privateKey.pem ) and your certificate file from VDP (for example: cert.pem ) in the same directory.

    Run the following OpenSSL command to create the P12 certificate store containing your private key and your client certificate.

    The resulting file, called myProject_keyAndCertBundle.p12 will contain both your private key and your client certificate.

    Note: The Visa Developer sandbox does not validate the VDP root CA, so you do not have to include it in your P12 keystore. However, the root certificate is required when you create your Java Key Store, because you cannot add the client certificate to the JKS file without the root certificate. During the actual SSL handshake, the VDP sandbox does not validate the root certificate, so both JKS with the root cert and P12 without the root certificate will work equally well.

    Keytool is a certificate management utility that is part of the standard Java distribution.

    If you use a JKS file as your truststore , follow the instructions below to add the DigiCert Global Root CA certificate to your truststore.

    keytool -import -alias DigiCertGlobalCA -keystore <Path to JKS (TrustStore) file> -file DigiCertGlobalRootCA.crt 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 javax.net.ssl.SSLContext; import java.io.File; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; private CloseableHttpClient createHttpClient() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException { return HttpClients.custom().setSSLSocketFactory(getSSLSocketFactory()).build(); private SSLConnectionSocketFactory getSSLSocketFactory() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException { SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(loadSSLContext(), new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); return sslSocketFactory; private SSLContext loadSSLContext() throws KeyManagementException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException { SSLContext sslcontext = SSLContexts.custom() .loadKeyMaterial(new File(VisaProperties.getProperty(Property.KEYSTORE_PATH)), VisaProperties.getProperty(Property.KEYSTORE_PASSWORD).toCharArray(), VisaProperties.getProperty(Property.PRIVATE_KEY_PASSWORD).toCharArray()) .loadTrustMaterial(new File(VisaProperties.getProperty(Property.TRUSTSTORE_PATH)), VisaProperties.getProperty(Property.TRUSTSTORE_PASSWORD).toCharArray()) .build(); return sslcontext; Description Common Name

    This field must be a fully qualified domain name and must identify the company. Format should be hostname.domainname.com. This cannot have wildcard characters for hostname and hostname should not be www.

    For example: services.company.com

    Organization Name

    Name of your organization.

    For example: Bank of USA

    Organizational Unit

    Name of your division within your organization.

    For example: Debit Card Processing Unit.

    Locality/City

    A valid city name. Spell out the name completely (do not abbreviate).

    For example: San Francisco

    State

    Name of the state or province where the server is located. Spell out the name completely (do not abbreviate).

    For example: California

    Country

    Two-letter International Standards Organization (ISO) 3166-1 country code.

    For example: US

    This should be the CSR Unique Id appended with ”-CERT” or “-PROD” to indicate the environment:

  • Certification environment: <UID>-CERT
  • Production environment: <UID>-PROD
  • To get the CSR Unique Id, go to the dashboard, select the Project Name for which you need to generate the CSR, and click on Settings.

    For Message Level Encryption (MLE) the CSR Unique Id will be the MLE KeyID.

  • MLE does not require to append “-CERT” or “-PROD” to indicate the environment the CSR is being generated for
  • CSR File Name Name of the CSR File

    Update Java Key Store with Root Certificate and Client Certificate using Java Keytool.

    To invoke an API using Two-Way SSL, you must have a client certificate and your root CA in your keystore, since your Java SSL library only accepts one input for all certificates – the keystore. Therefore, you will need to add the certificates downloaded from VDP to the keystore (for example: clientkeystore.jks ) that you generated while creating the CSR.

    Note: Replace the < password > above with the actual password that was used while creating the clientkeystore.jks .
    Click yes when prompted to trust the certificate option.

    SOAPUI is a free and open source Web Service Functional Testing solution. With an easy-to-use graphical user interface, SOAPUI allows client developer's the ability to rapidly create and execute web service API functional tests. Visa recommends that client developers use SOAPUI or a similar connectivity tool to establish initial connection to the VDP sandbox.

    In order to configure Two-Way SSL, you must create the  Certificate Signing Request (CSR) and use Visa Developer to obtain the VDP root CA and project specific certificate. The certificates and the private key need to be bundled together into a keystore (either Java Key Store or PKCS12 keystore), as described in the Configuring 2-way SSL Keystore section.

    Once the keystore file is available, follow these steps to configure SOAPUI Two-Way SSL preferences.

    Once in SOAPUI, click Project > New REST Project . Then, provide the following helloworld URI in the URI field:
    https://sandbox.api.visa.com/vdp/helloworld

    In order to configure Two-Way SSL, you need a VDP Project Certificate (cert.pem), basic authentication credentials (user name / password) from your VDP Project Dashboard, an Environment (E.g. Sandbox),  a Credentials section and the private key for your project. You can then follow these steps to configure Postman Two-Way SSL preferences.

  • Once in Postman, click Collections > New Collection .
  • Provide a name and select the Authorization tab.
  • Provide Username and Password availability from VDP for your project.
  • Click Create .
  • 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; // 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(); // Allow TLSv1.2 protocol only SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1.2" }, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(sslSocketFactory).build(); r = requests.post(url, verify = ('put the CA certificate pem file path here'), cert = ('put the client certificate pem file path here','put the private key pem file path here'), headers = headers, auth = (user_id, password), data = body)
    uri : "https://sandbox.api.visa.com/…", key: fs.readFileSync(keyFile), cert: fs.readFileSync(certificateFile), ca: fs.readFileSync(caFile) headers: { 'Content-Type' : 'application/json', 'Accept' : 'application/json', 'Authorization' : 'Basic ' + new Buffer(userId + ':' + password).toString('base64') body: data }, function(error, response, body) { :payload => $body, :user => user_id, :password => password, :ssl_client_key => OpenSSL::PKey::RSA.new(File.read(key_path)), :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read(cert_path)), :ssl_ca_file => ca_cert_path rescue RestClient::ExceptionWithResponse => e response = e.response using System.Net; using System.Security.Cryptography.X509Certificates; HttpWebRequest request = WebRequest.Create (requestURL) as HttpWebRequest; // Add headers string authString = userId + ":" + password; var authStringBytes = System.Text.Encoding.UTF8.GetBytes (authString); string authHeaderString = Convert.ToBase64String (authStringBytes); request.Headers ["Authorization"] = "Basic " + authHeaderString; // Add certificate var certificate = new X509Certificate2(p12certificatePath, p12certificatePassword); request.ClientCertificates.Add(certificate); $authString = $userId.":".$password;$authStringBytes = utf8_encode($authString); $authloginString = base64_encode($authStringBytes); $authHeader= "Authorization:Basic ".$authloginString; $header = (array("Accept: application/json", "Content-Type: application/json", $authHeader)); $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_SSLCERT, $certificatePath); curl_setopt($ch, CURLOPT_SSLKEY, $privateKey); curl_setopt($curl, CURLOPT_CAINFO, $caFile);