Blog


Most Recent Post  |  Next Post  |  Previous Post  |  Index List

TMS FNC Cloud Pack is here!

Bookmarks: 

Tuesday, April 30, 2019

First release!

We are excited to announce the first release of the TMS FNC Cloud Pack!

What's included

Included in the TMS FNC Cloud Pack is the ability to create/implement your own REST service client(s). There is a small accompanying guide available after installation, that explains a few of the basics to get started. Additionally, below is a list of some of the many features that are supported in the TMS FNC Cloud Pack.

  • Create your own REST service client(s) built on top of the TMS FNC Cloud Pack core
  • One source code base to use on multiple frameworks (FMX, VCL, WEB and LCL)
  • Make GET, POST, PUT, UPDATE, DELETE and PATCH requests
  • Support for multi-part form data via a separate form data builder class
  • Built-in OAuth 2.0 authentication flow
  • Built-in URL encoding, JSON parsing, file to Base64 encoding and many more

Included in the TMS FNC Cloud Pack is a set of ready-to-use REST service client implementations that are listed below.

  • Google Tasks
  • Google Calendar
  • Google Contacts
  • Google Firebase Database
  • Google Drive
  • Google GMail
  • Google Search terms
  • Google Maps address data
  • Google Photos
  • Microsoft Onedrive
  • Outlook Calendar
  • Outlook Contacts
  • Outlook Mail
  • Apple CloudKit
  • DropBox Cloud storage
  • PayPal
  • YouTube
  • Hubic
  • myCloudData.net

How to create your own REST service client?

To illustrate how to create your own REST service client, we take the source code from accessing a Google service, such as Google Drive. Google Drive has a common layer in where the authentication flow and access token generation are handled to allow other services from Google implement the API’s on top of this layer. The first step is to generate the authentication URL.
function TTMSFNCCustomCloudGoogle.GetAuthenticationURL: string;
begin
  Result := InitializeAuthenticationURL(Self);
end;

function InitializeAuthenticationURL(const ACloudBase: TTMSFNCCloudBase): string;
var
  url, sc: string;
begin
  sc := TTMSFNCCloudBaseOpen(ACloudBase).GetScopes('+', True);
  url :=
      '?scope=' + sc
    + '&state=profile'
    + '&redirect_uri='+ TTMSFNCUtils.URLEncode(ACloudBase.Authentication.CallBackURL)
    + '&response_type=code'
    + '&client_id=' + ACloudBase.Authentication.ClientID
    + '&approval_prompt=force'
    + '&access_type=offline'
    + '&hl=en';

  url := 'https://accounts.google.com/o/oauth2/auth' + url;

  Result := url;
end;
The URL is a concatenation of The ClientID, CallBackURL, some default parameters and a set of scopes, which is crucial to allow the user to identify which services is accessing which information. For Google Drive, the scopes are added in the constructor:
  Scopes.Clear;
  Scopes.Add('https://www.googleapis.com/auth/drive');
  Scopes.Add('https://www.googleapis.com/auth/drive.file');
  Scopes.Add('https://www.googleapis.com/auth/userinfo.profile');
When calling the Connect method, and the Access Token is not yet retrieved, or no longer valid, a browser is shown which allows identifying and authorizing the application which is requesting access to your files/folders and account information. Below is a screenshot of the browser and the scopes that are requested via the authorization URL.



After Clicking on the “Allow” button, the Application is redirected back to your application which runs an HTTP Server listening to the Callback URL & Port set via Authentication.CallBackURL. As soon as the HTTP Server catches the OAuth 2.0 redirect callback URL, it parses the URL and generates an authentication token. The next step is to take the authentication token and convert it to an access token:
procedure TTMSFNCCustomCloudGoogle.RetrieveAccessToken;
begin
  InitializeRetrieveAccessTokenRequest(Self);
  ExecuteRequest({$IFDEF LCLWEBLIB}@{$ENDIF}DoRetrieveAccessToken);
end;

procedure InitializeRetrieveAccessTokenRequest(const ACloudBase: TTMSFNCCloudBase);
begin
  ACloudBase.Request.Clear;
  ACloudBase.Request.Name := 'RETRIEVE ACCESS TOKEN';
  ACloudBase.Request.Host := 'https://accounts.google.com';
  ACloudBase.Request.Path := '/o/oauth2/token';
  ACloudBase.Request.Query :=  'client_id=' + ACloudBase.Authentication.ClientID
  + '&client_secret=' + ACloudBase.Authentication.Secret
  + '&redirect_uri=' + ACloudBase.Authentication.CallBackURL
  + '&code=' + ACloudBase.Authentication.AuthenticationToken
  + '&grant_type=authorization_code';
  ACloudBase.Request.Method := rmPOST;
