I'm trying to create an Apache CXF (2.7.5) client for the Microsoft Dynamics CRM 2011 ("xRM") web services (which I understood to be based on WCF 4) where CRM is in claims mode, so that the WSDL for this web service points to an STS (in my case AD FS 2.0).
My main question: Are there any tutorial, suggestions, blog posts to help me out (either describing how to send claims, or how to avoid them and instead use Windows authentication)?
Below is a description of what I've done until now.
I already had working code for the same web service, which works when CRM is in Windows authentication mode. That code is based on "CXF and MS CRM 2011" on Groovy Tom's Blog.
To support claims mode, I additionally needed to include org.apache.cxf:cxf-rt-ws-mex, so that the xRM WSDL can be parsed by CXF. Then I needed to make the CXF built-in STS client use SOAP 1.2:
client.getRequestContext().put("ws-security.sts.client-soap12-binding", "true");
to avoid an error 500 from AD FS 2.0. (Apparently AD FS 2.0 expects the /adfs/services/trust/mex endpoint to be called using SOAP 1.2, and CXF defaults to SOAP 1.1. I had to find this out from AD FS's WCF trace, which reported
System.ServiceModel.ProtocolException: Content Type text/xml; charset=UTF-8 was sent to a service expecting application/soap+xml; charset=utf-8. The client and service bindings may be mismatched.
when Apache CXF used SOAP 1.1.)
Then there was another problem: the WSDL returned by AD FS's /adfs/services/trust/mex endpoint seemed incomplete, in that it contains
<wsdl:types>
<xsd:schema
targetNamespace="http://schemas.microsoft.com/ws/2008/06/identity/securitytokenservice/Imports">
<xsd:import namespace="http://schemas.microsoft.com/Message" />
<xsd:import namespace="http://schemas.xmlsoap.org/ws/2005/02/trust" />
<xsd:import namespace="http://docs.oasis-open.org/ws-sx/ws-trust/200512" />
</xsd:schema>
</wsdl:types>
so none of the import
s has a schemaLocation
. This makes CXF complain that
org.apache.cxf.wsdl11.WSDLRuntimeException: Part request defined as element {http://docs.oasis-open.org/ws-sx/ws-trust/200512}RequestSecurityToken which is not in the schema.
I found out what caused this: the schemas containing RequestSecurityToken
etc. are in the mex SOAP call result, but in separate <wsx:MetadataSection Dialect="http://www.w3.org/2001/XMLSchema">
sections, which the code in AbstractSTSClient
completely ignores.
So I put in place my own WSDLFactory+WSDLReader (using property {{javax.wsdl.factory.WSDLFactory}}), which just inserts the schemas for the three namespaces into any WSDL it reads.
Now I'm blocked at the next point: the xRM WSDL (after formatting) contains an Address
of http://www.w3.org/2005/08/addressing/anonymous
(see below), which somehow causes CXF to look up that endpoint in AD FS's metadata. However, such an endpoint of course does not exist: it contains, e.g., https://...:.../adfs/services/trust/2005/usernamemixed
.
<wsdl:definitions
targetNamespace="http://schemas.microsoft.com/xrm/2011/Contracts/Services"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
snipped="other xmlns attributes">
<wsp:Policy wsu:Id="CustomBinding_IOrganizationService_policy">
<wsp:ExactlyOne>
<wsp:All>
<!-- snip -->
<sp:EndorsingSupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:IssuedToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<Issuer
xmlns="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<Address xmlns="http://www.w3.org/2005/08/addressing">
http://www.w3.org/2005/08/addressing/anonymous
</Address>
So what can I do now?
More generally, my question is now: Am I on the right path for building a Java client for xRM-in-claims-mode? How have others gotten this to work? Or is there perhaps a way to avoid using claims, and instead use Windows authentication with xRM-in-claims-mode?