Authenticate Office 365 users with Customer Engagement web services

This topic applies to customers who access Dynamics 365 Customer Engagement (on-premises) through the Microsoft Online Services environment. There are multiple Dynamics 365 Customer Engagement (on-premises) identity providers that must be accounted for when you develop an application that connects to the Organization or Discovery web services. These providers can be identified as managed domain, federated, and Microsoft account. This topic focuses on Dynamics 365 Customer Engagement (on-premises) web service authentication with managed domain and federated identity providers, although the same classes and code shown here also work with all supported identity providers and Dynamics 365 Customer Engagement (on-premises) deployment types.

Use the simplified authentication classes

You can use the OrganizationServiceProxy and DiscoveryServiceProxy classes when authenticating with the web services.
For more information about using these proxy classes see Authentication by using the client proxy classes.

Note

The sample helper code containing the ServerConnection class is no longer maintained and will be removed some time in the future. Instead, use one of the supported authentication APIs in the SDK assemblies such as CrmServiceClient.

Another authentication approach is to use the helper source code provided in the SDK. The ServerConnection helper class, shown in Helper Code: ServerConnection Class, provides GetOrganizationProxy and GetProxy methods for authentication. If you look at the source code for ServerConnection, you will see that GetOrganizationProxy actually calls GetProxy.

using ( OrganizationServiceProxy orgServiceProxy = ServerConnection.GetOrganizationProxy(serverConfig) ) { }  

You must create these organization or discovery service proxy objects in a using statement to correctly dispose of the service proxy, or call Dispose directly. For sample code that uses the GetOrganizationProxy helper code method, see Sample: Quick Start.

The complete list of authentication classes available in the SDK assemblies are shown in the Authentication Classes section.

Authenticate Microsoft account users with Office 365

Your application needs to support those Dynamics 365 Customer Engagement (on-premises) users whose organization is transitioned from the Microsoft account identity provider to the Microsoft Online Services identity provider. In this scenario, users may provide their Microsoft account sign-in credentials when they authenticate with the Microsoft Online Services identity provider of Dynamics 365 Customer Engagement (on-premises).

To do this, pass the populated credentials in the OrganizationServiceProxy constructor or the AuthenticationCredentials method of the IServiceManagement class. The credential values are populated as follows:

AuthenticationCredentials.ClientCredentials = <Microsoft account sign-in credentials>  
AuthenticationCredentials.SupportingCredentials.ClientCredentials = <device credentials>  

If your code checks the identity provider type to determine how to authenticate, then additional code is required. See the GetCredentials method in the next section for sample code that supports transitioned Microsoft account users.

For more information about this transition, see Dynamics 365 Customer Engagement (on-premises) Integration with Office 365.

Authentication deep dive

The previous discussion introduced two simple approaches that can be used to authenticate a user with the Dynamics 365 Customer Engagement (on-premises) web services. The following information shows how to authenticate a user by using the IServiceManagement<TService> class and includes the source code to the GetProxy method. To see the complete sample that contains the following examples, see Sample: Authenticate Office 365 Users. You will notice that authentication at this level takes a lot more code.

The following sample code demonstrates the classes and methods that you can use in your application to authenticate an Office 365/MOS user using the Dynamics 365 Customer Engagement (on-premises) web services.



IServiceManagement<IOrganizationService> orgServiceManagement =
    ServiceConfigurationFactory.CreateManagement<IOrganizationService>(
    new Uri(organizationUri));

// Set the credentials.
AuthenticationCredentials credentials = GetCredentials(orgServiceManagement, endpointType);

// Get the organization service proxy.
using (OrganizationServiceProxy organizationProxy =
    GetProxy<IOrganizationService, OrganizationServiceProxy>(orgServiceManagement, credentials))
{
    // This statement is required to enable early-bound type support.
    organizationProxy.EnableProxyTypes();

    // Now make an SDK call with the organization service proxy.
    // Display information about the logged on user.
    Guid userid = ((WhoAmIResponse)organizationProxy.Execute(
        new WhoAmIRequest())).UserId;
    SystemUser systemUser = organizationProxy.Retrieve("systemuser", userid,
        new ColumnSet(new string[] { "firstname", "lastname" })).ToEntity<SystemUser>();
    Console.WriteLine("Logged on user is {0} {1}.",
        systemUser.FirstName, systemUser.LastName);
}

The code creates an IServiceManagement<TService> object for the Organization service. An object of type AuthenticationCredentials is used to contain the user’s sign-in credentials. The IServiceManagement object and user credentials are then passed to GetProxy to obtain the web service proxy reference.



