Microsoft Dynamics 365 Blog

This topic is about new authentication mechanism for accessing CRM Web Services that was in Dynamics CRM Live – Passport Authentication.

This new method requires you to jump a few more hoops before you can make your first web service call (after all we have now stepped out of our friendly AD neighborhood and are out in the Internet wilderness), but once you have the appropriate helper methods defined it’ll be just as easy as setting good old CredentialCache.DefaultCredentials.

There are 4 steps required in order to retrieve a proper CRM Ticket:


  1. Call CrmDiscoveryService to retrieve a Policy
  2. Use Policy to call Passport service to retrieve Passport Ticket
  3. Use Passport Ticket to call CrmDiscoveryService to retrieve list of Organziations and pick one of them that we want to make authenticated calls against
  4. Call CrmDiscoveryService with Passport Ticket and Orgnatization Name to retrieve Crm Ticket

Easy enough?… Not yet? Alright then, read on.

But first things first – I assume you have already downloaded CRM 4.0 SDK and unpacked it in, lets say, “C:\CrmSdk” folder.

Building CrmDiscoveryService DLL

In order to call CrmDiscoveryService methods we need an assembly that defines this web service methods. And there are two ways to build it:


  • Add it to your project directly as a WSDL file
  • Build it into DLL and add it as assembly reference

Since definition of CrmDiscoveryService is not changing I would recommend going with second method. Build a DLL once and reuse this same DLL in all projects calling CrmDiscoveryService by adding it as an assembly reference, simply because it is much easier to add an assembly reference than a web reference.

1. Open you Visual Studio command prompt (or your regular command prompt that knows a path to wsdl.exe) and go to:


> C:
> cd CrmSdk\sdk\wsdl


2. Build a C# proxy for crmdiscoveryservice.wsdl file with following command:


> wsdl /namespace:CrmSdk.CrmDiscoveryService /out:CrmDiscoveryService.cs crmdiscoveryservice.wsdl


3. Compile CrmDiscoveryService.cs file into a DLL:


> csc /target:library CrmDiscoveryService.cs


4. Create a BIN folder under C:\CrmSdk and move your CrmDiscoveryService.dll there:


> mkdir C:\CrmSdk\bin

> move CrmDiscoveryService.dll C:\CrmSdk\bin


Note that we specified CrmSdk.CrmDiscoveryService namespace for this DLL, this is important so there will be no conflicts with main CrmService proxy.

Building a Passport Service Helper

Now, the second component that we will need is a wrapper around IDCRL library that is required to talk to Passport Service.

Why do we need a wrapper? Well… take a look at the code that it consists of and tell me – do you want to write this stuff every time you need to get a Passport ticket?… I didn’t think so.

The wrapper project is located in “C:\CrmSdk\sdk\server\helpers\cs\idcrlwrapper” folder. In the SDK it is constructed as a sample code. But what we need is a library. So personally I would apply the following 2 modifications to the Program.cs before building it:


  • Delete Program class from it (don’t delete anything else, it’s all good stuff! :o)
  • Rename namespace “Microsoft.Crm.Passport.Sample” to “CrmSdk.Passport” (unless you really like that original name and want to include it in all of your programs)

Now:


  1. Build this project.
  2. Apply environments.reg registry file to your environment (it contains registry values that are needed for IDCRL library, so naturally you’ll need to apply them on all machines where you want to run your code calling into CRM Live web services)
  3. Copy IdCrlWrapper.dll to “C:\CrmSdk\bin” folder

Getting CrmTicket

Okay, now that we have paid our dues of tedium to the programming Gods and have CrmDiscoveryService.dll and IdCrlWrapper.dll in our possession it is time to do some actual coding.

Here is a helper function that I would suggest you add somewhere in your code that will retrieve a CrmTicket and OrganizationDetail information for you.


public string GetCrmTicket(string liveusername, string livepassword, string orgname, out OrganizationDetail orgdetail)

{

// Create and configure the CrmDiscoveryService Web service.

CrmDiscoveryService discoveryService = new CrmDiscoveryService();

discoveryService.Url =

“https://dev.crm.dynamics.com/MSCRMServices/2007/Passport/CrmDiscoveryService.asmx”;

// Retrieve a policy from the Web service.

RetrievePolicyRequest policyRequest = new RetrievePolicyRequest();

RetrievePolicyResponse policyResponse =

(RetrievePolicyResponse)discoveryService.Execute(policyRequest);

string partner = “crm.dynamics.com”;

// Retrieve a ticket from the Windows Live (Passport) service.

LogonManager lm = new LogonManager();

string passportTicket = lm.Logon(liveusername, livepassword, partner,

policyResponse.Policy, “Production”);

// Dispose of the LogonManager object to avoid a FileNotOpen exception.

lm.Dispose();

// Retrieve a CrmTicket from the Web service.

RetrieveCrmTicketRequest crmTicketRequest = new RetrieveCrmTicketRequest();

crmTicketRequest.OrganizationName = orgname;

crmTicketRequest.PassportTicket = passportTicket;

RetrieveCrmTicketResponse crmTicketResponse =

(RetrieveCrmTicketResponse)discoveryService.Execute(crmTicketRequest);

orgdetail = crmTicketResponse.OrganizationDetail;

return crmTicketResponse.CrmTicket;

}


Calling CRM Live Web Service

If you have read to this point you probably thinking “Where exactly is the “easy” part that was promised in the beginning?” Not to worry. The hard part is over (forever)! From now on the call to CRM Live Web Service will look like this:


public Guid WhoAmI()

{

// Set up the CRM Service

OrganizationDetail orgDetail;

CrmAuthenticationToken token = new CrmAuthenticationToken();

token.AuthenticationType = 1;

token.OrganizationName = “AdventureWorksCycle”;

token.CrmTicket = GetCrmTicket(“crmuser@live.com”, “crmuser_password”, “AdventureWorksCycle”, out orgDetail);

CrmService Service = new CrmService();

Service.Url = orgDetail.CrmServiceUrl;

Service.CrmAuthenticationTokenValue = token;

// Call WhoAmI()

WhoAmIRequest req = new WhoAmIRequest();

WhoAmIResponse resp = (WhoAmIResponse) Service.Execute(req);

return resp.UserId;

}


Where of course “Set up the CRM Service” part should be done only one time somewhere in your application (could be defined as a property for example):


private CrmService _service;

public CrmService Service

{

get

{

if (_service == null)

{

// Set up the CRM Service.

OrganizationDetail orgDetail;

CrmAuthenticationToken token = new CrmAuthenticationToken();

token.AuthenticationType = 1;

token.OrganizationName = “AdventureWorksCycle”;

token.CrmTicket = GetCrmTicket(“crmuser@live.com”, “crmuser_password”, “AdventureWorksCycle”, out orgDetail);

_service = new CrmService();

_service.Url = orgDetail.CrmServiceUrl;

_service.CrmAuthenticationTokenValue = token;

}

return _service;

}

}


Obviously user credentials and organization name will not be hard coded in your application, but you get the idea.

So, to review, what we have done was:


  1. We have built CrmDiscoveryService proxy DLL
  2. We have built IdCrl library wrapper DLL (to access Passport services)
  3. Wrote some helpers to retrieve CrmTicket for given CRM Live user and organization
  4. Wrote a helper to prepare CrmService using CrmAuthenticationToken set up with CrmTicket (step 3)

And for the next project all we will have to do will be – reference those DLLs in project and use CrmService helper. That’s pretty easy I would say.

Alexander Panov

We're always looking for feedback and would like to hear from you. Please head to the Dynamics 365 Community to start a discussion, ask questions, and tell us what you think!