2
votes

I am trying to access an Azure Function from Dynamics 365 Plugin via service to service call: https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service

This function is protected via App Service Authentication.

I created a Function App and enabled App Service Authentication under Platform Features -> Authentication/Authorisation. I enabled Azure Active Directory as the Auth Provider and set Management mode to Express

enter image description here

I then got the generated Client ID and Client Secret from the Advanced Mode:

enter image description here

Apparently this is all that is needed to make a token request for the Azure function based, based on article I need 4 required parameters:

Client ID

Client Secret

Grant Type

Resource

I make the following request to generate a token from a Dynamics 365 Plugin but get the following error:

Invalid Plugin Execution Exception: Microsoft.Xrm.Sdk.InvalidPluginExecutionException: {"error":"invalid_client","error_description":"AADSTS70002: Error validating credentials. AADSTS50012: Invalid client secret is provided.\r\nTrace ID: 06ddda7f-2996-4c9b-ab7e-b685ee933700\r\nCorrelation ID: d582e2f2-91eb-4595-b44b-e95f42f2f071\r\nTimestamp: 2018-05-23 06:30:58Z","error_codes":[70002,50012],"timestamp":"2018-05-23 06:30:58Z","trace_id":"06ddda7f-2996-4c9b-ab7e-b685ee933700","correlation_id":"d582e2f2-91eb-4595-b44b-e95f42f2f071"}-The remote server returned an error: (401) Unauthorized.

My code is :

         var tokenendpoint = "https://login.microsoftonline.com/de194c13-5ff7-4085-91c3-ac06fb869f28/oauth2/token";
         var reqstring = "client_id=" + Uri.EscapeDataString("5f315431-e4da-4f68-be77-4e257b1b9295");
         reqstring += "&client_secret=" + Uri.EscapeDataString("/oK7nh8pl+LImBxjm+L7WsQdyILErysOdjpzvA9g9JA=");
         reqstring += "&resource=" + Uri.EscapeUriString("https://keyvaultaccess.azurewebsites.net");
         reqstring += "&grant_type=client_credentials";

         //Token request
         WebRequest req = WebRequest.Create(tokenendpoint);
         req.ContentType = "application/x-www-form-urlencoded";
         req.Method = "POST";
         byte[] bytes = System.Text.Encoding.ASCII.GetBytes(reqstring);
         req.ContentLength = bytes.Length;
         System.IO.Stream os = req.GetRequestStream();
         os.Write(bytes, 0, bytes.Length);
         os.Close();

         //Token response
         HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
         StreamReader tokenreader = new StreamReader(resp.GetResponseStream());
         string responseBody = tokenreader.ReadToEnd();

I have made sure that I have the correct Client Secret and have also encoded it as I have read somewhere that '+' and '/' are no good.

I am getting the same error in Postman

Any ideas??

1
I have changed my secret to just "Hello" and still no joy - Stanza

1 Answers

1
votes

reqstring += "&resource=" + Uri.EscapeUriString("https://keyvaultaccess.azurewebsites.net");

Since you set resource parameter to https://keyvaultaccess.azurewebsites.net, I assumed that you have set the App ID URI of your AAD app (clientId equals 5f315431-xxxxxxx-4e257b1b9295) to https://keyvaultaccess.azurewebsites.net. I assume that you could retrieve the access_token, but when accessing your azure function endpoint with the access_token, you got the 401 status code.

You need to modify your advanced management mode for Active Directory Authentication, add https://keyvaultaccess.azurewebsites.net to ALLOWED TOKEN AUDIENCES or change the resource parameter to your AAD clientID when sending the token request for acquiring the access_token.

Active Directory Authentication configuration:

enter image description here

TEST:

enter image description here

Docode the JWT token to check the aud property:

enter image description here

Access my Azure Function endpoint:

enter image description here

Note: You need to take care of the Authorization level of your function as follows:

enter image description here

If you also enable function level authentication, your request sent to azure function needs to have the relevant code parameter in the querystring or set the header x-functions-key with the value of your function key, or you may just set the authorization level to Anonymous.