Export (0) Print
Expand All

Walkthrough: Server to Server Authentication with CRM Online

banner art

[Applies to: Microsoft Dynamics CRM 4.0]

This walkthrough shows how to access Microsoft Dynamics CRM Online Web services by using Windows Live authentication. This scenario is used for accessing the Microsoft Dynamics CRM Web services from a Windows service, Web service, or ASPX page.

During this walkthrough you will learn how to do the following:

  • Use Visual Studio 2008 to create a console application that uses the Microsoft Dynamics CRM Online Web services.
  • Use Windows Live authentication to access the Microsoft Dynamics CRM Online Web services.

This walkthrough uses C# sample code only.  You can find the complete code sample in the SDK\Walkthroughs\Authentication\CS\ServerToServerNoCerts folder of the SDK download.

Prerequisites

In order to complete this walkthrough, you will need the following:

  • Visual Studio 2008
  • Microsoft Dynamics CRM Online user account that has security privileges to add a new account to your organization
  • Access to the SDK download (version 4.0.12 or higher)

Creating a Visual Studio 2008 Solution

Use Visual Studio to create a solution to build your code.

To create a Visual Studio solution

  1. In Microsoft Visual Studio, on the File menu, point to New, and then click Project to open the New Project dialog box.
  2. In the Project types pane, select Visual C#.
  3. In the Templates pane, click Console Application.
  4. Type a name for your project and then click OK.

Downloading the Web Service Description Files

For programming against Microsoft Dynamics CRM Online, you have to obtain local copies of the Web Service Description Language (WSDL) files for your organization. Be aware that for the WSDL to be complete, you must repeat the following procedure if you make any customizations to entities in your organization.

  1. Open a Web browser and enter the URL for the Microsoft Dynamics CRM Online portal. For example:
    http://crm.dynamics.com
    
  2. Click the CRM Online Login button, enter your Windows Live account logon information, and then click Sign in.
  3. In the Navigation pane click Settings.
  4. In the Settings pane click Customization.
  5. In the Customization area, click Download Web Service Description Files.
  6. Click the CrmService.asmx icon.
  7. When the Web browser displays the WSDL, save the XML to a file on your hard disk. The procedure for saving the file will be different depending on the Web browser that you are using. In Internet Explorer 7, click the Page menu, and then click Save.
  8. Click the CrmDiscoveryService.asmx icon.
  9. Download the WSDL as you did before in step 7. If you see a CrmDiscoveryService Web page instead of WSDL, click the Service Description link to obtain the WSDL.
  10. Close the Web browser window that contains the WSDL definitions and sign out of Microsoft Dynamics CRM Online.
  11. Alternately, instead of downloading the discovery service WSDL, you could use the CrmDiscoveryService.wsdl file that is provided in the SDK\WSDL folder of the SDK download.
  12. In addition, instead of downloading the CrmService.asmx WSDL, you could add references to your project for the CRM Online versions of the Microsoft.Crm.Sdk and Microsoft.Crm.SdkTypeProxy assemblies located in the SDK\bin\online or SDK\bin\64bit\online folders. For example, the sample at SDK\Walkthroughs\Authentication\CS\ServerToServerNoCerts uses these assemblies instead of the obtaining the CrmService.asmx WSDL. However, using the assemblies instead of the downloaded CrmService WSDL means that any entity customizations to your organization are not easily available to your project. You would have to use dynamic entities in your code to access those custom entities.

Adding References

You have to add references to the required Microsoft Dynamics CRM Online Web services; in this case, you will add a reference to the CrmDiscoveryService Web service and the CrmService Web service. You also have to add two references to .NET components.

To add the CrmService Web service reference

  1. In the Solution Explorer window, right-click your project name and select Add Service Reference.
  2. In the Add Service Reference dialog box, click Advanced.
  3. In the Service Reference Settings dialog box, click Add Web Reference.
  4. Type the URL for the CrmService WSDL XML file that you previously downloaded into the URL box, and then click Go. For example:
    file://C:\Documents and Settings\user\My Documents\CrmServiceWsdl.xml
    
  5. When the CrmService Web service is found, change the text in the Web reference name box to CrmSdk and then click Add Reference.

To add the CrmDiscoveryService Web service reference

  1. In the Solution Explorer window, right-click your project name and select Add Service Reference.
  2. In the Add Service Reference dialog box, click Advanced.
  3. In the Service Reference Settings dialog box, click Add Web Reference.
  4. Type the URL for the CrmDiscoveryService WSDL XML file that you previously downloaded into the URL box, and then click Go. For example:
    file://C:\Documents and Settings\user\My Documents\CrmDiscoveryServiceWsdl.xml
    
  5. When the CrmDiscoveryService Web service is found, change the text in the Web reference name box to CrmSdk.Discovery and then click Add Reference.

