Lars Fosdal 1792 Posted January 12, 2023 I am stumped. I can't convince the Delphi TRESTClient to connect to a system using OAuth2 authentication. Either it is a about a parameterization mistake, or it is a functional failure. I can't get it to work with the REST debugger either. Any examples (Other than the RESTdemo) would be appreciated! I have C# code that uses the same creds, and it has no issues. I get access to the system using the Authentication URL with the clientid + clientsecret I request a token through a different URL I call the API URL, using the token Share this post Link to post
Attila Kovacs 629 Posted January 12, 2023 (edited) The authentication can be implemented in severeal ways. I would sniff the traffic and see the difference oooooor read the manual. Usually there are some "postman" (Application) examples. Edited January 12, 2023 by Attila Kovacs Share this post Link to post
Lars Fosdal 1792 Posted January 12, 2023 I have instrumented the C# app with logging, so I see exactly what happens. The challenge is convincing the Delphi REST components to do the same thing. Share this post Link to post
Uwe Raabe 2057 Posted January 12, 2023 It is possible that you have to implement it yourself in the way it is needed as it is noted in the docs: Quote TOAuth2Authenticator implements a basic OAuth2 authentication. TOAuth2Authenticator offers minimal support and provides the infrastructure to follow the workflow of the service provider. Inherit from this class to create an authenticator class specific to a service provider. That said, giving a concrete example is difficult without knowing more details. 1 Share this post Link to post
Attila Kovacs 629 Posted January 12, 2023 OAuth2 is the authentication protocol. How the credentials are exchanged is up to the service provider. There are some common ways like pass it in the URL (RESTDebugger) or pass it in the headers, pass it in a JSON Object etc... The service provider will give you the documentation and examples. Share this post Link to post
Lars Fosdal 1792 Posted January 12, 2023 I think I was fooled by my own expectations with regards to the simplicity of OAuth2 and functional level of the TOAuth2Authenticator. The C# code example can be found here, but it uses another assembly from Thinktecture to do the http parts. https://github.com/LarsFosdal/csharp-ion-api-sdk/blob/master/DotNetBackendOAuth2/Program.cs I'll ponder a little, google some more, and see if I can't crack this nut. Share this post Link to post
Attila Kovacs 629 Posted January 12, 2023 did you ask chatGPT for an example? Share this post Link to post
Lars Fosdal 1792 Posted January 20, 2023 I ended up writing a small class around THTTPClient from System.Net.HttpClient. No need for the humongous REST.* classes. 1 Share this post Link to post
Darian Miller 361 Posted February 18, 2023 On 1/12/2023 at 9:07 AM, Attila Kovacs said: did you ask chatGPT for an example? I just did for fun. Here's the result: Can you create an example OAuth2 bearer token example in Delphi using the THTTPClient ? Sure, here is an example of how to use the THTTPClient component in Delphi to authenticate with an OAuth2 bearer token: uses System.Net.HttpClient, System.Net.URLClient, System.NetConsts; function SendRequestWithBearerToken(const AURL: string; const AToken: string): string; var Client: THTTPClient; Request: THTTPRequest; Response: IHTTPResponse; begin Client := THTTPClient.Create; Request := THTTPRequest.Create(TNetEncoding.Base64); try Request.Method := TRESTRequestMethod.rmGET; Request.URL := AURL; Request.Headers.AddValue('Authorization', 'Bearer ' + AToken); Response := Client.Execute(Request); if Response.StatusCode = 200 then Result := Response.ContentAsString else raise Exception.CreateFmt('Request failed with HTTP error %d: %s', [Response.StatusCode, Response.StatusText]); finally Request.Free; Client.Free; end; end; In this example, the SendRequestWithBearerToken function takes two parameters: AURL: The URL of the API endpoint that you want to call. AToken: The OAuth2 bearer token that you want to use for authentication. The function creates a THTTPClient object to send the HTTP request, and a THTTPRequest object to set up the request headers. It sets the HTTP method to GET and sets the URL and Authorization header with the bearer token. Finally, it sends the request using the Execute method of the THTTPClient object and returns the response as a string. You can call this function like this: var ResponseContent: string; begin try ResponseContent := SendRequestWithBearerToken('https://api.example.com/items', 'my_bearer_token'); // Process the response content here except on E: Exception do ShowMessage('Error: ' + E.Message); end; end; Note that in this example, you would need to replace the https://api.example.com/items with the actual API endpoint you want to call, and my_bearer_token with the actual OAuth2 bearer token that you want to use for authentication. 1 Share this post Link to post
Dmitry Arefiev 101 Posted February 18, 2023 A lot depends on a resource, which you are trying to authenticate. What is it (hopefully some publicly available) ? Share this post Link to post
David Schwartz 426 Posted February 19, 2023 This might help. It took me a while to track down. Using the REST Debugger, just put "Bearer " in front of the token and select OAuth2. When you get it working, click the option to copy the components and paste the result onto your form. One of the components it creates is this component, which is in the REST.Authenticator.OAuth unit: You set the TokenType to ttBEARER, set the Access Token, and tell it the name of the parameter, and I think that's it. Share this post Link to post
Lars Fosdal 1792 Posted February 20, 2023 What lacks in this example is that the bearer token can be a temporary token, and you first have to authenticate to retrieve the bearer token and the renewal token, and use the renewal token periodically to update your tokens. Share this post Link to post
David Schwartz 426 Posted February 20, 2023 (edited) 15 hours ago, Lars Fosdal said: What lacks in this example is that the bearer token can be a temporary token, and you first have to authenticate to retrieve the bearer token and the renewal token, and use the renewal token periodically to update your tokens. Maybe you need to find less paranoid services to work with. 🙂 🙂 🙂 Edited February 20, 2023 by David Schwartz Share this post Link to post
Lars Fosdal 1792 Posted February 20, 2023 That is more or less the industry standard of how to authenticate. Share this post Link to post
Uwe Raabe 2057 Posted February 20, 2023 Have you tried the TOAuth2Authenticator component linked to a TRESTClient? It has a context menu that lets you specify play with some parameters. Share this post Link to post
KMarb 5 Posted February 22, 2023 Jumping in here... I am new to much of this. I have a client certificate and key file (.pem and .key). I have successfully used Postman (new to that too) to send an HTTP Post request to get a bearer token. To do this I added my client cert in Postman settings: And the HTTP request has several parameters in the body and header, which I added on the Postman request pages. It works! The response looks like this: { "access_token": "20c686eb-1313-4e53-9d73-df1626dd3996", "token_type": "Bearer", "expires_in": 3600, "scope": "api" } Using the bearer token I'm then able to make api calls for 60 minutes. My question is, can someone tell me how to add the client certificate to the Delphi RestClient or RestRequest? I'm looking at the OAuth2Authenticator component but it's not obvious to me what I need to do. I think I have all the parameters set up in the RestRequest successfully, but without the client cert I'm getting an error, "unspecified certificate from client" Share this post Link to post
Angus Robertson 574 Posted February 22, 2023 Quote how to add the client certificate to the Delphi RestClient or RestRequest? Client certificates are unrelated to REST, OAuth2 or tokens. They are an alternate means of server authentication by HTTPS clients to HTTPS servers, not that common except for corporate VPNs and high security financial applications. It is quite hard to buy a commercial client certificate, for email for instance, they are usually issued by corporates for employees and customers. I don't use the TRestClient component, but I'm not aware it supports client certificates. You need a proper component library like ICS that has full support for REST, Auth2, tokens and client certificates. Angus Share this post Link to post
KMarb 5 Posted February 22, 2023 Many thanks - For ICS is this the right site?: http://www.overbyte.eu/frame_index.html?redirTo=/products/ics.html Share this post Link to post
Angus Robertson 574 Posted February 22, 2023 Yes, but the ICS download page is http://wiki.overbyte.eu/wiki/index.php/ICS Once you have it installed run the SSLDemos OverbyteIcsHttpRestTst sample, it does everything you need. However that sample expects your client certificate to be provided as a bundle file for ease of configuration, ie the certificate, key and intermediate in a single PEM or PFX file. The PemTool sample does all that, although a text editor also works for PEM. There is an ICS support topic here. Angus Share this post Link to post
KMarb 5 Posted February 22, 2023 Thanks again. Rookie question - my URL starts https://, not http://. Is that enough to require OpenSSL, or how do I determine if I need to use OpenSSL? From the wiki - "You will also need OpenSSL libraries if using SSL-enabled components" I am reading the notes and if I answer my own question I will post again. Share this post Link to post
KMarb 5 Posted February 22, 2023 Options to ICS? It's free which is great but appears development has stopped? The app I'm creating might be needed for several years. Is there an option that is well regarded and actively updated? Share this post Link to post
Angus Robertson 574 Posted February 23, 2023 Quote Options to ICS? It's free which is great but appears development has stopped? Why would you think that? The last release was in November 2022 which you can install from GetIt, and the latest SVN update was last week. The latest OpenSSL DLLs are installed with the samples, updated this month. Angus Share this post Link to post
KMarb 5 Posted February 23, 2023 The first page I found stated the last supported version was D10.3, screen capture below. Thanks for correcting me. I have an issue with install on Berlin. I load project D101InstallVclFmx and all projects compile, but when I try to install the design packages I get this error: One note - I'm using Berlin - Please ignore the folder name "Delphi Tokyo"... it is misnamed. The file is in that folder, so I'm stumped: What should I look at to correct that? This is why I thought development had stopped: Share this post Link to post
Uwe Raabe 2057 Posted February 23, 2023 It is probably another module (BPL or DLL) that is internally used by the mentioned package, but is either missing or fails to load. Share this post Link to post