none
access CRM web API from other federation domain using WS-Fed or SAML RRS feed

  • Question

  • Hi,

    We have a middle-ware system (system A) which needs to access CRM web API (system B)from another federation domain. In the development environment, we use WS-Fed. The the production env, we used SAML claims. 

    Since this is machine to machine and through different federation, I am wondering what is the best approach to accommodate this GET action.

    1: I tried to use ASP.NET to mimic the relying party to call the federation url ( STS). It worked, however the credential cannot be passed through. I hope we could use code from system A to access system B without manual interruptions. I could see the session could be established once the cookies obtained. However, I have to manually enter the password, even though the user  name has been accepted in the signing in request message.

    I mainly used Microsoft Identity dll. Would the new OWIN package give me more advantage on this topic?

    2. Are there better way to accommodate this kind of action on accessing two different federation systems and using machine to machine talk mechanism simply and easily? 

    thanks and regards,


    Thursday, May 9, 2019 2:18 PM

All replies

  • Is this an ASP.NET app? If so then please post your question in the ASP.NET forums. If this is a Windows app then most APIs are REST based now and support using OAuth2 which is how server-to-server communication is implemented these days.

    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, May 9, 2019 2:47 PM
    Moderator
  • Thank you Michael for your reply. 

    Actually, we have not decide what is the best approach. We have system A ( as I mentioned above), it is a middle-ware ( like Oracle service bus or other middle-ware) which needs to access system B ( CRM system).

    I need to create some artifacts ( like services or apps) to invoke system B to create entry in CRM system. As the systems are in different federation, I need use code to send credentials to the STS. 

    Even more, at production environment, I need to create SAML request and pass the certificate of the middle-ware ( system A) to system B to get SAML claims.

    Is there any samples to use latest Microsoft dll to accomplish this actions?

    thanks


    Thursday, May 9, 2019 3:54 PM
  • For WS-Fed I'd wonder about the credentials not going through because of a trust relationship between the domains but I'm just guessing here based upon issues I saw years ago when we were implementing WS-Fed in a web app.

    I don't have any experience trying to get WS-Fed working outside of that system but System.IdentityModel.Services contains the core types for WSFed in .NET Framework. Here's a blog article on using the older Microsoft.IdentityModel framework (which is now System.IdentityModel) to connect to an ADFS secured API from a console app. Even if it doesn't quite match your scenario it has some code that may help you find what you're looking for.

    There is a SO post that talks about someone trying to do something similar to what you're doing outside a web app. You might be able to get their code to work for you.

    OWIN, in newer versions of .NET and .NET Core, also supports this. I've never seen OWIN used outside a web app but in theory OWIN doesn't care about the underlying host, it just configures the pipeline. Ultimately it is hosting a web server inside a regular app.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, May 9, 2019 4:10 PM
    Moderator
  • Thank you so much. Michael. 

    I will try the console app and I will update status here.

    Regards,

    M

    Thursday, May 9, 2019 6:29 PM
  • I used MS System.IdentityModel dll and tried to get token from STS. However, I got exception at the stop of Issue() to work. 

    Following is code and my sample RequestSecurityTokenResponse sample. I changed to use TrustVersion.WSTrustFeb2005 as I saw response use this version : "http://schemas.xmlsoap.org/ws/2005/02/trust".

    The last step at Issue() never can get through. It throws exception on context-type.

    Could someone help to see the problem on the WSTrustChannelFactory ? 

    Is the TokenType I used correct?

    Thanks a lot!

    "

    System.ServiceModel.ProtocolException

      HResult=0x80131501

      Message=The content type text/html; charset=utf-8 of the response message does not match the content type of the binding (application/soap+xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 1024 bytes of the response were: ' <!DOCTYPE html>

    <html lang="en-US">

        <head>

    ......."

    code : 

               var binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);

                binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

                var factory = new WSTrustChannelFactory(binding, fedAddress);

                factory.TrustVersion = TrustVersion.WSTrustFeb2005; // WSTrust13;

                factory.Credentials.UserName.UserName = userName;

                factory.Credentials.UserName.Password = Password;

                var rst = new RequestSecurityToken

                {

                    RequestType = RequestTypes.Issue,

                    KeyType = KeyTypes.Bearer,

                    TokenType = "urn:oasis:names:tc:SAML:1.0:assertion",                  

                    AppliesTo = new EndpointReference(svcAddress)

                };                                 

                return factory.CreateChannel().Issue(rst);

    sample response: 

    <?xml version="1.0" encoding="UTF-8"?>
    <t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
       <t:Lifetime>
          <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2019-05-13T18:40:11.282Z</wsu:Created>
          <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2019-05-14T06:40:11.282Z</wsu:Expires>
       </t:Lifetime>
       <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
          <wsa:EndpointReference xmlns:wsa="http://www.w3.org/2005/08/addressing">
             <wsa:Address>https://myCRM.com/</wsa:Address>
          </wsa:EndpointReference>
       </wsp:AppliesTo>
       <t:RequestedSecurityToken>
          <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
             <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
             <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                <e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">
                   <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">
                      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                   </e:EncryptionMethod>
                   <KeyInfo>
                      <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
                         <X509Data>
                            <X509IssuerSerial>
                               <X509IssuerName>CN=Entrust Certification Authority - L1K, OU="(c) 2012 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US</X509IssuerName>
                               <X509SerialNumber>28...3716</X509SerialNumber>
                            </X509IssuerSerial>
                         </X509Data>
                      </o:SecurityTokenReference>
                   </KeyInfo>
                   <e:CipherData>
                      <e:CipherValue> .....==</e:CipherValue>
                   </e:CipherData>
                </e:EncryptedKey>
             </KeyInfo>
             <xenc:CipherData>
                <xenc:CipherValue>.... =</xenc:CipherValue>
             </xenc:CipherData>
          </xenc:EncryptedData>
       </t:RequestedSecurityToken>
       <t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
       <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
       <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
    </t:RequestSecurityTokenResponse>

    Monday, May 13, 2019 7:56 PM
  • "It throws exception on context-type."

    The content type it is returning is HTML instead of the expected XML. That generally means you're getting a server side error (404 or similar) instead of actually connecting. The HTML itself should indicate the error so take a look at the response it actually sent you and then scan down for the status code and actual error.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, May 14, 2019 3:19 AM
    Moderator
  • Thank you Michael.

    I checked detail of stack trace. It failed at HttpChannelUtilities.ValidateRequestReplyResponse().

    There is not much detail about this failure.


    maggiecandyland

    Thursday, May 16, 2019 6:19 PM
  • details of stack trace:

    Server stack trace:

       at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)

       at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

       at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)

       at System.ServiceModel.Channels.SecurityChannelFactory`1.SecurityRequestChannel.Request(Message message, TimeSpan timeout)

       at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.DoOperation(SecuritySessionOperation operation, EndpointAddress target, Uri via, SecurityToken currentToken, TimeSpan timeout)

       at System.ServiceModel.Security.SecuritySessionSecurityTokenProvider.GetTokenCore(TimeSpan timeout)

       at System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(TimeSpan timeout)

       at System.ServiceModel.Security.SecuritySessionClientSettings`1.ClientSecuritySessionChannel.OnOpen(TimeSpan timeout)

       at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)

       at System.ServiceModel.Channels.ReliableChannelBinder`1.ChannelSynchronizer.SyncWaiter.TryGetChannel()

       at System.ServiceModel.Channels.ReliableChannelBinder`1.ChannelSynchronizer.SyncWaiter.TryWait(TChannel& channel)

       at System.ServiceModel.Channels.ReliableChannelBinder`1.ChannelSynchronizer.TryGetChannel(Boolean canGetChannel, Boolean canCauseFault, TimeSpan timeout, MaskingMode maskingMode, TChannel& channel)

       at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode)

       at System.ServiceModel.Channels.RequestReliableRequestor.OnRequest(Message request, TimeSpan timeout, Boolean last)

       at System.ServiceModel.Channels.ReliableRequestor.Request(TimeSpan timeout)

       at System.ServiceModel.Channels.ClientReliableSession.Open(TimeSpan timeout)

       at System.ServiceModel.Channels.ReliableRequestSessionChannel.OnOpen(TimeSpan timeout)

       at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)

       at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)

       at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)

       at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)

       at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)

       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)

       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)

       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

    Exception rethrown at [0]:

       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)

       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)

       at System.ServiceModel.Security.IWSTrustContract.Issue(Message message)

       at System.ServiceModel.Security.WSTrustChannel.Issue(RequestSecurityToken rst, RequestSecurityTokenResponse& rstr)

       at System.ServiceModel.Security.WSTrustChannel.Issue(RequestSecurityToken rst)


    maggiecandyland

    Thursday, May 16, 2019 6:22 PM
  • This is happening on the response which correlates to the remote server returning an HTML error back instead of the expected XML. You're going to need to get the HTML to see what is failing. Wrap your call to Issue in a try-catch and grab the exception coming back. In the debugger look at the details to see what is going on.

    If for some reason you cannot get the exception details then use Fiddler to monitor the call so you can see the request sent and the response.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, May 16, 2019 6:52 PM
    Moderator