I am trying to get my RESTClient’s CRUD Requests to work after retrieving the access-token from Azure but I don’t know what parameters need to be added and I cannot find examples of the syntax that work, or maybe my app’s registration info isn’t correct for a REST API. Both apps are written Delphi 10.4.2 (Sydney).
I have a RESTServer/RESTClient pair of apps (originated using the IDE’s DataSnap wizards). I added a RESTful WebAction to the RESTServer and a corresponding GET Request to the RESTClient, and they perform perfectly if both apps reside on my network or both are on a drive in my Azure Windows Server VM. I wish to have only the RESTServer app on Azure so I am trying to get my RESTClient app to connect to the RESTServer app on Azure Windows Server VM.
I put a TOAuth2Authenticator component on a form in my Delphi 10.4.2 app and was able to confirm that I can retrieve the Access-Token using the identity values from Azure app registration info. The registration specifies that this is a "Public" API and I created a Scope for it but I’m not sure a Scope is needed for a Public REST API.
If I ping the Public IP of the VM I get "Request timed out." but I’m assuming that is normal and retrieval of the token works anyway, which is confirmed in the following code from this test app:
procedure TMainForm.RESTTokenRequestAfterExecute(Sender: TCustomRESTRequest);
begin
if RESTTokenResponse.StatusCode = 200 then
begin
MyAuthToken := RESTTokenResponse.JSONValue.GetValue<String>('access_token');
OAuth2Authenticator5.AccessToken := FConnection.MyAuthToken; // store it here in case I decide to use this component.
That code and the RESTClient code to retrieve the token are based on this demo app:
https://github.com/jfbilodeau/AzureRESTExample
But the following code (and dozens of variations) in my app always times out with
ENetHTTPClientException with message ‘Error sending data: (12002) The operation timed out’.
ERESTException with message ‘REST request failed: Error sending data: (12002) The operation timed out’.
I’ve read messages that suggest that the Resource parameter is not used now, at least not for Public APIs, and I don’t see any examples about how to specify the Scope in Delphi components.
Intuitively, it would make sense to apply a "REST Endpoint" URL to these Requests that use the Token for subsequent contact.
Is all of that handled by the contents of the Token? I have parsed the Token at jwt.io and cannot tell if it contains all that is needed for the connection. I could redact some of that and include it if that would be helpful.
procedure MyForm.Button1Click(Sender: TObject);
var
RESTClient1: TRESTClient;
RESTRequest1: TRESTRequest;
strImageJSON : string;
begin
RESTClient1 := TRESTClient.Create('http://<Azure Public IP>:8080/'); // tried https also
try
RESTRequest1 := TRESTRequest.Create(nil);
try
RESTRequest1.Method := TRESTRequestMethod.rmGET; // or rmPOST?
// MyAzureResource from Delphi RESTServer app's WebModule.WebActionItem's Pathinfo
RESTRequest1.Resource := 'api/<AzureClientID>/<MyAzureResource>';
RESTRequest1.Params.AddItem('MyKey1', 'MyValue1', TRESTRequestParameterKind.pkREQUESTBODY);
RESTRequest1.Params.AddItem('MyKey2', 'MyValue2', TRESTRequestParameterKind.pkREQUESTBODY);
RESTRequest1.Params.AddItem('Authorization','Bearer ' + FConnection.AuthToken);
RESTRequest1.Client := RESTClient1;
RESTRequest1.Execute;
strImageJSON := RESTRequest1.Response.Content;
finally
RESTRequest1.Free;
end;
finally
RESTClient1.Free;
end;
end;
When not connecting to Azure, the basic Request with only these 2 parameters works fine:
RESTRequest1.Params.AddItem(‘MyKey1’, ‘MyValue1’);
RESTRequest1.Params.AddItem(‘MyKey2’, ‘MyValue2’);
Can you tell me what is wrong with this Request under Azure?
2
Answers
The problem is that you’re passing the authorization bearer token as parameter and not as an header try this code
in your code you where sending the authorization as a request parameter
btw if i can give you a suggestion try to use indy to make rest call is pretty easy and you can handle everything IMO
This is an example of your call made with indy10 on delphi 11
it should work fine on Sydney version