IRS Soap Fault - Invalid WS Security Header

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

I am trying to send a Soap Request to IRS and facing the same error like others in this group - 'Invalid WS Security Header'. can someone guide me with a sample Soap Request? One more question is - as part of the Enrollment process, we submitted our X509 certificate(public key) to IRS website which will be used to authenticate/decrypt your message digests. Which certificate file did you upload for this process? We are really stuck with this error for days now. Appreciate any help on this. I have seen 2 questions on this topic, but there are no helping answers.

回答1:

I am assuming this is for ACA Air IRS submissions. We uploaded the .cer file to the IRS site, where you associate your TCC (in the format BBBBB, for example) with the .cer you uploaded. The stack we used were: Oracle's JDK 8, WSS4J v2.1.4, and CXF v3.1.4. Here is sample Java code we used for signing the reference elements that the IRS wants signed:

 public static SOAPMessage signSoapMessage(SOAPMessage message,                                           String keystorePassword, String irsPrivateKeyPassword, Class> clazz) throws WSSecurityException {      //TODO remove below hard coded     final String _irsPrivateKeyPassword = "yourprivatekeypasswordyougotfromCA";     final String _keystorePassword = "yourpasswordtoyourJKS";     keystorePassword = _keystorePassword;     irsPrivateKeyPassword = _irsPrivateKeyPassword;      PrivateKeyEntry privateKeyEntry = getPrivateKeyEntry(keystorePassword,             irsPrivateKeyPassword);      PrivateKey signingKey = privateKeyEntry.getPrivateKey();     X509Certificate signingCert = (X509Certificate) privateKeyEntry             .getCertificate();      //TODO add alias to database     final String alias = "thealiasforthiscertandprivatekey";     final int signatureValidityTime = 3600; // 1hour in seconds      WSSConfig config = WSSConfig.getNewInstance();     //config.setWsiBSPCompliant(true);      WsuIdAllocator idAllocator = new WsuIdAllocator() {          @Override         public String createSecureId(String prefix, Object o) {             //e.g.              if(prefix.equals("KI-"))                 return "KI-" + UUID.randomUUID().toString().replace("-", "").toUpperCase();             //e.g.              else if (prefix.equals("STR-"))                 return "STR-" + UUID.randomUUID().toString().replace("-", "").toUpperCase();             //TODO why is there a condition where prefix.equals("X509") and o.toString() is the public cert?             else                 return null;         }          //e.g.  wsEncryptionParts = new ArrayList();          //Very important, ordering of the parts is critical: refer to page 34 of the guide         //for ACAGetTransmitterBulkRequestService, it is Timestamp, ACATransmitterManifestReqDtl, ACABusinessHeader         if(clazz.equals(ACATransmitterManifestReqDtl.class)){             WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp",                     WSConstants.WSU_NS, "");              //This is very important, Timestamp needs to be fist             wsEncryptionParts.add(timestampPart);                          WSEncryptionPart aCATransmitterManifestReqDtlPart = new WSEncryptionPart(                 "ACATransmitterManifestReqDtl",                 "urn:us:gov:treasury:irs:ext:aca:air:7.0", "");             wsEncryptionParts.add(aCATransmitterManifestReqDtlPart);              WSEncryptionPart aCABusinessHeaderPart = new WSEncryptionPart(                     "ACABusinessHeader",                     "urn:us:gov:treasury:irs:msg:acabusinessheader", "");                         wsEncryptionParts.add(aCABusinessHeaderPart);         }         //for ACAGetTransmitterBulkRequestStatus, it is Timestamp, ACABusinessHeader, ACABulkRequestTransmitterStatusDetailRequest         else if(clazz.equals(ACABulkRequestTransmitterStatusDetailRequest.class)){             WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp",                     WSConstants.WSU_NS, "");              //This is very important, Timestamp needs to be fist             wsEncryptionParts.add(timestampPart);                          WSEncryptionPart aCABusinessHeaderPart = new WSEncryptionPart(                     "ACABusinessHeader",                     "urn:us:gov:treasury:irs:msg:acabusinessheader", "");                         wsEncryptionParts.add(aCABusinessHeaderPart);              WSEncryptionPart aCABulkRequestTransmitterStatusDetailRequestPart = new WSEncryptionPart(                     "ACABulkRequestTransmitterStatusDetailRequest",                     "urn:us:gov:treasury:irs:msg:irstransmitterstatusrequest", "");                 wsEncryptionParts.add(aCABulkRequestTransmitterStatusDetailRequestPart);         }          wsSecSignature.getParts().addAll(wsEncryptionParts);          Properties properties = new Properties();         properties.setProperty("org.apache.ws.security.crypto.provider",                 "org.apache.ws.security.components.crypto.Merlin");         Crypto crypto = CryptoFactory.getInstance(properties);         KeyStore keystore = KeyStore.getInstance("JKS");          java.io.FileInputStream fis = null;         try {             fis = new java.io.FileInputStream(System.getProperty("java.home") + "//lib//security//meckeystore.jks");             if(fis != null) {                 keystore.load(fis, keystorePassword.toCharArray());             } else {                 //TODO: replace with custom MEC exception                 throw new Exception("Unable to read keystore file.");             }          } finally {             if (fis != null) {                 fis.close();             }         }          keystore.setKeyEntry(alias, signingKey, keystorePassword.toCharArray(),                 new Certificate[]{signingCert});         ((Merlin) crypto).setKeyStore(keystore);         crypto.loadCertificate(new ByteArrayInputStream(signingCert.getEncoded()));          document = wsSecSignature.build(document, crypto, secHeader);          updateSOAPMessage(document, message);       } catch (Exception e) {         // throw new         // WSSecurityException(WSSecurityException.Reason.SIGNING_ISSUE, e);         e.printStackTrace();     }      return message; }  /**  * Changes the SOAPMessage to a dom.Document.  */ private static Document toDocument(SOAPMessage soapMsg) throws TransformerException,         SOAPException, IOException {     Source src = soapMsg.getSOAPPart().getContent();     TransformerFactory tf = TransformerFactory.newInstance();     Transformer transformer = tf.newTransformer();     DOMResult result = new DOMResult();     transformer.transform(src, result);     return (Document) result.getNode(); }  //https://svn.apache.org/repos/asf/webservices/wss4j/branches/WSS4J_1_1_0_FINAL/test/wssec/SOAPUtil.java private static SOAPMessage updateSOAPMessage(Document doc,                                              SOAPMessage message)         throws Exception {     DOMSource domSource = new DOMSource(doc);     message.getSOAPPart().setContent(domSource);     return message; } 

Here is the sample SOAP request

ojqiqHiXxPWIaEumCOO3bKJZ73A=cm3KGHFWHyJcBU9MEQzw6Ru04z0=6nM3ONVPyHtiupcznWiixpNG82k=removed==removed2016-01-27T23:59:36.352Z2016-01-28T00:59:36.352Z20150OTHealth SystemsRockvilleMDXI100011094/1095Bapplication/xml5bae956d7c6a01c95ce570dd11debe7859381094B_Request_BBBBB_20151019T121002000Z.xmld81ead9b-1223-4d28-8d46-f7af58710268:SYS12:BBBBB::T2016-01-27T23:59:36ZRequestSubmissionStatusDetail

The key really for us was this from the IRS documentation because we were using Apache CXF v2.1.4:

Big Hack for 7bit content type encoding and content type

5.4.2 (from IRS documentation) Message Attachment Content Type ISS-A2AAIR web services require transmitters to use SOAP-over-HTTP messaging with MTOM to send XML data files. The file that is encoded in the MTOM attachment must be uncompressed native XML. The content type for the MTOM encoded binary object identified in the Manifest header must be “application/xml”. The content-transfer-encoding of the Form Data File must be 7-bit.

Inside apache-cxf-3.1.4-src/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java

194     private static void writeHeaders(String contentType, String attachmentId, 195                                      Map> headers, Writer writer) throws IOException { 196 //        writer.write("\r\nContent-Type: "); 197 //        writer.write(contentType); 198 writer.write("\r\nContent-Type: application/xml"); 199 //        writer.write("\r\nContent-Transfer-Encoding: binary\r\n"); 200 writer.write("\r\nContent-Transfer-Encoding: 7bit\r\n"); 


回答2:

Prabhat, I think MTOM and SwA cannot go hand in hand. You can use either one of them. When you enable MTOM, you cannot use Attachment APIs (SwA).



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!