Java based MLE requests work but C# and NodeJS MLE requests get "Token validation failed"

SOLVED
jhollandgtp
Regular Visitor

Java based MLE requests work but C# and NodeJS MLE requests get "Token validation failed"

Hello,

We were able to make successful MLE requests using Java JWE libraries. Both com.nimbusds nimbus-jose-jwt v8.14.1 and org.bitbucket.b_c jose4j v0.7.0 work in the sandbox. However, we're a C# shop and would like to get a C# implementation working. But we were not able to get MLE working in C# MLE. As a sanity check, we also tried NodeJS but that didn't work either.

 

Request

Headers
{
Content-Type: application/json
Accept: application/json
keyId: 4d76f834-dde5-4ea0-af7e-fd22ba020900
Authorization: Basic U0tVMFhaWEg1TDBPNUEwVVA0VEsyMTZ5WEVGVXNiZXRzYVdVc0otcTdhTmc2SjRWazpDZG9tUmszYzBQbTY4UTJwOFNWbzMwSHA=
ex-correlation-id: 0VY6X1AV4WYF_SC
}

Body
{
"encData":"eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMTI4R0NNIiwia2lkIjoiNGQ3NmY4MzQtZGRlNS00ZWEwLWFmN2UtZmQyMmJhMDIwOTAwIiwiaWF0IjoxNTg4OTcwNjU3fQ.rZPyIYroUvtMu_eBn4SlLUzOpeM9C7-yNF92bgoDCqvMJpx0cia_nKbesUxPBC6U-TJ100T0WQkPQ9ShaknSZkf6tJR5BX3gTed9ed9A8vudcs2wzE9L-DvzOadvzHjQZW3WvniP-T2JMZqst4t_Pq2P0Rr2M4UAsLOmlhGYKh3rM69WjXADKVxVhXows2gM1n-mkTUu1HdHj4U7D5lAvgkLdVq75y6iOD0Q_-_s8kuXImoEjtSJRO7Ngd-IE1pGvUvyjQ6HI_ejnYEfilttO5bZ2cG17C40GlvNGAMe3GtT2BJH4mQECXBYYx-d1RbvA384woHcuz0oqOCC8Lej2w.vE6SszwsjJxtiiVG.ODtUY7fvj_IxHl2ASfjmXOCAE42sxvMNWxTYHDV5RmZ_kdZ_CH2TiUPVQtU-bcj_vLM8a5WLKSZIybHpq9XAJexqx1apTYoTs-KaC3UhK_EYzFKYA_VaJ5ajnIT2CPLPn1FQe7O1iDX6ssgNYRlepj9FUx01wEIsMH5XmEF15ezUihQ_0F52wQrruJGaDQiSi3yydX8B33XDoyMGRo-h5Yx-YloaVUNR_QzAAwcU3SIMb_o-b9PnK1rr9yJutg-coBm6kpqAmsYMHASfgZUa-RfTPQzUfVoBPjL-2Rf2-qPqnhgVkNRICY5JSnGFDkTGdtxJVxIIu2eEbbgmFl3sWQeZZmkuiqEM0WJ8yMsWpgkwEPkNAZDP4KEt-AJ1gJnSS_1c0zhnBcgMyIwJUFbinHrHBGAGRLjbYkym1FFXSS6G5dXjrKS0XP9T62bg2IOAlEqDl_7XezCWcSEMYogQpodj4bAa7V254uPqUvJv_p__kZy8RfntrsH-UKRUv3Nn7RAampFXaeAX6BIOH2qpLTzow1pOcKK0vCmGAaIecfuBn37JaxKnEc_U4gGxBYQP-LuRcrcVONvCxcTJ6wKw_4fMVfXXaVC_JWrUkSw29gJuZdNeoxLhm8_ILoEErkdSBdfmZot2W5V76TRQUjnj59Hx5nGMW-TF8Xq-EFuS7COLnqSKqYr5uJovw7yFnzGZlfigOSHCJRjioANgjt6VOF8ZiXkuea8qNzN4W29spoRC4_KZ0EwkrXtEV05y4xUGSn6jR41sjSL_0XxQa8E7DTMpbksA48dHANA16xVbFDA.kTLYysiXbtCA_j2Xf-vCLA"
}

Response

Headers
{
Server: nginx
X-SERVED-BY: l55c017
X-CORRELATION-ID: 1588970712_323_833486348_l55c017_VDP_WS
X-APP-STATUS: 401
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=2592000;includeSubdomains
Cache-Control: no-store, must-revalidate, no-cache
Pragma: no-cache
Date: Fri, 08 May 2020 20:45:12 GMT
Connection: close
Content-Type: application/json; charset=UTF-8
Content-Length: 112
Expires: -1
}

Body
{
"responseStatus":{"status":401,"code":"9210","severity":"ERROR","message":"Token validation failed","info":""}
}

Test Class

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using VdpCSharpCore.VDPApiTest.helpers;
using VdpCSharpCore.Mle;

namespace VdpCSharpCore.VDPApiTest.visadirect
{
    [TestClass]
    public class MVisaTest
    {
        private VdpConfig vdpConfig = VdpConfig.Init();
        private string cashInPushPayments;
        private VisaAPIClient visaAPIClient;

