Token validation failed

supriya7768
Occasional Visitor

Token validation failed

package visa.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jose.util.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPublicKey;

public class EncryptionUtils {

private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
private static final String END_CERT = "-----END CERTIFICATE-----";
// Update the path to your public certificate
private static String mleServerPublicCertificatePath = "C:\\Users\\supriya.mahajan\\Downloads\\server_cert.pem";

public static String getEncryptedPayload(Object payload, String keyId) throws CertificateException, JOSEException, IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.setSerializationInclusion(Include.NON_EMPTY);

String plainText = payload == null ? "" : mapper.writeValueAsString(payload);
JWEHeader.Builder headerBuilder = new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A128GCM);

headerBuilder.keyID(keyId);
headerBuilder.customParam("iat", System.currentTimeMillis());

JWEObject jweObject = new JWEObject(headerBuilder.build(), new Payload(plainText));
jweObject.encrypt(new RSAEncrypter(getRSAPublicKey()));
return "{\"encData\":\"" + jweObject.serialize() + "\"}";
}

/*
* Converts PEM file content to RSAPublicKey
*/
private static RSAPublicKey getRSAPublicKey() throws CertificateException, IOException {
String pemEncodedPublicKey = IOUtils.readFileToString(new File(mleServerPublicCertificatePath), Charset.forName("UTF-8"));
Base64 base64 = new Base64(pemEncodedPublicKey.replaceAll(BEGIN_CERT, "").replaceAll(END_CERT, "").trim());
Certificate cf = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(base64.decode()));
return (RSAPublicKey) cf.getPublicKey();
}

This is my EncryptionUtils.java file

package visa.api;

import visa.api.EncryptionUtils;

public class App {
public String getGreeting() {
return "Hello World!";
}

public static void main(String[] args) {
System.out.println(new App().getGreeting());

try {
// Sample payload and keyId
String payload = "{\n" +
" \"Envt\": {\n" +
" \"Card\": {\n" +
" \"CardTp\": \"PHYS\",\n" +
" \"XpryDt\": \"1230\",\n" +
" \"PAN\": \"4000123456781234\",\n" +
" \"Seed\": \"123456ABCDEF\",\n" +
" \"CardSeqNb\": 1\n" +
" }\n" +
" },\n" +
" \"Hdr\": {\n" +
" \"msgIdentfctn\": {\n" +
" \"clientId\": \"TEST_CLIENT_123\",\n" +
" \"correlatnId\": \"456987456\"\n" +
" },\n" +
" \"PrtcolVrsn\": \"VIP.1.1\"\n" +
" }\n" +
"}";
String keyId = "ccc10b08-04ae-4c4a-bdb9-0e8216148e9c";

// Encrypt the payload
String encryptedPayload = EncryptionUtils.getEncryptedPayload(payload, keyId);
System.out.println("Encrypted Payload: " + encryptedPayload);
} catch (Exception e) {
// Print stack trace for debugging
e.printStackTrace();
}
}
}

This is my App.java file

After running this code I am getting an encrypted payload.

That encrpyted code I am passing as postman request body as :

{"encData":"eyJlbmMiOiJBMTI4R0NNIiwiaWF0IjoxNzI5NTAwNjE5OTk2LCJhbGciOiJSU0EtT0FFUC0yNTYiLCJraWQiOiJjY2MxMGIwOC0wNGFlLTRjNGEtYmRiOS0wZTgyMTYxNDhlOWMifQ.jf_HQbQxUe__x2FSx1zafEjo4Y8D2BT2gWpTMxfmRMh6jCYn9A7HRx_r2SrVcC_uy3gUWGTxPzmlA-H8kPhw2uZzEDGJrBU-Y7ZNPziBW370E8H9OqqM9rYmuX2gznHYr6j9cvu7zm80sVtSEOLjT9q2FEW3MeRYvsjl_v_3e0ie-kH9Q04Om9aj8RFoNkXriTWE1peOqDy448SBEytu2Uhz2LnoZZk5AAE3rzgcFnXlXfLeFUsqxkaP0y442UJSUcSdXr7cszVWG90SQMjVj4AArJdGyxIY-QQkmz8pfMpFlOzyUnCxMCHJP7m6uHbfU_FN7yE9GRxsGoGl5Y5IdA.tUhkGuOSb0rFZmAh.dYzsHlXPfeGNeMhMaRvBVG5A6L9Nr-VzDZjnqwinjbzP_pfTnfplM6fwZ0yx_pzCtPVQVjveL4Ac99ZDb2pgX2DESqeBWgWNWrmi58gRETtMdDt7ujDEhKOPvqIcv-mijbJzsgBSvCEhmpVxW0EGW2sWRBkHKSPw0wFS3s20jn5MprteT6VG1cGph17UKN7yGe2h6irGHkeIMjKzcll_f9K9ZaPolOx3lFhv4S3TxhhiE1rxtYtlmnJa-R4jZuH4EcfIdJ-nwxXdNhwYGwrGLiS85pGrKJS7ZA3gOJiZl94uVMgEuZgvgGhLIVfoIUFQq_RRogS8wIuwBtnFO8lr2IwmxTkVqAXvvGRLS0Xn_xgfSdBYG2LxWkiuoIa_pLye8KWUJ-gOK6bGYYkjkxOKovSIl1tQj1YdwRC_KqVhMdN0cW3HOn2W59FTpIbmPYkQSNjcjbNzxBYr9gcHgoo0FKQge-rfsMIukY7XXq1Prc1chdA.N0SYMkFGyfB5tfHIup5-2g"}

