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; } } }
Solved! Go to Solution
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.
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() } });
@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
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