        public MVisaTest()
        {
            visaAPIClient = new VisaAPIClient();
            string strDate = DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ss");
            cashInPushPayments =
                 "{"
                 + "\"acquirerCountryCode\": \"643\","
                 + "\"acquiringBin\": \"400171\","
                 + "\"amount\": \"124.05\","
                 + "\"businessApplicationId\": \"CI\","
                 + "\"cardAcceptor\": {"
                                         + "\"address\": {"
                                                             + "\"city\": \"Bangalore\","
                                                             + "\"country\": \"IND\""
                                                      + "},"
                                         + "\"idCode\": \"ID-Code123\","
                                         + "\"name\": \"Card Accpector ABC\""
                                       + "},"
                 + "\"localTransactionDateTime\": \"" + strDate + "\","
                 + "\"merchantCategoryCode\": \"4829\","
                 + "\"recipientPrimaryAccountNumber\": \"4123640062698797\","
                 + "\"retrievalReferenceNumber\": \"430000367618\","
                 + "\"senderAccountNumber\": \"4541237895236\","
                 + "\"senderName\": \"Mohammed Qasim\","
                 + "\"senderReference\": \"1234\","
                 + "\"systemsTraceAuditNumber\": \"313042\","
                 + "\"transactionCurrencyCode\": \"USD\","
                 + "\"transactionIdentifier\": \"381228649430015\""
                 + "}";
        }

        [TestMethod]
        public void TestMle_CSharp_Dvsekhvalnov()
        {
            // Implement MLE encryption
            var headers = new Dictionary<string, string>
            {
                { "keyId", vdpConfig.mleKid }
            };

            var jwtService = new DvsekhvalnovJoseJwtService(vdpConfig.mleKid, vdpConfig.mleP12ServerCertPath, vdpConfig.mleP12ServerCertPassword);
            string encData = jwtService.EncryptPayload(cashInPushPayments);
            string requestBodyString = "{\"encData\":\"" + encData + "\"}";

            // Send request
            string baseUri = "visadirect/";
            string resourcePath = "mvisa/v1/cashinpushpayments";
            string status = visaAPIClient.DoMutualAuthCall(baseUri + resourcePath, "POST", "M Visa Transaction Test", requestBodyString, headers);
            Assert.AreEqual(status, "OK");
        }
    }
}

Encryption Service Class

using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;

namespace VdpCSharpCore.Mle
{
    // Encryption Library Used: https://github.com/dvsekhvalnov/jose-jwt
    class DvsekhvalnovJoseJwtService
    {
        private readonly string kid;
        private readonly string mlePublicKeyPath;
        private readonly string mlePublicKeyPassword;

        public DvsekhvalnovJoseJwtService(string kid, string mlePublicKeyPath, string mlePublicKeyPassword)
        {
            this.kid = kid;
            this.mlePublicKeyPath = mlePublicKeyPath;
            this.mlePublicKeyPassword = mlePublicKeyPassword;
        }

        public string EncryptPayload(string payload)
        {
            //NET40-NET45
            //var publicKey = new X509Certificate2(mlePublicKeyPath, mlePublicKeyPassword).PublicKey.Key as RSACryptoServiceProvider;

            //NETCORE
            var publicKey = new X509Certificate2(mlePublicKeyPath, mlePublicKeyPassword).GetRSAPublicKey();

            string token = Jose.JWT.Encode(
                payload: payload,
                key: publicKey,
                alg: Jose.JweAlgorithm.RSA_OAEP_256,
                enc: Jose.JweEncryption.A128GCM,
                extraHeaders: new Dictionary<string, object>
                {
                    { "kid", kid },
                    { "iat", Microsoft.IdentityModel.Tokens.EpochTime.GetIntDate(DateTime.UtcNow) }
                });

            return token;
        }
    }
}
4 REPLIES 4
ricardo_visa
Community Manager

Re: Java based MLE requests work but C# and NodeJS MLE requests get "Token validation failed&qu

Hey @jhollandgtp - sorry to hear that, totally understand the frustrations. Thanks for the info, this will help - let me do some digging and run this by some of our engineers to see what I can get for you. 

 

In the meantime, let me know if any other questions come up. 

 




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

Re: Java based MLE requests work but C# and NodeJS MLE requests get "Token validation failed&am

This is now working with the following update to the encryption code:

            string token = Jose.JWT.Encode(
                payload: payload,
                key: publicKey,
                alg: Jose.JweAlgorithm.RSA_OAEP_256,
                enc: Jose.JweEncryption.A128GCM,
                extraHeaders: new Dictionary<string, object>
                {
                    { "kid", kid },
                    { "iat", new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds() }
                });
asaldanha
New Contributor

Re: Java based MLE requests work but C# and NodeJS MLE requests get "Token validation failed&am

@jhollandgtp - I am trying to use the code you posted to get MLE going with C#. What is throwing me off is the value that should be used 

for "vdpConfig.mleP12ServerCertPassword". 

 

var jwtService = new DvsekhvalnovJoseJwtService(vdpConfig.mleKid, vdpConfig.mleP12ServerCertPath, vdpConfig.mleP12ServerCertPassword);

 

Once you create the Key ID for the project you get the server cert, you get a download to the certificate, but no password.  The only password I have associated with a p12 is the one I choose when I created the p12 key store for my project 

 

Any help would be appreciated 

 

 

vkamboj
Visa Dev Moderator

Re: Java based MLE requests work but C# and NodeJS MLE requests get "Token validation failed&am

Hello @jhollandgtp 

 

Please refer to the sample code available  here.

I am not sure which sample code you are referring to because we do not need any mle cert password.

See screenshot below from the sample present at above link.

 

In the cert password -> PASSPHRASE FOR P12 CERTIFICATE HERE-> client needs to enter the password it provided while creating the .p12 file for 2-way ssl.

But no password needed for mle cert.

 

Thank you, 

Vaibhav

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