Integration between MS Dynamics CRM 2013 and LAMP

I am a web developer working at the back of my site. They want to integrate their existing CRM system with the new site, so the site can execute CRUD requests against the system. However, I am struggling to successfully authenticate with Microsoft systems and would like to help plan a better strategy for this to work.

System overview:

Server: MS Dynamics CRM 2013 (web-facing deployment) using Active Directory for authentication

Client: LAMP (Drupal 7 will be running, but this is the bit I really know how to use!)

First, I tried the authentication method described below in the Open the OAuth Endpoint URL section:

http://msdn.microsoft.com/en-gb/library/dn531009.aspx#bkmk_oauthurl

For this, I used the following curl from the command line:

curl -H "Authorization: Bearer" http://crm.example.com/XRMServices/2011/Organization.svc -v

      

Which gives the following output:

* Hostname was NOT found in DNS cache
*   Trying xx.xx.xx.xx...
* Connected to crm.example.com (xx.xx.xx.xx) port 80 (#0)
> GET /XRMServices/2011/Organization.svc HTTP/1.1
> User-Agent: curl/7.35.0
> Host: crm.example.com
> Accept: */*
> Authorization: Bearer
>
< HTTP/1.1 200 OK
< Cache-Control: private
< Content-Length: 3165
< Content-Type: text/html; charset=UTF-8
* Server Microsoft-IIS/8.0 is not blacklisted
< Server: Microsoft-IIS/8.0
< X-AspNet-Version: 4.0.30319
< Set-Cookie: ReqClientId=ee9c75fe-db2e-4775-a71e-c2708c46748b; expires=Tue, 14-Oct-2064 09:16:06 GMT; path=/; HttpOnly
< X-Powered-By: ASP.NET
< Date: Tue, 14 Oct 2014 09:16:06 GMT
<
<HTML>...

      

But authorization-uri is not mentioned :(

I have also tried the same command as URLs ending in 'discovery.svc,' organization.svc / web, 'discovery.svc / web. The last two include the "WWW-Authenticate" field in the response, as shown below:

< WWW-Authenticate: Negotiate
< WWW-Authenticate: NTLM

      

This led me to believe that I am trying to use the wrong method and should be looking at MSL NTLM authentication.

I established that PHP-cURL can use NTLM, so my second approach was to send a SOAP request from the code. Similar to the code in this StackOverflow thread:

php - crm 2011 access dynamics with web services

Here is my code:

//sample SOAP envelope from StackOverflow thead
$SOAPEnv = <<<ENV
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
 <s:Body>
  <Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services"
           xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
   <request i:type="b:AssignRequest"
            xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts"
            xmlns:b="http://schemas.microsoft.com/crm/2011/Contracts">
    <a:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
     <a:KeyValuePairOfstringanyType>
      <c:key>Target</c:key>
      <c:value i:type="a:EntityReference">
       <a:Id>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</a:Id>
       <a:LogicalName>account</a:LogicalName>
       <a:Name i:nil="true" />
      </c:value>
     </a:KeyValuePairOfstringanyType>
     <a:KeyValuePairOfstringanyType>
      <c:key>Assignee</c:key>
      <c:value i:type="a:EntityReference">
       <a:Id>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</a:Id>
       <a:LogicalName>systemuser</a:LogicalName>
       <a:Name i:nil="true" />
      </c:value>
     </a:KeyValuePairOfstringanyType>
    </a:Parameters>
    <a:RequestId i:nil="true" />
    <a:RequestName>Assign</a:RequestName>
   </request>
  </Execute>
 </s:Body>
</s:Envelope>
ENV;

$headers = array(
  'Method: POST',
  'Connection: Keep-Alive',
  'User-Agent: PHP-SOAP-CURL',
  'Content-Type: text/xml; charset=utf-8',
  "SOAPAction: http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute",  
);


$url = 'http://crm.example.com/XRMServices/2011/Organization.svc/web';
$username  = 'myusername';
$password  = 'MyP@55w0rd';

$ch = curl_init();

curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $SOAPEnv);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);

$output = curl_exec($ch);

      

And this will give a SOAP response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <s:Fault>
      <faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:FailedAuthentication</faultcode>
      <faultstring xml:lang="en-GB">Access is denied.</faultstring>
    </s:Fault>
  </s:Body>
</s:Envelope>

      

It is gratifying that this is a SOAP answer, so I feel like Im close. This is definitely an authentication with the credentials I provide, because if I change them, I don't get SOAP. But I feel like there needs to be another layer of authentication so the SOAP endpoint can know that it is a legitimate client.

So, I'm a bit stuck as the documentation on using SOAP with Dynamics seems to be written in terms of the SDK from Microsoft, and certainly doesn't help someone in my experience who really only knows PHP.

If anyone could provide any feedback on my approach, I would really appreciate it. If you could point me in the right direction to proceed further, that would be even better. And I don't have enough time for the project, so lay it out to the experts. Please note that Im a relatively new developer will apologize in advance if you need to skip your answers slightly :)

Thanks a lot Ashwah

+3


source to share


1 answer


I was struggling with something related. I could get some example Python code to connect to a cloud-based CRM version with a tenant name, but I was trying to integrate with a local / IFD install / install that had its own STS (security token). Using this domain didn't work for me. I couldn't figure out what the correct redirect_uri is.

Once I realized that I needed to connect to the CRI CRM endpoint to get the Bearer_uri authorizer, it worked for me.

If you have Dyanmic CRM instand in foo.crm.dynamics.com

, you can twist this

curl -I https://foo.crm.dynamics.com/api/data/v8.0/WhoAmI

Replace with the foo

name of your CRM instance and return something like this



HTTP / 1.1 401 Unauthorized
Cache-Control: private
Content-Length: 49
Content-Type: text / html
Server: Microsoft-IIS / 8.X
REQ_ID: 995XXXX-XXXX-XXXX-XXX-XXXXXXXXe7
Set-Cookie: ReqClientId = 95XXXX-XXXX-XXXX-XXX-XXXXXXXXe7; expires = Wed, XX-Jan-XX 15: MM: SS GMT; path = /; secure; HttpOnly
WWW-Authenticate: Bearer authorization_uri = https: //login.windows.net/62d6e7de-bbbb-cccc-dddd-4f9605b2ad79/oauth2/authorize, resource_id = https: //foo.crm.dynamics.com/
X-Powered-By: ASP.NET
...

The UUID 62d6e7de-bbbb-cccc-dddd-4f9605b2ad79

is what you are looking for. For some reason, I explained why I need to switch the domain from login.windows.net

to login.microsoftonline.com

.

https://login.microsoftonline.com/62d6e7de-bbbb-cccc-dddd-4f9605b2ad79

...

Then I was able to use this sample code with username and password and actually connect.

https://github.com/jlattimer/CrmWebApiPython/blob/master/CrmConnect

0


source







All Articles