3

I need to implement a REST API in FireMonkey to get some information, but I'm not sure how I can do it.

The REST API uses OAuth2, I have access to two codes: Consumer Key and Consumer Secret. After this, I need to get a temporary Bearer token.

To request the temporary token, it is necessary to perform an HTTP POST request to the Token endpoint https://apigateway.serpro.gov.br/token, informing the access credentials (consumerKey: consumerSecret) in the HTTP Authorization Header, in base64 format, as shown below.

[POST] grant_type = client_credentials 
[HEAD] Authorization: Basic Base64 (Consumer key: ConsumerSecret)

How can I get the access token with Delphi?

2

2 Answers 2

5

The OAuth2 component coming with the Delphi REST Framework do sadly not work when the authentication method is client_credentials, so you have to do it the manual way. I've included the test code I used for finding out how it worked. Even tested it again today just to make sure that it works :)

Drop a Memo and a button on the form and set the Button1 OnClick event, change the <your_xxxx> to what suits you and you should be good to go (just check that it is named Memo1, Button1 and Form1)

You will have access to the REST components with Firemonkey too, so this is just to show of the REST framework.

unit Unit1;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    GaToken: string;
    GaTokenType: string;
    GaTokenExpire: integer;
  end;

var
  Form1: TForm1;

implementation

uses
  REST.Types,
  REST.Client,
  REST.Utils,
  System.NetEncoding,
  System.Net.HttpClient;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  vClientId,
    vClientSecret,
    vScope,
    aExpire: string;
  LClient: TRESTClient;
  LRequest: TRESTRequest;
  LResponse: TRESTResponse;
begin
  // Scope is not mandatory and can be skiped
  vClientId := '<your_clientID>';
  vClientSecret := '<your_seecret>';
  // vScope := '<Your_scope>;

  LClient := TRESTClient.Create('<YOUR_TOKEN_URL>');
  try
    LRequest := TRESTRequest.Create(LClient);
    try
      LResponse := TRESTResponse.Create(LClient);
      try
        LRequest.Client := LClient;  // This line is not really needed but it is good for code readability, see TRESTRequest.Create(LClient);
        LRequest.Response := LResponse;

        LRequest.Method := rmPOST;
        LRequest.AddAuthParameter('grant_type', 'client_credentials', pkGETorPOST);
        LRequest.AddAuthParameter('client_id', vClientId, pkGETorPOST);
        LRequest.AddAuthParameter('client_secret', vClientSecret, pkGETorPOST);
        // LRequest.AddAuthParameter('scope', vScope, pkGETorPOST);

        LRequest.Execute;

        LResponse.GetSimpleValue('access_token', GaToken);
        LResponse.GetSimpleValue('token_type', GaTokenType);
        LResponse.GetSimpleValue('expires_in', aExpire);
        GaTokenExpire := aExpire.ToInteger;

        Memo1.Clear;
        Memo1.Lines.Add(IntToStr(LResponse.StatusCode) + ' / ' + LResponse.StatusText);
        Memo1.Lines.Add('------------   R A W   R E S P O N S E   ---------------------');
        Memo1.Lines.Add(LResponse.Headers.Text);
        Memo1.Lines.Add('--------------------------------------------------------------');
        Memo1.Lines.Add(LResponse.Content);
        Memo1.Lines.Add('--------------------  T O K E N  -----------------------------');
        Memo1.Lines.Add(GAToken);
      finally
        LResponse.Free;
      end;
    finally
      LRequest.Free;
    end;
  finally
    LClient.Free;
  end;
end;

end.
Sign up to request clarification or add additional context in comments.

3 Comments

Eirik, I hope my edit is not offending. I changed the code style and removed the use of inline vars, the feature is fairly new and it is not mainstream yet, your code now works on 10.2 tokyo as well which is still used by a lot of people.
The code works good for me, now I need to call other request: LClient := TRESTClient.Create('apigateway.serpro.gov.br/consulta-cnpj-df/v1/cnpj/…); LRequest.Accept:='application/json'; LRequest.Params.AddHeader('Authorization', 'Bearer fb841ac7c00b41ca8747acc1985defea'); LRequest.Method := rmGET; LRequest.Execute; But I received an error: Required OAuth credentials not provided. Make sure your API invocation call has a header: "Authorization: Bearer ACCESS_TOKEN, can you help me?
If it helped you, please accept the answer. When it comes to further questions you have to make a new post, as only one question pr. topic is answered.
1

take a look at RESTRequest4Delphi. Might help you

https://github.com/viniciussanchez/RESTRequest4Delphi

Request.Token('bearer token');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.