I have also added certificates in postman setting of cert.pem and the key.pem which was generated when I created the project in visa

In HTTP Header I have added the keyId which is generated in the credentials tab under Encryption/Decryption.
In Authorization I have selected Basic Auth and added Username and password which is given in Credentials tab

But it is giving the response as:
{
    "responseStatus": {
        "status": 401,
        "code": "9210",
        "severity": "ERROR",
        "message": "Token validation failed",
        "info": ""
    }
}

And I am also not understanding what X-App-Id value I should add in Header
Please help me out to solve this problem.
3 REPLIES 3
supriya7768
Occasional Visitor

Re: Token validation failed

I am using the api to create new card and doing sandbox testing

jenn_kh
Community Moderator

Re: Token validation failed

Hi @supriya7768Thank you for reaching out. An agent will look into this and get back to you soon. Until then, if any community member knows a solution, please feel free to reply in this thread. 

DianaVisaPM
Visa Developer Support Specialist

Re: Token validation failed

Hey @supriya7768,

 

It looks like you're encountering a "Token validation failed" error when calling the Visa Card Service API. Here are some steps and tips to troubleshoot and resolve this issue:

1. Check Your API Credentials:
Ensure that the credentials you are using (API Key, Shared Secret) are correct and correspond to the sandbox environment.

2. X-App-Id:
This is the App ID generated when you created your project on the Visa Developer Platform. You can find this in the dashboard of your project under the "Credentials" section.

3. Certificate Configuration:
Ensure that you have correctly configured your certificates in Postman. You should add both the `cert.pem` and `key.pem` files in the "Certificates" section of Postman.

4. Authorization Header:
Make sure you are using the correct Base64 encoded username and password in the Authorization header. The format should be:
```
Authorization: Basic Base64Encode(username:password)
```

5. Headers:
Ensure you have the following headers in your request:
```http
X-App-Id: [Your X-App-Id]
keyID: [Your Key ID]
Accept: application/json
Content-Type: application/json
Authorization: Basic [Base64EncodedCredentials]
```

6. Payload Encryption:
Confirm that the payload encryption using the `EncryptionUtils` class is correct and matches the expected format by the API. Make sure that the `keyID` used in the encryption matches the `keyID` sent in the headers.

7. Timestamp:
The `iat` (issued at) parameter in the JWEHeader should be set to the current timestamp in milliseconds. Ensure this is correctly set as shown in your `EncryptionUtils` class.

8. Endpoint URL:
Confirm that you are using the correct sandbox endpoint URL:
```
https://sandbox.api.visa.com/connect/v1/cardServices/new
```

9. Example Code:

Here is an example of how you can structure your code and Postman request:

