Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Authenticating to Microsoft Dynamic CRM

by mart1076 (Initiate)
on Jul 16, 2009 at 17:32 UTC ( [id://780789]=perlquestion: print w/replies, xml ) Need Help??

mart1076 has asked for the wisdom of the Perl Monks concerning the following question:

I am attempting to login to Microsoft Dynamic CRM from Linux. The CRM software is configured to use NTLM for authentication. I have installed Authen::NTLM and was still unable to authenticate to the CRM software but was able to authenticate to Sharepoint. I found this information about Negotiate (found at http://davenport.sourceforge.net/ntlm.html#ntlmHttpAuthentication) “With Windows 2000, Microsoft introduced the "Negotiate" HTTP authentication mechanism. While primarily aimed at providing a means of authenticating the user against Active Directory via Kerberos, it is backward-compatible with the NTLM scheme. When the Negotiate mechanism is used in "legacy" mode, the headers passed between the client and server are identical, except "Negotiate" (rather than "NTLM") is indicated as the mechanism name. “ and then installed LWP::Authen::Negotiate because the authentication had Negotiate before the authentication strings but have still been unable to successfully authenticate. Below is the script and result I receive (after I have authenticated to a domain). Does anyone have any advice on how to successfully authenticate to the CRM software?
Script: use LWP::Debug qw(+); use LWP::UserAgent; my $url = 'http:// xxxxx.xxx.xxx /'; # Set up the ntlm client and then the base64 encoded ntlm handshake me +ssage my $ua = new LWP::UserAgent(keep_alive=>1); $ua->credentials(xxxxx.xxx.xxx:80', '', 'xxx\xxxxxxxxxxxxx' => 'xxxxxx +xxxxxx'); #$request = GET $url; my $request = new HTTP::Request GET => $url; print "--Performing request now...-----------\n"; $response = $ua->request($request); print "--Done with request-------------------\n"; #my $content = $response->content; my $content = $response->as_string; print $content . "\n"; if ($response->is_success) {print "It worked!->" . $response->code . " + " . $response->message . "\n"} else {print "It didn't work!->" . $response->code . "\n"} Result with only Authen::NTLM installed: LWP::UserAgent::new: () --Performing request now...----------- LWP::UserAgent::request: () LWP::UserAgent::send_request: GET http:// xxxxx.xxx.xxx LWP::UserAgent::_need_proxy: Not proxied LWP::Protocol::http::request: () LWP::Protocol::collect: read 51 bytes LWP::Protocol::http::request: Keep the http connection to xxxxx.xxx.xx +x:80 LWP::UserAgent::request: Simple response: Unauthorized LWP::Authen::Ntlm::authenticate: authenticate() has been called Use of uninitialized value in exists at /usr/lib/perl5/site_perl/5.8.3 +/LWP/UserAgent.pm line 566. Use of uninitialized value in hash element at /usr/lib/perl5/site_perl +/5.8.3/LWP/UserAgent.pm line 567. LWP::Authen::Ntlm::authenticate: In first phase of NTLM authentication LWP::Authen::Ntlm::authenticate: Returning response object with auth h +eader: Authorization NTLM TlRMTVNTUAABAAAAB7IAABQAFAAgAAAABgAGADQAAABpY3MtZW5 +nLW1vbi1vcGluaW9ubHN0Z2xkcw== LWP::UserAgent::request: () LWP::UserAgent::send_request: GET http:// xxxxx.xxx.xxx LWP::UserAgent::_need_proxy: Not proxied LWP::Protocol::http::request: () LWP::Protocol::collect: read 100 bytes LWP::UserAgent::request: Simple response: Internal Server Error --Done with request------------------- HTTP/1.1 500 Internal Server Error Connection: close Date: Thu, 16 Jul 2009 17:13:30 GMT Server: Microsoft-IIS/6.0 Content-Length: 100 Content-Type: text/html Client-Date: Thu, 16 Jul 2009 17:12:31 GMT Client-Peer: 10.96.114.26:80 Client-Response-Num: 2 Title: Error X-Powered-By: ASP.NET <html><head><title>Error</title></head><body>The function requested is + not supported </body></html> It didn't work!->500 Result with LWP::Authen::Negotiate installed: LWP::UserAgent::new: () --Performing request now...----------- LWP::UserAgent::request: () LWP::UserAgent::send_request: GET http://xxxxx.xxx.xxx/ LWP::UserAgent::_need_proxy: Not proxied LWP::Protocol::http::request: () LWP::Protocol::collect: read 51 bytes LWP::Protocol::http::request: Keep the http connection to xxxxx.xxx.xx +x/:80 LWP::UserAgent::request: Simple response: Unauthorized LWP::Authen::Negotiate::authenticate: authenticate() version 0.06 call +ed LWP::Authen::Negotiate::authenticate: target hostname xxxxx.xxx.xxx LWP::Authen::Negotiate::authenticate: GSSAPI servicename HTTP@ xxxxx.x +xx.xxx LWP::Authen::Negotiate::authenticate: successfull $ctx->init() LWP::UserAgent::request: () LWP::UserAgent::send_request: GET http:// xxxxx.xxx.xxx / LWP::UserAgent::_need_proxy: Not proxied LWP::Protocol::http::request: () LWP::Protocol::collect: read 51 bytes LWP::Protocol::http::request: Keep the http connection to xxxxx.xxx.xx +x:80 LWP::UserAgent::request: Simple response: Unauthorized LWP::Authen::Negotiate::authenticate: authenticate() version 0.06 call +ed LWP::Authen::Negotiate::authenticate: target hostname xxxxx.xxx.xxx LWP::Authen::Negotiate::authenticate: GSSAPI servicename HTTP@ xxxxx.x +xx.xxx LWP::Authen::Negotiate::authenticate: Invalid token was supplied LWP::Authen::Negotiate::authenticate: No error --Done with request------------------- HTTP/1.1 401 Unauthorized Date: Tue, 14 Jul 2009 15:35:29 GMT Server: Microsoft-IIS/6.0 WWW-Authenticate: Negotiate YIGWBgkqhkiG9xIBAgIDAH6BhjCBg6ADAgEFoQMCAR +6kERgPMjAwOTA3MTQxNTM1MjlapQUCAwnxTqYDAgE8qRMbEVNURy5MRFNDSFVSQ0guT1J +HqjAwLqADAgEDoScwJRsEaG9zdBsdY2hxcHZ1dzg0MDQuc3RnLmxkc2NodXJjaC5vcmes +EQQPMA2hAwIBAaIGBARqAADA Content-Length: 51 Content-Type: text/plain Client-Date: Tue, 14 Jul 2009 15:34:38 GMT Client-Peer: 10.96.114.26:80 Client-Response-Num: 2 X-Powered-By: ASP.NET HTTP Error 401.1 - Unauthorized: Access is denied

Replies are listed 'Best First'.
Re: Authenticating to Microsoft Dynamic CRM
by rdfield (Priest) on Mar 05, 2014 at 17:55 UTC
    Having looked at various pieces of code in other languages (e.g. http://crmtroubleshoot.blogspot.co.uk/2013/07/dynamics-crm-2011-php-and-soap-using.html with http://crmtroubleshoot.blogspot.co.uk/2013/07/dynamics-crm-2011-php-and-soap-calls.html and http://blogs.msdn.com/b/girishr/archive/2011/02/04/connecting-to-crm-online-2011-web-services-using-soap-requests-only.aspx), I've cobbled this together, which logs into CRM Dynamics from Perl:
    use strict; use warnings; use WWW::Curl::Easy; use Data::GUID; use Date::Manip; use XML::Simple; use Data::Dumper; sub make_guid { my $guidobj = Data::GUID->new; return $guidobj->as_string; } sub curl_request { my ($url,$data) = @_; my $headers = [ 'Connection: Keep-Alive', "Content-type: application/soap+xml; charset=UTF-8", "Content-length: " . length($data), ]; my $curl = WWW::Curl::Easy->new; $curl->setopt(CURLOPT_URL, $url); $curl->setopt(CURLOPT_TIMEOUT, 60); $curl->setopt(CURLOPT_SSL_VERIFYPEER, 0); $curl->setopt(CURLOPT_FOLLOWLOCATION, 1); $curl->setopt(CURLOPT_SSLVERSION, 3); $curl->setopt(CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); $curl->setopt(CURLOPT_HTTPHEADER, $headers); $curl->setopt(CURLOPT_POST, 1); $curl->setopt(CURLOPT_POSTFIELDS, $data); my $response_body; $curl->setopt(CURLOPT_WRITEDATA,\$response_body); my $retcode = $curl->perform; return $retcode, $response_body; } my $guid = make_guid; my $reqguid = make_guid; my $region = 'urn:crmemea:dynamics.com'; # use your region my $username = 'youremailaddress'; my $password = 'yourpassword'; my $host = "yourhost.crm4.dynamics.com"; # use crm5 etc depending on r +egion my $loginurl = 'https://login.microsoftonline.com/RST2.srf'; my $serviceurl = "https://$host/XRMServices/2011/Organization.svc"; my $OCPRequest = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap- +envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="htt +p://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utili +ty-1.0.xsd"> <s:Header> <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/200 +5/02/trust/RST/Issue</a:Action> <a:MessageID>urn:uuid:' . $guid . '</a:MessageID> <a:ReplyTo> <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:A +ddress> </a:ReplyTo> <a:To s:mustUnderstand="1">https://login.microsoftonline.com/RST +2.srf</a:To> <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open +.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <u:Timestamp u:Id="_0"> <u:Created>'. UnixDate(ParseDate("now"), "%Y-%m-%dT%H:%M:%S").' +Z</u:Created> <u:Expires>' . UnixDate(ParseDate("24 hours"), "%Y-%m-%dT%H:%M +:%S") . 'Z</u:Expires> </u:Timestamp> <o:UsernameToken u:Id="uuid-cdb639e6-f9b0-4c01-b454-0fe244de73 +af-1"> <o:Username>' . $username . '</o:Username> <o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis- +200401-wss-username-token-profile-1.0#PasswordText">' . $password . ' +</o:Password> </o:UsernameToken> </o:Security> </s:Header> <s:Body> <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2 +005/02/trust"> <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/0 +9/policy"> <a:EndpointReference> <a:Address>'. $region .'</a:Address> </a:EndpointReference> </wsp:AppliesTo> <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Iss +ue</t:RequestType> </t:RequestSecurityToken> </s:Body> </s:Envelope>'; my ($retcode, $response); ($retcode, $response) = curl_request($loginurl, $OCPRequest); if ($retcode) { die("An error logging in\n"); } my $xml = XMLin($response); my $cipher1 = $xml->{"S:Body"}{'wst:RequestSecurityTokenResponse'}{'ws +t:RequestedSecurityToken'}{'EncryptedData'}{'ds:KeyInfo'}{'EncryptedK +ey'}{'CipherData' }{'CipherValue'}; my $cipher2 = $xml->{"S:Body"}{'wst:RequestSecurityTokenResponse'}{'ws +t:RequestedSecurityToken'}{'EncryptedData'}{ 'CipherData'}{'CipherVal +ue'}; my $keyidentifier = $xml->{"S:Body"}{'wst:RequestSecurityTokenResponse +'}{'wst:RequestedSecurityToken'}{'EncryptedData'}{ 'ds:KeyInfo'}{'Enc +ryptedKey'}{'ds:KeyInfo'}{'wsse:SecurityTokenReference'}{'wsse:KeyIde +ntifier'}{'content'}; my $action = "Execute"; # or Retrieve, Create etc my $envelope_start = ' <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-en +velope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis- +200401-wss-wssecurity-utility-1.0.xsd">'; my $crmSoapRequestHeader = ' <s:Header> <a:Action s:mustUnderstand="1"> http://schemas.microsoft.com/xrm/2011/Contracts/Se +rvices/IOrganizationService/' . $action . '</a:Action> <a:MessageID> urn:uuid:' . $reqguid . '</a:MessageID> <a:ReplyTo> <a:Address> http://www.w3.org/2005/08/addressing/anonymous</ +a:Address> </a:ReplyTo> <a:To s:mustUnderstand="1"> ' . $serviceurl . '</a:To> <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oa +sis-200401-wss-wssecurity-secext-1.0.xsd"> <u:Timestamp u:Id="_0"> <u:Created>' .UnixDate(ParseDate("now"), "%Y-% +m-%dT%H:%M:%S") . 'Z</u:Created> <u:Expires>' . UnixDate(ParseDate("24 hours"), + "%Y-%m-%dT%H:%M:%S") . 'Z</u:Expires> </u:Timestamp> <EncryptedData Id="Assertion0" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns="http://www.w3.org/2001/04/xmlenc#"> <EncryptionMethod Algorithm="http://www.w3.org +/2001/04/xmlenc#tripledes-cbc"> </EncryptionMethod> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/0 +9/xmldsig#"> <EncryptedKey> <EncryptionMethod Algorithm="http://www.w3 +.org/2001/04/xmlenc#rsa-oaep-mgf1p"> </EncryptionMethod> <ds:KeyInfo Id="keyinfo"> <wsse:SecurityTokenReference xmlns:wsse= +"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-s +ecext-1.0.xsd"> <wsse:KeyIdentifier EncodingType="http +://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-secu +rity-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/ +wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIde +ntifier"> ' . $keyidentifier . ' </wsse:KeyIdentifier> </wsse:SecurityTokenReference> </ds:KeyInfo> <CipherData> <CipherValue> ' . $cipher1 . ' </CipherValue> </CipherData> </EncryptedKey> </ds:KeyInfo> <CipherData> <CipherValue> ' . $cipher2 . ' </CipherValue> </CipherData> </EncryptedData> </o:Security> </s:Header> '; my $retrieveMultipleRequestBodyTemplate =' <s:Body> <Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Ser +vices" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <request i:type="b:WhoAmIRequest" xmlns:a="http://schemas.microsof +t.com/xrm/2011/Contracts" xmlns:b="http://schemas.microsoft.com/crm/2 +011/Contracts"> <a:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/Sy +stem.Collections.Generic" /> <a:RequestId i:nil="true" /> <a:RequestName>WhoAmI</a:RequestName> </request> </Execute> </s:Body> '; my $envelope_end = ' </s:Envelope>'; ($retcode, $response) = curl_request($serviceurl,$envelope_start . $cr +mSoapRequestHeader . $retrieveMultipleRequestBodyTemplate . $envelope +_end); if ($retcode == 0) { print("Transfer went ok\n"); print("Received response: $response\n"); } else { print("An error happened: $retcode \n"); print $envelope_start . $crmSoapRequestHeader . $retrieveMultipleRe +questBodyTemplate . $envelope_end }

    rdfield

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://780789]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-04-19 07:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found