How to connect a Delphi desktop app to a third-par

2019-08-22 19:13发布

问题:

All the information I have found so far is that the desktop app needs to be registered with Microsoft Azure Active Directory, and that there is a library called ADAL that has all that is needed.

https://msdn.microsoft.com/en-nz/library/gg327838.aspx

https://docs.microsoft.com/en-nz/azure/active-directory/develop/active-directory-authentication-libraries

But what I want to do is just log into a third-party app that is already running on top of Dynamics, and then use a REST method to read custom data that this third-party app provides.

Is this at all possible?

If push comes to shove, I could write a C#.NET DCOM wrapper class that I then import into Delphi to gain access to the ADAL functionality, but the developers of the third-party Dynamics 365 app want to control access themselves.

I've looked at the RESTDemos project example supplied with Delphi Studio 10.2 Tokyo, and while it has a number of OAuth 2.0 examples (which is what Dynamics 365 needs), they don't include Dynamics 365 itself.

But to see what might be needed, I have created a test Google app, gone through the sign-in process for Google Tasks, was able to fetch the auth-code and access-token, and then fetch a list of tasks, so at least I know that the OAuth 2.0 mechanism I am supposed to use is working.

I have been given the CRM root service address, which I can log into using the credentials they provided, but that is just for the Dynamics 365 web application. I want to be able to use the same credentials to access the API of their app.

Edit:

If I append api/data/v8.0/ to the root URL they gave me, I can see a list of all the supported REST methods. Trying to use one, like api/data/v8.0/accounts/ gives me an "Access is denied" message unless I have actually logged into the CRM system via the Microsoft login page, at which point the REST method returns every account in the system.

Edit2:

From further investigations I have found that the method I am looking for is the one suggested for daemon/server applications.

https://docs.microsoft.com/en-nz/azure/active-directory/develop/active-directory-authentication-scenarios#daemon-or-server-application-to-web-api

For this to work, I do have to register the application but into the AD domain of the third-party Dynamics 365 app. Once this is done, I can create a Public Key that will allow me to get the Azure Token without needing to login as a particular Dynamics 365 User.

The code to use is similar to below:

  RESTClient.BaseURL := 'https://login.microsoftonline.com/';

  RESTRequest.Method := TRESTRequestMethod.rmPOST;
  RESTRequest.Resource := '/' + ATenantID + '/oauth2/token';

  RESTRequest.Params.AddItem('grant_type', 'client_credentials', TRESTRequestParameterKind.pkGETorPOST);
  RESTRequest.Params.AddItem('client_id', AClientID, TRESTRequestParameterKind.pkGETorPOST);
  RESTRequest.Params.AddItem('client_secret', AClientSecret, TRESTRequestParameterKind.pkGETorPOST);
  RESTRequest.Params.AddItem('resource', AResourceURI, TRESTRequestParameterKind.pkGETorPOST);

  RESTRequest.Execute;

The ATentantID, AClientID, AClientSecret, and AResourceURI values can all be obtained from Azure Active Directory; either from its properties, or the properties of the Registered app.

You then pull the Token from the RESTRequest.Response object.

回答1:

The following code using the Delphi REST Client Library will authenticate to Dynamics 365 when your application has been registered and configured correctly:

  RESTClient.BaseURL := 'https://login.microsoftonline.com/';
  RESTClient.Authenticator := OAuth2_Dynamics365;

  RESTRequest.Method := TRESTRequestMethod.rmPOST;
  RESTRequest.Resource := '/' + ATenantID + '/oauth2/token';

  RESTRequest.Params.AddItem('grant_type', 'client_credentials', TRESTRequestParameterKind.pkGETorPOST);
  RESTRequest.Params.AddItem('client_id', AClientID, TRESTRequestParameterKind.pkGETorPOST);
  RESTRequest.Params.AddItem('client_secret', AClientSecret, TRESTRequestParameterKind.pkGETorPOST);
  RESTRequest.Params.AddItem('resource', AResourceURI, TRESTRequestParameterKind.pkGETorPOST);

  RESTRequest.Execute;

  if RESTRequest.Response.GetSimpleValue('access_token', AToken) then
    OAuth2_Dynamics365.AccessToken := AToken;

As noted above, the ATentantID, AClientID, AClientSecret, and AResourceURI values can all be obtained from Azure Active Directory; either from its properties, or the properties of the Registered app.