I have an onPremise Dynamics CRM instance setup with HTTP and AD authentication, without any ADFS.
I'm willing to do a basic web service call (with NTLM) :
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ser="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:con="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<soap:Header/>
<soap:Body>
<ser:Retrieve>
<!--Optional:-->
<ser:entityName>?</ser:entityName>
<!--Optional:-->
<ser:id>?</ser:id>
<!--Optional:-->
<ser:columnSet>
<!--Optional:-->
<con:AllColumns>?</con:AllColumns>
<!--Optional:-->
<con:Columns>
<!--Zero or more repetitions:-->
<arr:string>?</arr:string>
</con:Columns>
</ser:columnSet>
</ser:Retrieve>
</soap:Body>
</soap:Envelope>
...But it seems I'm missing something since I get this response :
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">An error occurred when verifying security for the message.</s:Text>
</s:Reason>
</s:Fault>
</s:Body>
</s:Envelope>
My guess so far is I'm missing something in the SOAP header but I don't know why, maybe something to do server side?
Maybe someone would have a clue?
[2016-03-01 11:12:02.248] Process: w3wp |Organization:00000000-0000-0000-0000-000000000000 |Thread: 146 |Category: Platform.Sdk |User: 00000000-0000-0000-0000-000000000000 |Level: Error |ReqId: a9210b00-7f84-43dc-a794-d8f9697c8b53 | ServiceModelTraceRedirector.TraceData ilOffset = 0x45
><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>http://msdn.microsoft.com/en-US/library/System.ServiceModel.Diagnostics.ThrowingException.aspx</TraceIdentifier><Description>Throwing an exception.</Description><AppDomain>/LM/W3SVC/2/ROOT-2-131012583114393978</AppDomain><Exception><ExceptionType>System.ServiceModel.Security.MessageSecurityException, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType><Message>Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.</Message><StackTrace> at System.ServiceModel.Security.SecurityStandardsManager.CreateReceiveSecurityHeader(Message message, String actor, SecurityAlgorithmSuite algorithmSuite, MessageDirection direction)
> at System.ServiceModel.Security.MessageSecurityProtocol.CreateSecurityHeader(Message message, String actor, MessageDirection transferDirection, SecurityStandardsManager standardsManager)
> at System.ServiceModel.Security.MessageSecurityProtocol.ConfigureReceiveSecurityHeader(Message message, String actor, SecurityProtocolCorrelationState[] correlationStates, SecurityStandardsManager standardsManager, IList`1& supportingAuthenticators)
> at System.ServiceModel.Security.SymmetricSecurityProtocol.VerifyIncomingMessageCore(Message& message, String actor, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
> at System.ServiceModel.Security.MessageSecurityProtocol.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationStates)
> at System.ServiceModel.Channels.SecurityChannelListener`1.ServerSecurityChannel`1.VerifyIncomingMessage(Message& message, TimeSpan timeout, SecurityProtocolCorrelationState[] correlationState)
> at System.ServiceModel.Channels.SecurityChannelListener`1.SecurityReplyChannel.ProcessReceivedRequest(RequestContext requestContext, TimeSpan timeout)
> at System.ServiceModel.Channels.SecurityChannelListener`1.ReceiveItemAndVerifySecurityAsyncResult`2.OnInnerReceiveDone()
> at System.ServiceModel.Channels.SecurityChannelListener`1.ReceiveItemAndVerifySecurityAsyncResult`2.InnerTryReceiveCompletedCallback(IAsyncResult result)
> at System.Runtime.Fx.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
> at System.Runtime.AsyncResult.Complete(Boolean completedSynchronously)
> at System.Runtime.InputQueue`1.AsyncQueueReader.Set(Item item)
> at System.Runtime.InputQueue`1.Dispatch()
> at System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
> at System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped)
> at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
>
It means the incoming message should have a security header, which wasn't in the SOAP request, that's true.
Then I don't know what kind of security header I should add to my SOAP request.
I would suggest to capture your SOAP call using SoapClient as it mentioned here - https://msdn.microsoft.com/en-us/library/gg594434(v=crm.7).aspx#BKMK_CaptureHTTPTraffic
Related
I tried to call EnhancedVehBookRQ API with CERT ENV
This is my request and response
REQUEST:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sec="http://schemas.xmlsoap.org/ws/2002/12/secext" >
<soapenv:Header>
<Security xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<BinarySecurityToken>
token
</BinarySecurityToken>
</Security>
<MessageHeader xmlns="http://www.ebxml.org/namespaces/messageHeader">
<From>
<PartyId type="urn:x12.org:IO5:01">from</PartyId>
</From>
<To>
<PartyId type="urn:x12.org:IO5:01">to</PartyId>
</To>
<CPAId>hiddendata
</CPAId>
<ConversationId>hiddendata</ConversationId>
<Action>EnhancedVehBookRQ</Action>
<MessageData>
<MessageId>1001</MessageId>
<Timestamp>2021-08-18T10:00:01</Timestamp>
<!--Optional:-->
<TimeToLive>2021-08-19T10:00:01</TimeToLive>
<!--Optional:-->
<Timeout>0</Timeout>
</MessageData>
</MessageHeader>
</soapenv:Header>
<soapenv:Body>
<EnhancedVehBookRQ xmlns="http://services.sabre.com/sp/enhanced/veh/book/v1" version="1.0.0">
<VehBook>
<BookingInfo >
<BookingKey>23accd05-4770-4d1c-a286-ab0e6f360fc5
</BookingKey>
</BookingInfo>
<Customer NameNumber="1.1">
<Address>
<CityName>DALLAS</CityName>
<CountryCode>US</CountryCode>
<PostalCode>12345</PostalCode>
<StateCountyProv StateCode="TX" />
<StreetNmbr>1234 TEST ADDRESS</StreetNmbr>
</Address>
</Customer>
<RentalPaymentPrefs>
<GuaranteePrepaid Type="GUARANTEE">
<PaymentCard>
<CardCode>DC</CardCode>
<CardNumber>311234567685619</CardNumber>
<ExpiryMonth>12</ExpiryMonth>
<ExpiryYear>2022</ExpiryYear>
<FullCardHolderName>
<LastName>Monster</LastName>
</FullCardHolderName>
</PaymentCard>
</GuaranteePrepaid>
</RentalPaymentPrefs>
<VehRentalCore Quantity="1" />
</VehBook>
</EnhancedVehBookRQ>
</soapenv:Body>
</soapenv:Envelope>
I could not move ahead with car booking, getting errors like this
<Message code="ERR.SP.INTERNAL_ERROR">TravelItineraryReadRQ: After maximum retry count it was not possible to successfully execute target service</Message>
Can anybody please confirm whether SOAP requst is proper or not or I am missing something from my side
Yes, before running EnhancedVehBookRQ API you need to run PassengerDetailsRQ with TravelIntinerary details in it. On the success of this API use the response details for the request of this API and then run it
I'm trying to connect to WSDL server, which requires basic auth along with the body. I tried hitting with SOAPUI, and was able to do so. While working for the same in groovy and using wslite package for SOAP call, I'm getting error as "Password required".
I tried the tutorial on https://github.com/jwagenleitner/groovy-wslite, but the method described (in Usage block) didn't help.
I'm using groovy for this.
Below is the raw code from SOAP UI, with response 200OK
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:w="http://xmlns.oracle.com/Enterprise/Tools/schemas/W_CHKLST_CREATE_REQ.1">
<soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:UsernameToken wsu:Id="UsernameToken-83C962CC24EAB67F1D15586306447678"><wsse:Username>userName</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">Password</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">JLTdeK6Yg3D64+2qz5xnbA==</wsse:Nonce><wsu:Created>2019-05-23T16:57:24.767Z</wsu:Created></wsse:UsernameToken></wsse:Security></soapenv:Header>
<soapenv:Body>
<w:helloWorld/>
</soapenv:Body>
</soapenv:Envelope>
which results in a 200OK from SOAPUI
HTTP/1.1 200 OK
Date: Wed, 22 May 2019 21:54:12 GMT
Content-Type: text/xml; charset=UTF-8
Content-Length: 3570
My Groovy Code,
def client = new SOAPClient("URL of WSDL")
def response = client.send(SOAPAction: "someAction",
connectTimeout:10000,
readTimeout:20000,
useCaches:false,
followRedirects:false) {
version SOAPVersion.V1_2 // SOAPVersion.V1_1 is default
soapNamespacePrefix "soapenv" // "soap-env" is default
envelopeAttributes "xmlns:ns":"http://example.weather.org"
header {
security("xmlns:ns20":"http://SecurityOpenXSD"){
"ns20:Username"("username")
"ns20:Password"("password")
}
}
body {
"ns:helloWorld" {
}
}
}
which gives soap xml as
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand='1'
xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'>
<wsse:UsernameToken wsu:Id='UsernameToken-83C962CC24EAB67F1D15586299636605'>
<wsse:Username>userName</wsse:Username>
<wsse:Password
Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>
password
</wsse:Password>
<wsse:Nonce
EncodingType='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'>
JLTdeK6Yg3D64+2qz5xnbA==
</wsse:Nonce>
<wsu:Created>2019-05-23T10:07:52.913Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
But i get error as password required,
<?xml version="1.0" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<Code><Value>SOAP-ENV:Receiver</Value></Code>
<Reason><Text>null</Text></Reason>
<Detail><IBResponse type="error" xmlns=""><DefaultTitle> Error Response</DefaultTitle>
<StatusCode>20</StatusCode>
<DefaultMessage><![CDATA[User Password required]]></DefaultMessage>
</IBResponse></Detail></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>
I'm recreating calendar meeting events in a sychronization tool (using CreateItem), basically preserving some properties for meetings and writing them back.
However, there are some properties that are read-only, and I see no way to preserve their state:
IsMeeting
IsCancelled
MeetingRequestWasSent
IsOnlineMeeting
Some of these boolean values are stored in property AppointmentState, but that is read-only too:
Name Bit Description
None 0x0000 No flags have been set. This is only used for an appointment that does not include attendees.
Meeting 0x0001 This appointment is a meeting.
Received 0x0002 This appointment has been received.
Canceled 0x0004 This appointment has been canceled.
Is IsMeeting maybe automatically set if I set other meeting-properties, like e.g. OptionalAttendees or RequiredAttendees? That would help with one of the four, if I knew which properties trigger the setting of IsMeeting.
(Yes, this is a follow-up to Meeting request properties not settable in EWS SOAP calls?).
You should be able to use MAPI Extended Properties:
Appointment state is
Named Prop Name: id: 0x8217=33303 = PidLidAppointmentStateFlags, dispidApptStateFlags
Named Prop Guid: {00062002-0000-0000-C000-000000000046} = PSETID_Appointment
So SOAP that should be something like
<t:ExtendedProperty>
<t:ExtendedFieldURI DistinguishedPropertySetId="Appointment" PropertyId="33303" PropertyType="Integer" />
<t:Value>1</t:Value>
</t:ExtendedProperty>
(I use the managed API for that, and got that XML from the trace-log, hope that is something you can use)
[Edited by the OP] This is the complete call that does the job:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
<soapenv:Header>
<typ:RequestServerVersion Version="Exchange2007_SP1"/>
<typ:MailboxCulture>en-US</typ:MailboxCulture>
<typ:TimeZoneContext>
<typ:TimeZoneDefinition Id="W. Europe Standard Time"/>
</typ:TimeZoneContext>
</soapenv:Header>
<soapenv:Body>
<mes:UpdateItem ConflictResolution="AutoResolve" SendMeetingInvitationsOrCancellations="SendOnlyToChanged">
<mes:ItemChanges>
<typ:ItemChange>
<typ:ItemId <t:ItemId Id="AAMkA[snip]xAAA=" ChangeKey="Dw[snip]Mar"/>
<typ:Updates>
<typ:SetItemField>
<typ:ExtendedFieldURI DistinguishedPropertySetId="Appointment" PropertyId="33303" PropertyType="Integer"/>
<typ:CalendarItem>
<typ:ExtendedProperty>
<typ:ExtendedFieldURI DistinguishedPropertySetId="Appointment" PropertyId="33303" PropertyType="Integer"/>
<typ:Value>5</typ:Value>
</typ:ExtendedProperty>
</typ:CalendarItem>
</typ:SetItemField>
</typ:Updates>
</typ:ItemChange>
</mes:ItemChanges>
</mes:UpdateItem>
</soapenv:Body>
</soapenv:Envelope>
Strangely, the result says "Success", but reports a (one) conflict. I have no idea which one:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="15" MinorVersion="1" MajorBuildNumber="225" MinorBuildNumber="19" Version="V2_48" xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</s:Header>
<s:Body>
<m:UpdateItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:UpdateItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items>
<t:CalendarItem>
<t:ItemId Id="AAMk[snip]xAAA=" ChangeKey="DwA[snip]aMat"/>
</t:CalendarItem>
</m:Items>
<m:ConflictResults>
<t:Count>1</t:Count>
</m:ConflictResults>
</m:UpdateItemResponseMessage>
</m:ResponseMessages>
</m:UpdateItemResponse>
</s:Body>
</s:Envelope>
I am trying to write configure a gateway, which should take a complete SOAP Message and then delegate it to another SOAP Provider (incl. all SOAP headers of the first request).
What I have done so far:
1) web.xml
MessageDispatcherServlet with Mapping:
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/appservices/*</url-pattern>
</servlet-mapping>
2) Configuration with an Endpoint-Mapping
<bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
<property name="defaultEndpoint" ref="ws-in-gw"/>
</bean>
3) Configuration of Spring Integration inbound-gateway and outbound-gateway
<int-ws:inbound-gateway id="ws-in-gw"
request-channel="in"
reply-channel="out"
mapped-request-headers="*" />
<int:channel id="in" />
<int:channel id="out" />
<int-ws:outbound-gateway
id="ws-out-gw-status"
request-channel="in-status"
reply-channel="out-status"
uri="http://${delegationServer}/${delegation.contextroot}/soap/AnotherService"
interceptor="soapEnricher"
</int-ws:outbound-gateway>
<bean id="soapEnricher" class="foo.bar.SoapHeaderEnricher" />
public class SoapHeaderEnricher implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
try {
SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();
SoapHeader sh = soapMessage.getSoapHeader();
// can use sh.addHeaderElement(new QName(...)) now, but where are the original Headers???
} catch () {
}
}
My first Problem was, that the original SOAP Headers had been cut of, so I introduced the ' mapped-request-headers="*" ' attribute at the inbound gateway.
When I now configure a wire-tap, I see the Headers (myToken:MySecretToken) are received:
DEBUG 10:46:53 - [Payload DOMSource content=javax.xml.transform.dom.DOMSource#24a6ce98][Headers={errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#43456ff4, myToken:MySecretToken=org.springframework.ws.soap.saaj.SaajSoapHeaderElement#3b91ead, ...}]
This is the SOAP Message for my test:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:stat="http://status.service.promakler.provinzial.com/">
<soapenv:Header>
<myToken:MySecretToken xmlns=""
xmlns:myToken="http://foo.bar">12345</myToken:MySecretToken>
</soapenv:Header>
<soapenv:Body>
<stat:getStatus/>
</soapenv:Body>
</soapenv:Envelope>
So the Headers are now in my Message, but in the ClientInterceptor, there is no way to get the Headers (just the payload)?! I can add new Headers, but how can I get the original Header?
Can anybody give me a hint (or perhaps there is even a quiet simpler solution??)
Regards
Timo
Try to introduce a custom extension of DefaultSoapHeaderMapper and override populateUserDefinedHeader to extract those SaajSoapHeaderElement from the MessageHeaders and populate them to the SoapHeader. And finally inject your solution to the header-mapper of your <int-ws:outbound-gateway>.
I have this error
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Message part {http://soap.ws.server.wst.fit.cvut.cz/}createOrders was not recognized. (Does it exist in service WSDL?)</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
which is completely fine. But the problem is that CXF is returning Internal Server Error (HTTP 500). I would expect it to return 400 Bad Request because a wrong request is causing this. How can I change that?
DETAILS
The wrong request which produces the error above - there should be <soap:createOrder/> instead of <soap:createOrders/>.
POST http://localhost:8080/wst-server-1.0.0/services/soap/order
POST data:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://soap.ws.server.wst.fit.cvut.cz/">
<soapenv:Header/>
<soapenv:Body>
<soap:createOrders/>
</soapenv:Body>
</soapenv:Envelope>
[no cookies]
Request Headers:
Content-Length: 238
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
I know maybe this is too late for the answer but another way to handle HTTP status code is using CXF interceptors.
you can add an interceptor in your server CXF configure
public class ServiceConfigurer implements CxfConfigurer {
#Override
public void configureServer(Server server) {
server.getEndpoint().getOutFaultInterceptors().add(new ChangingStatusCodeInterceptor();
}
}
and in your interceptor, you can change this
public class SaveInfluxDataInterceptor extends WSS4JOutInterceptor {
#Override
public void handleMessage(SoapMessage soapMessage) {
((Fault)exchange.get(Exception.class)).setStatusCode(202); // this is because of soap12OutFaultInterceptor look to this fault
// or you can use this
// exchange.getOutFaultMessage().put(Message.RESPONSE_CODE, 202);
}
}
I used Camel with CXF. maybe this solution should change in yours.