Why am I getting 401 Unauthorized with my Access Token?
When dealing with D365FO integrations, OData 4.0 is the protocol introduced into D365FO to replace AIF (Application Integration Framework – integration architecture of previous AX versions.) With D365FO inherently living in Azure and requiring Azure Active Directory (Azure AD) – the Microsoft chosen authentication mechanism is OAuth 2.0. There is a good article on the Microsoft site which outlines how to get the OAuth2.0 authentication working here.
When working with D365FO OData calls, a valid bearer token must be part of the call. Where things get interesting is when you receive a token that doesn’t work. Specifically, you make the call for a token, receive the bearer token back – then when you go to use your token to retrieve Data from D365FO the system politely responds with “401 Unauthorized”
Postman (which is invaluable when testing integrations in D365FO), shows us a “401 Unauthorized”, even though we just got a new token and pasted it into the BearerToken parameter.
Hmmm…isn’t that the point of a token, to provide access? How are we getting a token that is not giving us access?
In our case, we found that the answer lies in URLEncoding the values of the parameters in the call to get the token. The call to get a token requires at minimum the following Key-Value pairs in the Post body of getting a token. See below:
|client_Id||The Application ID assigned to your app when you registered it with Azure AD. You can find this in the Azure Portal. Click Azure Active Directory in the services|
|client_secret||The application secret that you created in the Azure Portal for your app under Keys|
should be set to “client_credentials” when using client_secret and client_id
|resource||The App URI of the target web API (i.e. the D365FO environment you are trying to send or get data from).|
A typical URL Post string to get a token would look like so:
https://login.microsoftonline.com/<your tenant id>/oauth2/token?&client_id=<yourclientid>&client_secret=<yourclientsecret>&grant_type=client_credentials&resource=<yourresource>
While you may be able to use the existing strings you have, if there are any special characters (which is highly likely) you will need to URL encode the values to get a “working” token back. Postman does this automatically if you use variables, however does not when you embed the actual values into the parameters directly. So, in short, be sure to always URLEncode all your values specified in the post request. There is a fee Online URLEncode utility which is great for encoding static strings.
So, your string should look like so in the future:
https://login.microsoftonline.com/<your tenant id>/oauth2/token?&client_id=<your_urlencoded_clientid>&client_secret=<your_urlencoded_clientsecret>&grant_type=client_credentials&resource=<your_urlencoded_resource>
That’s it for today, short and sweet. We hope this saves you a bit of headache (and time) in the future!