To add the required .NET references

  1. In the Solution Explorer window, right-click your project name and select Add Reference.
  2. In the Add Reference dialog multi-select the System.IdentityModel and System.ServiceModel components, and then click OK.

Adding a Windows Live Helper Class

You now have to add helper class code that simplifies Windows Live authentication to your project.

To add the helper code to your project

  1. Right-click the project name in Solution Explorer.
  2. Select Add then select Existing Item.
  3. In the file dialog box, browse to the folder SDK\server\helpers\cs\CrmOnlineAuth.
  4. Select the WLIDTicket.cs file and then click Add.

Accessing Microsoft Dynamics CRM Online Web Services

You will first add using statements to provide access to the required namespaces, and a class definition to your project.

To add the required using statements

In the default Program.cs file that Visual Studio provides, replace all code in that file with the following C# code:

[C#]
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Web.Services.Protocols;

namespace Microsoft.Crm.Sdk.Walkthrough.Authentication.PartnerAuthConsoleApp
{
    // Import the Microsoft Dynamics CRM namespaces.
    using CrmSdk;
    using CrmSdk.Discovery;

    class PartnerAuthentication
    {
 
    }

To add configuration information to your solution

Add the following code within the PartnerAuthentication class definition. Make sure that you fill in the correct configuration data values for your installation as indicated by the TODO comments.

[C#]
        #region Configuration data
        // TODO: Supply a device password.
        static private string _devicePassword = "user-supplied-device-pswd"; 

        // Set the name (and TCP port) of the server hosting Microsoft Dynamics CRM Online.
        static private string _hostname = "dev.crm.dynamics.com";

        // TODO: Specify the Windows Live ID account and password for the ISV's service.
        static private string _userName = "someuser@hotmail.com";
        static private string _password = "password";

        // This is the authentication policy.
        static private string _policy = "MBI_SSL";

        // This is open information about Microsoft Dynamics CRM Online.
        static private string _partner = "crm.dynamics.com";

        // TODO: Set the friendly name of the target organization.
        static private string _orgFriendlyName = "Adventure Works Cycle";

        // Set the type of Environment.
        static private LiveIdTicketManager.LiveIdEnvironment 
           _environment = LiveIdTicketManager.LiveIdEnvironment.PROD;

        #endregion Configuration data

        // Defines the expired authentication ticket error code.
        static private string EXPIRED_AUTH_TICKET = "8004A101";

        // Attempt a service call a maximum number of times before failing.
        static private int MAX_RETRIES = 5;

        public sealed class AuthenticationType
        {
            public const int AD = 0;
            public const int Passport = 1;
            public const int SPLA = 2;
        }

To add a Main method with error handling to your solution

Add the following code after the AuthenticationType class. This code will provide some exception handling and console output to verify that your program is working.

[C#]
        static void Main(string[] args)
        {
            try
            {
                Run();
                Console.WriteLine("Authentication was successfull.");
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("The application exited with an error.");
                Console.WriteLine(ex.Message);

                // Display the details of the inner exception.
                if (ex.InnerException != null)
                {
                    Console.WriteLine(ex.InnerException.Message);

                    SoapException se = ex.InnerException as SoapException;
                    if (se != null)
                        Console.WriteLine(se.Detail.InnerText);
                }
            }
            finally
            {
                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }
        }

Your program will not build because the Run method does not exist. You will create that method next.

To add the Run and InvokeServiceMethod methods

The InvokeServiceMethod contains all the code needed to use the discovery service to obtain the correct URL for the CrmService of your organization. A WhoAmI request is sent to the Web service to verify that the user has been authenticated successfully.

Add the following class methods after the Main method.

[C#]
       public static bool Run()
        {
            try
            {
                // Connect to Microsoft Dynamics CRM and call a Web service method.
                int firstAttempt = 1;
                InvokeServiceMethod(firstAttempt);
            }

            // Handle any Web service exceptions that might be thrown.
            catch (SoapException ex)
            {
                // Handle the SOAP exceptions here.
                throw ex;
                
            }
            catch (Exception ex)
            {
                // Handle general exceptions here.
                // This sample will just rethrow the exception.
                throw ex;
            }

            return true;
        }

        public static void InvokeServiceMethod(int retryCount)
        {
            try
            {
                if (retryCount == MAX_RETRIES)
                {
                    // Display an error when the maximum retry count has been reached.  
                    throw new Exception("An error occurred while attempting to authenticate.");
                }
                else
                {
                    // STEP 1,2: Retrieve a ticket from the Windows Live service.
                    string wlidTicket = null;
                    wlidTicket = LiveIdTicketManager.RetrieveTicket(_devicePassword, _partner, 
                        _userName, _password, _policy, _environment);

                    // STEP 3,4: Retrieve organization information and a (Crm) ticket from the Discovery Web service.
                    // Retrieve a list of organizations that the logged on user is a member of.
                    CrmDiscoveryService discoveryService = new CrmDiscoveryService();
                    discoveryService.Url = String.Format("https://{0}/MSCRMServices/2007/{1}/CrmDiscoveryService.asmx",
                        _hostname, "Passport");
                    RetrieveOrganizationsRequest orgRequest = new RetrieveOrganizationsRequest();
                    orgRequest.PassportTicket = wlidTicket;
                    RetrieveOrganizationsResponse orgResponse =
                        (RetrieveOrganizationsResponse)discoveryService.Execute(orgRequest);
                    // Locate the target organization name using the organization friendly name.
                    String orgUniqueName = String.Empty;
                    OrganizationDetail orgInfo = null;
                    foreach (OrganizationDetail orgDetail in orgResponse.OrganizationDetails)
                    {
                        if (orgDetail.FriendlyName.Equals(_orgFriendlyName))
                        {
                            orgInfo = orgDetail;
                            orgUniqueName = orgInfo.OrganizationName;
                            break;
                        }
                    }
                    // Retrieve the CrmTicket.
                    RetrieveCrmTicketRequest crmTicketRequest = new RetrieveCrmTicketRequest();
                    crmTicketRequest.OrganizationName = orgUniqueName;
                    crmTicketRequest.PassportTicket = wlidTicket; 
                    RetrieveCrmTicketResponse crmTicketResponse =
                       (RetrieveCrmTicketResponse)discoveryService.Execute(crmTicketRequest);

                    // STEP 5: Create and configure an instance of the CrmService Web service.
                    CrmAuthenticationToken token = new CrmAuthenticationToken();
                    token.AuthenticationType = AuthenticationType.Passport;
                    token.CrmTicket = crmTicketResponse.CrmTicket;
                    token.OrganizationName = crmTicketResponse.OrganizationDetail.OrganizationName;

                    CrmService crmService = new CrmService();
                    crmService.Url = crmTicketResponse.OrganizationDetail.CrmServiceUrl;
                    crmService.CrmAuthenticationTokenValue = token;

                    // Invoke the desired CrmService Web service methods.
                    WhoAmIRequest whoRequest = new WhoAmIRequest();
                    WhoAmIResponse whoResponse = (WhoAmIResponse)crmService.Execute(whoRequest);

                    systemuser user = (systemuser)crmService.Retrieve(EntityName.systemuser.ToString(),
                        whoResponse.UserId, new AllColumns());

                    Console.WriteLine("Login user's name is {0}", user.fullname);
                }
            }
            catch (SoapException ex)
            {
                // Handle the exception thrown from an expired ticket condition.
                if (GetErrorCode(ex.Detail) == EXPIRED_AUTH_TICKET)
                {
                    // This will retry the CrmService Web service call.
                    InvokeServiceMethod(retryCount++);
                }

                // If this was some other SOAP exception, rethrow this exception.
                throw ex;
            }
            catch (Exception ex)
            {
                // Handle the MAX_RETRY exception here.
                // This sample will rethrow the exception.
                throw ex;
            }
        }

To add the GetErrorCode method

Add the following class method. This method returns the error code from a SOAP exception stored in an XmlNode or returns an empty string if no error exists.

[C#]
        private static string GetErrorCode(XmlNode errorInfo)
        {
            XmlNode code = errorInfo.SelectSingleNode("//code");

            if (code != null)
                return code.InnerText;
            else
                return "";
        }

Setting Project Properties and Building

In the Project menu, select the Properties command. In the Application property tab enter the application namespace, Microsoft.Crm.Sdk.Walkthrough.Authentication.PartnerAuthConsoleApp, in the Default namespace text box. Now build and run your solution by pressing F5. When the program runs, it will print "Login user's name is …" to the console window.

If you have compile errors, you can find the complete code sample in the SDK\Walkthroughs\Authentication\CS\ServerToServerNoCerts folder.


© 2010 Microsoft Corporation. All rights reserved.


Show:
© 2014 Microsoft