```java
// EncryptionUtils.java
package visa.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.RSAEncrypter;
import com.nimbusds.jose.util.Base64;
import com.nimbusds.jose.util.IOUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPublicKey;

public class EncryptionUtils {

private static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----";
private static final String END_CERT = "-----END CERTIFICATE-----";
private static String mleServerPublicCertificatePath = "C:\\Users\\supriya.mahajan\\Downloads\\server_cert.pem";

public static String getEncryptedPayload(Object payload, String keyId) throws CertificateException, JOSEException, IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_NULL);
mapper.setSerializationInclusion(Include.NON_EMPTY);

String plainText = payload == null ? "" : mapper.writeValueAsString(payload);
JWEHeader.Builder headerBuilder = new JWEHeader.Builder(JWEAlgorithm.RSA_OAEP_256, EncryptionMethod.A128GCM);

headerBuilder.keyID(keyId);
headerBuilder.customParam("iat", System.currentTimeMillis());

JWEObject jweObject = new JWEObject(headerBuilder.build(), new Payload(plainText));
jweObject.encrypt(new RSAEncrypter(getRSAPublicKey()));
return "{\"encData\":\"" + jweObject.serialize() + "\"}";
}

private static RSAPublicKey getRSAPublicKey() throws CertificateException, IOException {
String pemEncodedPublicKey = IOUtils.readFileToString(new File(mleServerPublicCertificatePath), Charset.forName("UTF-8"));
Base64 base64 = new Base64(pemEncodedPublicKey.replaceAll(BEGIN_CERT, "").replaceAll(END_CERT, "").trim());
Certificate cf = CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(base64.decode()));
return (RSAPublicKey) cf.getPublicKey();
}
}

// App.java
package visa.api;

import visa.api.EncryptionUtils;

public class App {
public String getGreeting() {
return "Hello World!";
}

public static void main(String[] args) {
System.out.println(new App().getGreeting());

try {
String payload = "{\n" +
" \"Envt\": {\n" +
" \"Card\": {\n" +
" \"CardTp\": \"PHYS\",\n" +
" \"XpryDt\": \"1230\",\n" +
" \"PAN\": \"4000123456781234\",\n" +
" \"Seed\": \"123456ABCDEF\",\n" +
" \"CardSeqNb\": 1\n" +
" }\n" +
" },\n" +
" \"Hdr\": {\n" +
" \"msgIdentfctn\": {\n" +
" \"clientId\": \"TEST_CLIENT_123\",\n" +
" \"correlatnId\": \"456987456\"\n" +
" },\n" +
" \"PrtcolVrsn\": \"VIP.1.1\"\n" +
" }\n" +
"}";
String keyId = "ccc10b08-04ae-4c4a-bdb9-0e8216148e9c";

String encryptedPayload = EncryptionUtils.getEncryptedPayload(payload, keyId);
System.out.println("Encrypted Payload: " + encryptedPayload);
} catch (Exception e) {
e.printStackTrace();
}
}
}
```

Here is an example of the request body to be used in Postman:
```json
{
"encData": "eyJlbmMiOiJBMTI4R0NNIiwiaWF0IjoxNzI5NTAwNjE5OTk2LCJhbGciOiJSU0EtT0FFUC0yNTYiLCJraWQiOiJjY2MxMGIwOC0wNGFlLTRjNGEtYmRiOS0wZTgyMTYxNDhlOWMifQ.jf_HQbQxUe__x2FSx1zafEjo4Y8D2BT2gWpTMxfmRMh6jCYn9A7HRx_r2SrVcC_uy3gUWGTxPzmlA-H8kPhw2uZzEDGJrBU-Y7ZNPziBW370E8H9OqqM9rYmuX2gznHYr6j9cvu7zm80sVtSEOLjT9q2FEW3MeRYvsjl_v_3e0ie-kH9Q04Om9aj8RFoNkXriTWE1peOqDy448SBEytu2Uhz2LnoZZk5AAE3rzgcFnXlXfLeFUsqxkaP0y442UJSUcSdXr7cszVWG90SQMjVj4AArJdGyxIY-QQkmz8pfMpFlOzyUnCxMCHJP7m6uHbfU_FN7yE9GRxsGoGl5Y5IdA.tUhkGuOSb0rFZmAh.dYzsHlXPfeGNeMhMaRvBVG5A6L9Nr-VzDZjnqwinjbzP_pfTnfplM6fwZ0yx_pzCtPVQVjveL4Ac99ZDb2pgX2DESqeBWgWNWrmi58gRETtMdDt7ujDEhKOPvqIcv-mijbJzsgBSvCEhmpVxW0EGW2sWRBkHKSPw0wFS3s20jn5MprteT6VG1cGph17UKN7yGe2h6irGHkeIMjKzcll_f9K9ZaPolOx3lFhv4S3TxhhiE1rxtYtlmnJa-R4jZuH4EcfIdJ-nwxXdNhwYGwrGLiS85pGrKJS7ZA3gOJiZl94uVMgEuZgvgGhLIVfoIUFQq_RRogS8wIuwBtnFO8lr2IwmxTkVqAXvvGRLS0Xn_xgfSdBYG2LxWkiuoIa_pLye8KWUJ-gOK6bGYYkjkxOKovSIl1tQj1YdwRC_KqVhMdN0cW3HOn2W59FTpIbmPYkQSNjcjbNzxBYr9gcHgoo0FKQge-rfsMIukY7XXq1Prc1chdA.N0SYMkFGyfB5tfHIup5-2g"
}
```

Ensure that the `X-App-Id` and other headers are correctly set. 




Thanks,

Diana



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