/// <summary>
/// Obtain the AuthenticationCredentials based on AuthenticationProviderType.
/// </summary>
/// <param name="service">A service management object.</param>
/// <param name="endpointType">An AuthenticationProviderType of the CRM environment.</param>
/// <returns>Get filled credentials.</returns>
private AuthenticationCredentials GetCredentials<TService>(IServiceManagement<TService> service, AuthenticationProviderType endpointType)
{
    AuthenticationCredentials authCredentials = new AuthenticationCredentials();

    switch (endpointType)
    {
        case AuthenticationProviderType.ActiveDirectory:
            authCredentials.ClientCredentials.Windows.ClientCredential =
                new System.Net.NetworkCredential(_userName,
                    _password,
                    _domain);
            break;
        case AuthenticationProviderType.LiveId:
            authCredentials.ClientCredentials.UserName.UserName = _userName;
            authCredentials.ClientCredentials.UserName.Password = _password;
            authCredentials.SupportingCredentials = new AuthenticationCredentials();
            authCredentials.SupportingCredentials.ClientCredentials =
                Microsoft.Crm.Services.Utility.DeviceIdManager.LoadOrRegisterDevice();
            break;
        default: // For Federated and OnlineFederated environments.                    
            authCredentials.ClientCredentials.UserName.UserName = _userName;
            authCredentials.ClientCredentials.UserName.Password = _password;
            // For OnlineFederated single-sign on, you could just use current UserPrincipalName instead of passing user name and password.
            // authCredentials.UserPrincipalName = UserPrincipal.Current.UserPrincipalName;  // Windows Kerberos

            // The service is configured for User Id authentication, but the user might provide Microsoft
            // account credentials. If so, the supporting credentials must contain the device credentials.
            if (endpointType == AuthenticationProviderType.OnlineFederation)
            {
                IdentityProvider provider = service.GetIdentityProvider(authCredentials.ClientCredentials.UserName.UserName);
                if (provider != null && provider.IdentityProviderType == IdentityProviderType.LiveId)
                {
                    authCredentials.SupportingCredentials = new AuthenticationCredentials();
                    authCredentials.SupportingCredentials.ClientCredentials =
                        Microsoft.Crm.Services.Utility.DeviceIdManager.LoadOrRegisterDevice();
                }
            }

            break;
    }

    return authCredentials;
}

The AuthenticationCredentials object is configured according to the subscribed identity for the signed-in user. Notice that user credentials for all types of identity providers are shown. The default case handles Office 365/MOS managed domain, online users whose identities are federated in the cloud, and transitioned Microsoft account users. Now let’s take a look at what GetProxy actually does.



private TProxy GetProxy<TService, TProxy>(
    IServiceManagement<TService> serviceManagement,
    AuthenticationCredentials authCredentials)
    where TService : class
    where TProxy : ServiceProxy<TService>
{
    Type classType = typeof(TProxy);

    if (serviceManagement.AuthenticationType !=
        AuthenticationProviderType.ActiveDirectory)
    {
        AuthenticationCredentials tokenCredentials =
            serviceManagement.Authenticate(authCredentials);
        // Obtain discovery/organization service proxy for Federated, LiveId and OnlineFederated environments. 
        // Instantiate a new class of type using the 2 parameter constructor of type IServiceManagement and SecurityTokenResponse.
        return (TProxy)classType
            .GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(SecurityTokenResponse) })
            .Invoke(new object[] { serviceManagement, tokenCredentials.SecurityTokenResponse });
    }

    // Obtain discovery/organization service proxy for ActiveDirectory environment.
    // Instantiate a new class of type using the 2 parameter constructor of type IServiceManagement and ClientCredentials.
    return (TProxy)classType
        .GetConstructor(new Type[] { typeof(IServiceManagement<TService>), typeof(ClientCredentials) })
        .Invoke(new object[] { serviceManagement, authCredentials.ClientCredentials });
}

 

For all deployments other than on-premises (Active Directory, without claims), the Authenticate(AuthenticationCredentials) method is invoked and then the service proxy is instantiated. Notice that the authentication credentials returned from Authenticate contain the security token response that is used in the service proxy constructor. The generic GetProxy method shown previously can be used to obtain an object reference to either OrganizationServiceProxy or DiscoveryServiceProxy.

See also

Connect with Microsoft Office 365 and Dynamics 365 Customer Engagement (on-premises) Sample: Authenticate Office 365 Users
Helper Code: ServerConnection Class
Active Directory and Claims-Based Authentication
Use connection strings in XRM tooling to connect to Dynamics 365 Customer Engagement (on-premises)