OAuth 2.0 authentication can transform into a very deep rabbit hole if you find yourself stumbling into it for the first time. Perhaps this is for a good reason. As the primary authentication mechanism for the vast majority of cloud services available today, there is an obvious expectation that the security aspects of this protocol remain top-notch at all times. Otherwise, all manner of insidious and treacherous individuals could end up poking around into systems that they have no right to be within. To ensure things remain as secure as possible, there is, therefore, a natural expectation that the setup aspects for legitimate access into systems leveraging OAuth2 be not necessarily a cakewalk.

Because OAuth2 is the backbone of Azure Active Directory, which is used to handle authentication into Dynamics 365 online / the Common Data Service, developers will have to cross the Rubicon with OAuth 2.0 at some stage. This action will become even more necessary if you are developing solutions that require a non-interactive login mechanism into the system. Traditionally, developers would have constructed a request similar to the below to generate an access token, which acts as the “key” into your particular service of choice; in this case, a Dynamics 365 online instance:

Request

POST https://login.microsoftonline.com/f38b4010-a9e0-40a8-af5e-626cfb3d85be/oauth2/token HTTP/1.1

--Headers removed for brevity

grant_type=client_credentials
&client_id=a05645a6-aa66-4441-b243-525563c1df2d
&client_secret=myclientsecret
&resource=https%3A%2F%2Fmycrminstance.crm11.dynamics.com%2F

Response

HTTP/1.1 200 OK

--Headers removed for brevity

{
   "token_type":"Bearer",
   "expires_in":"3599",
   "ext_expires_in":"3599",
   "expires_on":"1588493859",
   "not_before":"1588489959",
   "resource":"https://mycrminstance.crm11.dynamics.com/",
   "access_token":"myaccesstoken"
}

With our “key” in hand, we can then walk up and open the door into Dynamics 365 using a request similar to the below, to return details of the user making the request. The key portion here is the Authorization header value, which must contain the access_token generated in the previous step and be in the format Bearer <Access Token>:

Request

GET https://mycrminstance.crm11.dynamics.com/api/data/v9.1/WhoAmI HTTP/1.1
Authorization: Bearer myaccesstoken
--Other headers removed for brevity

Response

HTTP/1.1 200 OK

--Headers removed for brevity

{
   "@odata.context":"https://mycrminstance.crm11.dynamics.com/api/data/v9.1/$metadata#Microsoft.Dynamics.CRM.WhoAmIResponse",
   "BusinessUnitId":"9941c9c6-f71e-ea11-a812-00224801bc51",
   "UserId":"395439d2-d98a-ea11-a811-000d3a7fedbe",
   "OrganizationId":"4827d81f-172e-4d9d-b9b2-6db4e7c12490"
}

This request all works fine and dandy, as you can see. The main issue with it though is that, currently, it is utilising version 1 of the OData v2.0 token endpoint that Microsoft expose out to developers for use. This issue is not so much of a problem as things stand today and as noted by this convenient comparison post on the subject – indeed, depending on your scenario, it may be impossible for you to migrate currently, as the version 2 endpoints are missing some features. However, I would argue that the writing is on the wall and that the eventual deprecation of this endpoint is more than likely. For new projects, if you can get away with using V2 of the new endpoint to meet your requirements, you should use this wherever possible.

With all this laid out, we now get to the crux of the matter, which relates to a recent challenge I had – how to get web requests targeting Dynamics 365 moved across to start using the new v2 endpoints? Unfortunately, simply changing the URL to https://login.microsoftonline.com/f38b4010-a9e0-40a8-af5e-626cfb3d85be/oauth2/v2.0/token comes back with the following error:

{
   "error":"invalid_request",
   "error_description":"AADSTS901002: The 'resource' request parameter is not supported.\r\nTrace ID: 506b590a-7c90-4638-8a39-ff35cd9d1800\r\nCorrelation ID: 1eb1b320-7802-4983-a46d-e6d20c6ede5e\r\nTimestamp: 2020-05-03 07:38:44Z",
   "error_codes":[
      901002
   ],
   "timestamp":"2020-05-03 07:38:44Z",
   "trace_id":"506b590a-7c90-4638-8a39-ff35cd9d1800",
   "correlation_id":"1eb1b320-7802-4983-a46d-e6d20c6ede5e"
}

Obliging the error message, by removing the resource key/value pair from our body request, doesn’t give us much joy as well, as we get a new error instead:

“error_description”: “AADSTS90014: The required field ‘scope’ is missing from the credential. Ensure that you have all the necessary parameters for the login request.\r\nTrace ID: afeacc53-92b2-430b-a8a3-bf69af5b1800\r\nCorrelation ID: a6b2a96d-d7d6-4929-8402-5a9da9a27335\r\nTimestamp: 2020-05-03 07:42:54Z”
A quick read of the documentation tells us that we must supply a scope value that contains the URL of the resource we are trying to access, appended by .default. So our working request must resemble the below:
POST https://login.microsoftonline.com/f38b4010-a9e0-40a8-af5e-626cfb3d85be/oauth2/v2.0/token HTTP/1.1

--Headers removed for brevity

grant_type=client_credentials
&client_id=a05645a6-aa66-4441-b243-525563c1df2d
&client_secret=myclientsecret
&scope=https%3A%2F%2Fmycrminstance.crm11.dynamics.com%2F.default
With this, you will get a token back successfully, and we can now proceed to use this to authenticate into Dynamics 365 / the Common Data Service 🙂
Getting your head around the OAuth 2.0 “flow” for Azure Active Directory can be a challenge, at the best of times. Even if you find yourself equipped with advanced knowledge on the subject, you can expect to spend some time banging your head against the wall, as you attempt to get your access tokens generated for the first time. And, I can also anticipate there will be future issues arising as people look to migrate their applications to use the new V2 endpoints. As this article has hopefully demonstrated, moving across your Dynamics 365 / Common Data Service applications is pretty easy and possible to do today. So what are you waiting for? 😉🤣
Share This