Export (0) Print
Expand All

Server-to-Server Authentication

banner art

[Applies to: Microsoft Dynamics CRM 4.0]

The Server-to-Server authentication process is used when a non-Microsoft Dynamics CRM Web service, Windows service, or ASPX page needs to authenticate with Microsoft Dynamics CRM Online and access the Web services. This process uses a lightweight authentication method where user name, password, and device ID information can be used to authenticate the user instead of certificates. This is the preferred method to authenticate a user for Microsoft Dynamics CRM Online.

The Server-to-Server authentication process with Microsoft Dynamics CRM Online is shown in the following figure.

Windows Live authentication

The Microsoft Dynamics CRM Online authentication process involves the following steps:

  • (1,2) Retrieve a policy from the CrmDiscoveryService Web service. For this SDK release, the policy is "MBI_SSL".
  • (3,4) Retrieve a Windows Live ID (WLID) ticket from the Windows Live ID service.
  • (5,6) Retrieve detailed information about the specified organization and a (Crm) ticket from the CrmDiscoveryService Web service. The ticket applies to a single organization. The ticket contains an organization specific CrmService URL. Refer to the Active Directory authentication sample for additional sample code showing how to obtain organization information by using RetrieveOrganizationsRequest.
  • (7) Create an instance of the CrmAuthenticationToken class that has the CrmTicket and OrganizationName properties set to the correct values.
  • (7) Create an instance of the CrmService class that has the Url property value and the CrmAuthenticationTokenValue property value set.
  • (7) Invoke CrmService Web service methods.

In order to accomplish steps 3 and 4 shown previously, you need to set up a service account in Microsoft Dynamics CRM Online. The service account represents a virtual Microsoft Dynamics CRM Online user that is the owner of any data changes made to the Microsoft Dynamics CRM Online database through Microsoft Dynamics CRM SDK Web service calls. As with any other Microsoft Dynamics CRM user account, the service account must be added to each desired organization where business data is to be modified.

Example

The following code sample shows you how to authenticate with Microsoft Dynamics CRM Online and call a CrmService method.

[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 Microsoft.Crm.Sdk;
    using Microsoft.Crm.Sdk.Query;
    using Microsoft.Crm.SdkTypeProxy;
    using CrmSdk.Discovery;

    class PartnerAuthentication
    {
        #region Configuration data
        // The following configuration data is site specific. You will need to
        // change these data values to those that are appropriate for your
        // Microsoft Dynamics CRM Online installation and Windows Live ID Service.
        // Note: The following example code contains sample data for a user logon 
        // name and password. This is for illustration purposes only. User credentials
        // should never be hard coded. For more information, see Building Secure ASP.NET
        // Applications at msdn.microsoft.com/library/en-us/dnnetsec/html/SecNetch12.asp.

        // TODO: Define a password for the device you are accessing CRM Online from.
        static private string _devicePassword = "user-supplied-device-pswd"; 

        // Set the name, and if necessary the 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";

        // STEP 1,2: 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;

        /// <summary>
        /// The type of authentication supported in Microsoft Dynamics CRM. You could also
        /// add SDK\Server\Helpers\CS\CrmHelpers\Enums.cs to the project and remove this inner class.
        /// </summary>
        public sealed class AuthenticationType
        {
            public const int AD = 0;
            public const int Passport = 1;
            public const int SPLA = 2;
        }

        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();
            }
        }

        /// <summary>
        /// Authenticates a user with Microsoft Dynamics CRM Online. Afterwards,
        /// a call to a CrmService Web method is attempted to verify that the
        /// authentication was valid.
        /// </summary>
        /// <returns>True, if successful, otherwise, false.</returns>
        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;
        }

        /// <summary>
        /// Returns the error code that is contained in SoapException.Detail.
        /// </summary>
        /// <param name="errorInfo">An XmlNode that contains application specific error information.</param>
        /// <returns>Error code text or empty string.</returns>
        private static string GetErrorCode(XmlNode errorInfo)
        {
            XmlNode code = errorInfo.SelectSingleNode("//code");

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

        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 3,4: Retrieve a ticket from the Windows Live service.
                    string wlidTicket = null;
                    wlidTicket = LiveIdTicketManager.RetrieveTicket(_devicePassword, _partner, 
                        _userName, _password, _policy, _environment);

                    // STEP 5,6: 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 7: 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 ISV 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;
            }
        }        
    }
}

The CrmDiscoveryService Web service is accessed through the global URL of the Microsoft Dynamics CRM Online server:

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

If the (Crm) ticket expires during application execution, a new ticket must be obtained and assigned to the CrmTicket property of the CrmAuthenticationToken instance. If you try to access the CrmService Web methods with an expired ticket, a SOAP exception is thrown. The SoapException.Detail.Innertext property contains the error code value of "8004A101".

Note that, in real-world scenarios, you would never authenticate and then immediately check for an expired ticket as this sample shows. Instead, you would authenticate and make additional Web service method calls. Part of your software design would be to catch Soap exceptions from Microsoft Dynamics CRM Web service calls and check for an expired authentication ticket.

To access the Windows Live authentication service over the Internet and obtain a Windows Live ID ticket, the code sample uses the LiveIdTicketManager class that is provided as source code in Server\Helpers\CS\CrmOnlineAuth\WLIDTicket.cs file of the SDK download.

The complete code sample can be found in the SDK\Walkthroughs\Authentication\CS\ServerToServerNoCerts folder of the SDK download.

See Also

Concepts

Reference

Tasks

Other Resources


© 2010 Microsoft Corporation. All rights reserved.


Show:
© 2014 Microsoft