Tip #767: Server-to-server authentication is here

HeadlessWoot, woot! At long last we can create passive clients – the ones that do not have someone sitting in front of them. Clients like web sites or services – and authenticate them without using username and password AND get the magic bearer token that is good to use in Web API.

The detailed walkthrough is available, describing in glorious details the process of creating a web site (MVC applicaton) that can talk to Dynamics CRM. Don’t be put off by references to the web sites – you don’t have to be building one to take advantage of the feature. In fact, substantially lesser efforts required to create an equivalent console application that can be deployed as a Web Job and run unattended as a service.

  1. Register your application on Azure AD. No need for multi-tenant, single-tenant will do. What I found is that if you are using https://portal.azure.com, it does not create the application instance locally requiring the logon and consent. Easy to say with the web site, not so much with a console application. If instance is not created you will not be able to create an application user (see below). There is probably another way to do it but using old portal does immediately create an instance.
    Local Azure app
  2. Add permissions to access CRM and generate your key (same instructions)
  3. Create an application user. This is where the good stuff happens, we’re allowing a specific application to access CRM without a consent from a user.
  4. Create console application in Visual Studio and add nuget packages
  5. You are good to go!
  6. The code looks like this:
static void Main(string[] args)
{
    string organizationUrl = "https://notarealone.crm.dynamics.com";
    string clientId = "6db9cae3-dead-beef-dead-7179d4958975";
    string appKey = "get you own";
    string aadInstance = "https://login.microsoftonline.com/";
    string tenantID = "your tenant id";

    ClientCredential clientcred = new ClientCredential(clientId, appKey);
    AuthenticationContext authenticationContext = new AuthenticationContext(aadInstance + tenantID);
    AuthenticationResult authenticationResult = authenticationContext.AcquireToken(organizationUrl, clientcred);
    var requestedToken = authenticationResult.AccessToken;
            
    using (var sdkService = new OrganizationWebProxyClient(GetServiceUrl(organizationUrl), false))
    {
        sdkService.HeaderToken = requestedToken;

        OrganizationRequest request = new OrganizationRequest()
        {
            RequestName = "WhoAmI"
        };

        WhoAmIResponse response = sdkService.Execute(new WhoAmIRequest()) as WhoAmIResponse;
        Console.WriteLine(response.UserId);
    }
}
static private Uri GetServiceUrl(string organizationUrl)
{
    return new Uri(organizationUrl + @"/xrmservices/2011/organization.svc/web?SdkClientVersion=8.2");
}

Last but not least, to quickly find your tenant id, select application in either Azure portal and ask for Endpoints, your tenant id will be splattered all over endpoint urls as a guid that follows the domain.

Tweet about this on TwitterShare on Facebook3Share on Google+0

4 thoughts on “Tip #767: Server-to-server authentication is here

  1. Dibutil says:

    What about licensing of such a client?

    • Tracy,

      most of the posts you mention are quite old (by internet standards). S2S authentication has become available for Dynamics 365 not so long ago (one of the stackoverflow posts does mention that) and you’d need an updated ADAL library to get it all going. What I posted has been tried and tested; but, of course, your mileage may vary.

      Also worth noting that some of the posts refer to username/password authentication while the code I’m referring to uses clientid/secret credentials. Could be the source of misbehaviour as well.

      HTH
      George

Leave a Reply

Your email address will not be published. Required fields are marked *