end;
In the access token request, you’ll notice that the secret, authentication token, and callback URL are required to identify your application request and make sure the service returns the correct access token. The request is executed and automatically handled by the core layer in TMS FNC Cloud Pack. There is no need to manually parse the access token, unless the service deviates from the default OAuth 2.0 authentication flow. After retrieving the access token, the service core layer is automatically performing a test to validate the access token and grant access to service API’s. The test needs to be handled by your service implementation. For Google Drive, the test involves calling a simple tokeninfo API endpoint to validate the tokens, but for other services, it could be retrieving the account information, or testing a retrieval of files/folders.
procedure TTMSFNCCustomCloudGoogle.TestTokens(const ATestTokensRequestResultEvent: TTMSFNCCloudBaseRequestResultEvent = nil);
begin
  InitializeTestTokensRequest(Self);
  ExecuteRequest(ATestTokensRequestResultEvent);
end;

procedure InitializeTestTokensRequest(const ACloudBase: TTMSFNCCloudBase);
begin
  ACloudBase.Request.Clear;
  ACloudBase.Request.Name := 'TEST TOKENS';
  ACloudBase.Request.Host := 'https://www.googleapis.com';
  ACloudBase.Request.Path := '/oauth2/v1/tokeninfo';
  ACloudBase.Request.Query := 'access_token=' + ACloudBase.Authentication.AccessToken;
  ACloudBase.Request.Method := rmGET;
end;
After executing the test tokens request, the service returns a JSON response which is unique for each service. For Google Drive, this is checking if the returned JSON does not have an error tag.
function TTMSFNCCustomCloudGoogle.GetTestTokensResult(
  const ARequestResult: TTMSFNCCloudBaseRequestResult): Boolean;
begin
  Result := InitializeTestTokensResult(Self, ARequestResult)
end;

function InitializeTestTokensResult(const ACloudBase: TTMSFNCCloudBase; const ARequestResult: TTMSFNCCloudBaseRequestResult): Boolean;
var
  o: TJSONValue;
  s: string;
begin
  Result := False;
  s := ARequestResult.ResultString;
  if s <> '' then
  begin
    o := TTMSFNCUtils.ParseJSON(s);
    if Assigned(o) then
    begin
      Result := not Assigned(TTMSFNCUtils.GetJSONValue(o, 'error'));
      o.Free;
    end;
  end;
end;
The result is a Boolean (true/false). When the result is a true, the service is successfully authenticated, and the application can start accessing various API’s. Below is a sample that shows how to use the access token to retrieve the account drive space info.
procedure TTMSFNCCustomCloudGoogleDrive.GetAccountInfo;
begin
  Request.Clear;
  Request.Host := Service.BaseURL;
  Request.Path := FBasePath + '/about';
  Request.Query := 'access_token=' + Authentication.AccessToken;
  Request.Method := rmGET;
  Request.Name := 'GET SPACE USAGE';
  ExecuteRequest({$IFDEF LCLWEBLIB}@{$ENDIF}DoRequestGetSpaceUsage);
end;

procedure TTMSFNCCustomCloudGoogleDrive.DoRequestGetSpaceUsage(const ARequestResult: TTMSFNCCloudBaseRequestResult);
var
  o: TJSONValue;
begin
  if ARequestResult.ResultString <> '' then
  begin
    o := TTMSFNCUtils.ParseJSON(ARequestResult.ResultString);

    if Assigned(o) then
    begin
      try
        FInfo.UserName := TTMSFNCUtils.GetJSONProp(o, 'displayName');
        FInfo.Quota := TTMSFNCUtils.GetJSONDoubleValue(o, 'quotaBytesTotal');
        FInfo.QuotaUsed := TTMSFNCUtils.GetJSONDoubleValue(o, 'quotaBytesUsed');

      finally
        o.Free;
      end;
    end;
  end;

  DoGetSpaceUsage(FInfo, ARequestResult);
  DoGetCurrentAccount(FInfo, ARequestResult);
end;

Demo

Included in the release is a demo that allows you to test out each service individually in one easy and intuïtive overview. Click on the service of your choice and fill in your Application Client-ID, Secret and the appropriate Callback URL registered to your application. click on Authenticate and start exploring. The demo is available for FMX, VCL, WEB and LCL.

We want your feedback!

In this blog post, we already asked you for which service(s) you wish to see an implementation. We already received a lot of feedback, and want to thank you for this. This allows us to continue development in future updates of TMS FNC Cloud Pack. For those that didn't yet fill in the survey, please go to https://www.survio.com/survey/d/N4J9X1C8L4V7K1U7V

We want your feedback, so we can improve the TMS FNC Cloud Pack even more, so we want to ask you for a thorough testing on TMS FNC Cloud Pack and provide us with any feedback, comments, suggestions and issues you experience. This can be done via comments on this blog, or an email to support@tmssoftware.com

Pieter Scheldeman


Bookmarks: 

This blog post has not received any comments yet. Add a comment.




Most Recent Post  |  Next Post  |  Previous Post  |  Index List