FYI - this is probably only useful in a limited set of circumstances like a Windows 8 application using JavaScript or something that resides in the same domain as a browser handles executing the request a bit differently when the request is made between 2 different domains (CORS).
In this sample, Xrm.CRMAuth.GetHeaderOnPremise returns an object that contains the header which can be injected into a SOAP request as well as the expiration date of the header so you can check that date/time versus the current date/time to determine if it has expired or not.
Xrm = window.Xrm || { __namespace: true }; Xrm.CRMAuth = Xrm.CRMAuth || { __namespace: true }; /// <summary>Gets a CRM On Premise SOAP header & expiration.</summary> /// <param name="url" type="String">The Url of the CRM On Premise (IFD) organization (https://org.domain.com).</param> /// <param name="domain" type="String">Domain name of a vaid CRM user.</param> /// <param name="username" type="String">Username of a valid CRM user.</param> /// <param name="password" type="String">Password of a valid CRM user.</param> /// <returns type="Object">An object containing the SOAP header and expiration date/time of the header.</returns> Xrm.CRMAuth.GetHeaderOnPremise = function (url, domain, username, password) { if (!url.match(/\/$/)) url += "/"; username = domain + "\\" + username; var adfsUrl = Xrm.CRMAuth.GetADFS(url); var now = new Date(); var urnAddress = url + 'XRMServices/2011/Organization.svc'; var usernamemixed = adfsUrl + '/13/usernamemixed'; var xml = []; xml.push('<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">'); xml.push('<s:Header>'); xml.push('<a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action>'); xml.push('<a:MessageID>urn:uuid:' + Xrm.CRMAuth.CreateGuid() + '</a:MessageID>'); xml.push('<a:ReplyTo>'); xml.push('<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>'); xml.push('</a:ReplyTo>'); xml.push('<Security s:mustUnderstand="1" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">'); xml.push('<u:Timestamp u:Id="' + Xrm.CRMAuth.CreateGuid() + '">'); xml.push('<u:Created>' + now.toISOString() + '</u:Created>'); xml.push('<u:Expires>' + new Date(now.setMinutes(now.getMinutes() + 5)).toISOString() + '</u:Expires>'); xml.push('</u:Timestamp>'); xml.push('<UsernameToken u:Id="' + Xrm.CRMAuth.CreateGuid() + '">'); xml.push('<Username>' + username + '</Username>'); xml.push('<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">' + password + '</Password>'); xml.push('</UsernameToken>'); xml.push('</Security>'); xml.push('<a:To s:mustUnderstand="1">' + usernamemixed + '</a:To>'); xml.push('</s:Header>'); xml.push('<s:Body>'); xml.push('<trust:RequestSecurityToken xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">'); xml.push('<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">'); xml.push('<a:EndpointReference>'); xml.push('<a:Address>' + urnAddress + '</a:Address>'); xml.push('</a:EndpointReference>'); xml.push('</wsp:AppliesTo>'); xml.push('<trust:RequestType>http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue</trust:RequestType>'); xml.push('</trust:RequestSecurityToken>'); xml.push('</s:Body>'); xml.push('</s:Envelope>\n'); var authentication = {}; var request = xml.join(""); var req = new XMLHttpRequest(); req.open("POST", usernamemixed, false); req.setRequestHeader("Connection", "Keep-Alive"); req.setRequestHeader("Content-Type", "application/soap+xml; charset=UTF-8"); req.onreadystatechange = function () { if (req.readyState === 4) { if (req.status === 200) { var token0 = $(req.response).find("e\\:CipherValue"); var token1 = $(req.response).find("xenc\\:CipherValue"); var keyIdentifer = $(req.response).find("o\\:KeyIdentifier"); var issuerNameX509 = $(req.response).find("X509IssuerName"); var serialNumberX509 = $(req.response).find("X509SerialNumber"); var serverSecret = $($(req.response).find("trust\\:BinarySecret")[0]).text(); var created = new Date(now.setMinutes(now.getMinutes() - 1)).toISOString(); var expires = new Date(now.setMinutes(now.getMinutes() + 60)).toISOString(); var timestamp = '<u:Timestamp xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" u:Id="_0"><u:Created>' + created + '</u:Created><u:Expires>' + expires + '</u:Expires></u:Timestamp>'; var hashObj = new jsSHA(timestamp, "TEXT"); var digestValue = hashObj.getHash("SHA-1", "B64", 1); var signedInfo = '<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"></SignatureMethod><Reference URI="#_0"><Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>' + digestValue + '</DigestValue></Reference></SignedInfo>'; var b64SignedInfo = Base64.encode(signedInfo); var shaObj = new jsSHA(b64SignedInfo, "B64"); var signatureValue = shaObj.getHMAC(serverSecret, "B64", "SHA-1", "B64"); authentication.TokenExpires = $(req.response).find("wsu\\:Expires:first").text(); authentication.Header = Xrm.CRMAuth.CreateSOAPHeaderOnPremise(url, $(keyIdentifer[0]).text(), $(token0[0]).text(), $(token1[0]).text(), $(issuerNameX509[0]).text(), $(serialNumberX509[0]).text(), signatureValue, digestValue, created, expires); } } }; req.send(request); return authentication; }; /// <summary>Gets the name of the ADFS server CRM uses for authentication.</summary> /// <param name="url" type="String">The Url of the CRM On Premise (IFD) organization (https://org.domain.com).</param> /// <returns type="String">The ADFS server url.</returns> Xrm.CRMAuth.GetADFS = function (url) { var adfsUrl = null; var req = new XMLHttpRequest(); req.open("GET", url + "/XrmServices/2011/Organization.svc?wsdl=wsdl0", false); req.setRequestHeader("Connection", "Keep-Alive"); req.setRequestHeader("Content-Type", "application/soap+xml; charset=UTF-8"); req.onreadystatechange = function () { if (req.readyState === 4) { if (req.status === 200) { adfsUrl = $(req.response).find("ms-xrm\\:Identifier"); } } }; req.send(); return $(adfsUrl[0]).text().replace("http://", "https://"); }; /// <summary>Gets a CRM On Premise (IFD) SOAP header.</summary> /// <param name="url" type="String">The Url of the CRM On Premise (IFD) organization (https://org.domain.com).</param> /// <param name="keyIdentifer" type="String">The KeyIdentifier from the initial request..</param> /// <param name="token0" type="String">The first token from the initial request.</param> /// <param name="token1" type="String">The second token from the initial request.</param> /// <param name="issuerNameX509" type="String">The certificate issuer.</param> /// <param name="serialNumberX509" type="String">The certificate serial number.</param> /// <param name="signatureValue" type="String">The hashsed value of the header signature.</param> /// <param name="digestValue" type="String">The hashed value of the header timestamp.</param> /// <param name="created" type="String">The header created date/time.</param> /// <param name="expires" type="String">The header expiration date/tim.</param> /// <returns type="String">The XML SOAP header to be used in future requests.</returns> Xrm.CRMAuth.CreateSOAPHeaderOnPremise = function (url, keyIdentifer, token0, token1, issuerNameX509, serialNumberX509, signatureValue, digestValue, created, expires) { var xml = []; xml.push('<s:Header>'); xml.push('<a:Action s:mustUnderstand="1">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute</a:Action>'); xml.push('<a:MessageID>urn:uuid:' + Xrm.CRMAuth.CreateGuid() + '</a:MessageID>'); xml.push('<a:ReplyTo>'); xml.push('<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>'); xml.push('</a:ReplyTo>'); xml.push('<a:To s:mustUnderstand="1">' + url + 'XRMServices/2011/Organization.svc</a:To>'); xml.push('<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">'); xml.push('<u:Timestamp xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" u:Id="_0">'); xml.push('<u:Created>' + created + '</u:Created>'); xml.push('<u:Expires>' + expires + '</u:Expires>'); xml.push('</u:Timestamp>'); xml.push('<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">'); xml.push('<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>'); xml.push('<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">'); xml.push('<e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#">'); xml.push('<e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p">'); xml.push('<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>'); xml.push('</e:EncryptionMethod>'); xml.push('<KeyInfo>'); xml.push('<o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">'); xml.push('<X509Data>'); xml.push('<X509IssuerSerial>'); xml.push('<X509IssuerName>' + issuerNameX509 + '</X509IssuerName>'); xml.push('<X509SerialNumber>' + serialNumberX509 + '</X509SerialNumber>'); xml.push('</X509IssuerSerial>'); xml.push('</X509Data>'); xml.push('</o:SecurityTokenReference>'); xml.push('</KeyInfo>'); xml.push('<e:CipherData>'); xml.push('<e:CipherValue>' + token0 + '</e:CipherValue>'); xml.push('</e:CipherData>'); xml.push('</e:EncryptedKey>'); xml.push('</KeyInfo>'); xml.push('<xenc:CipherData>'); xml.push('<xenc:CipherValue>' + token1 + '</xenc:CipherValue>'); xml.push('</xenc:CipherData>'); xml.push('</xenc:EncryptedData>'); xml.push('<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">'); xml.push('<SignedInfo>'); xml.push('<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>'); xml.push('<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"/>'); xml.push('<Reference URI="#_0">'); xml.push('<Transforms>'); xml.push('<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>'); xml.push('</Transforms>'); xml.push('<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>'); xml.push('<DigestValue>' + digestValue + '</DigestValue>'); xml.push('</Reference>'); xml.push('</SignedInfo>'); xml.push('<SignatureValue>' + signatureValue + '</SignatureValue>'); xml.push('<KeyInfo>'); xml.push('<o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">'); xml.push('<o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">' + keyIdentifer + '</o:KeyIdentifier>'); xml.push('</o:SecurityTokenReference>'); xml.push('</KeyInfo>'); xml.push('</Signature>'); xml.push('</o:Security>'); xml.push('</s:Header>'); return xml.join(""); }; /// <summary>Creates a GUID.</summary> /// <returns type="String">GUID.</returns> Xrm.CRMAuth.CreateGuid = function () { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); };
Also note this code takes a dependency on jQuery as well as jsSHA (sha1.js).
So in action, it would look something like this:
var domain = "domain"; var username = "admin"; var password = "password"; var CRMSoapAuthentication = Xrm.CRMAuth.GetHeaderOnPremise(url, domain, username, password); var body = []; body.push('<s:Body>'); body.push('<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">'); body.push(' <request i:type="c:WhoAmIRequest" xmlns:b="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:c="http://schemas.microsoft.com/crm/2011/Contracts">'); body.push(' <b:Parameters xmlns:d="http://schemas.datacontract.org/2004/07/System.Collections.Generic"/>'); body.push(' <b:RequestId i:nil="true"/>'); body.push(' <b:RequestName>WhoAmI</b:RequestName>'); body.push(' </request>'); body.push('</Execute>'); body.push('</s:Body>'); var xml = []; xml.push('<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">'); xml.push(CRMSoapAuthentication.Header); xml.push(body.join("")); xml.push('</s:Envelope>'); var request = xml.join(""); var req = new XMLHttpRequest(); req.open("POST", url + "XRMServices/2011/Organization.svc", true); req.setRequestHeader("Content-Type", "application/soap+xml; charset=utf-8"); req.onreadystatechange = function () { if (req.readyState === 4) { if (req.status === 200) { //Handle the response } } else { //Error } }; req.send(request);