Recent

Author Topic: OAUTH2 authorization port to Lazarus  (Read 388 times)

ksabolc

  • Newbie
  • Posts: 2
OAUTH2 authorization port to Lazarus
« on: December 06, 2022, 09:07:38 pm »
Hello !

I'm struggling with OAUTH2 authorization. I can't port it from PHP to Lazarus.
In PHP it works fine, i am getting the authorization token fine, but I can't achive it from Lazarus. Tried with fphttpclient but without succes, always getting a '{"error":"invalid_request"}' error. Probably missing some header or not formed well the request body ???
Any suggestions ?

The working PHP code is:

Code: PHP  [Select][+][-]
  1. <?php
  2. $params = array(
  3.     'client_id'=> '****',
  4.     'client_secret'=> '****',
  5.     'grant_type'=> 'password',
  6.     'username'=> '****',
  7.     'password'=> '****',
  8.     'scope' => 'minimax.rs');
  9.  
  10. $request = array(
  11.     'http' => array(
  12.         'method'=> 'POST',
  13.         'header'=> array(
  14.             'Content-type: application/x-www-form-urlencoded',
  15.             ),
  16.         'content'=> http_build_query($params),
  17.         'timeout'=> 10
  18.         )
  19.     );
  20.  
  21. print_r($params);
  22. echo "<br>";
  23. echo "<br>";
  24. print_r($request);
  25. echo "<br>";
  26. echo "<br>";
  27. echo "<br>";
  28. echo "<br>";
  29.  
  30. if (!$response = file_get_contents('https://moj.minimax.rs/RS/aut/oauth20/token', false, stream_context_create($request))) {        
  31.     die('auth error');
  32. }
  33.  
  34. $token = json_decode($response);
  35.  
  36. print_r($response);
  37. echo "<br>";
  38. echo "<br>";
  39.  
  40. $request = array(
  41.     'http' => array(
  42.         'method'=> 'GET',
  43.         'header'=> 'Authorization: Bearer ' . $token->access_token,
  44.         'timeout'=> 10
  45.         )
  46.     );
  47. if (!$response = file_get_contents('https://moj.minimax.rs/RS/api/api/currentuser/orgs', false, stream_context_create($request))) {
  48.     die('orgs error');
  49. }
  50.  $orgs = json_decode($response, true); print_r($orgs);
  51. ?>
« Last Edit: December 06, 2022, 09:49:15 pm by ksabolc »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 10498
  • FPC developer.
Re: OAUTH2 authorization port to Lazarus
« Reply #1 on: December 06, 2022, 09:10:47 pm »
So where is your lazarus code?

Thaddy

  • Hero Member
  • *****
  • Posts: 12642
Re: OAUTH2 authorization port to Lazarus
« Reply #2 on: December 06, 2022, 09:17:44 pm »
OAUTH2 is already supported through the Google API bindings in the standard distribution of FreePascal and also through some MS bindings.
"Looks" OK, doesn't mean it is IS OK.

ksabolc

  • Newbie
  • Posts: 2
Re: OAUTH2 authorization port to Lazarus
« Reply #3 on: December 06, 2022, 09:33:03 pm »
So where is your lazarus code?

Code: Pascal  [Select][+][-]
  1. procedure TMiniMaxAPI.Button2Click(Sender: TObject);
  2.  
  3. var
  4.   HTTPClient: TFPHTTPClient;
  5.   Params: string = '{"client_id": "****", "client_secret": "****", "grant_type": "password", "username": "*****", "password": "*****", "scope": "minimax.rs"}';
  6.   MiniMaxResponse: TStringStream;
  7.   PostURL: string;
  8.   nParamsLength: integer;
  9.   sParamsLength: string;
  10.  
  11. begin
  12.   PostURL := '';
  13.   PostURL := PostURL + 'https://moj.minimax.rs/RS/AUT/OAuth20/Token';
  14.   nParamsLength:= length(PostURL);
  15.   Str(nParamsLength, sParamsLength);
  16.   MiniMaxResponse := TStringStream.Create;
  17.   if Length(EditCode.Text) > 0 then
  18.   begin
  19.     //ParamList.Create;
  20.     HTTPClient := TFPHTTPClient.Create(nil);
  21.     HTTPClient.AllowRedirect := True;
  22.     HTTPClient.AddHeader('Content-type','application/x-www-form-urlencoded');
  23.     HTTPClient.AddHeader('Accept', 'application/json');
  24.     HTTPClient.RequestBody := TRawByteStringStream.Create(Params);
  25.     HTTPClient.AddHeader('Content-Length','0');
  26.     try
  27.       HTTPClient.Post(PostURL, MiniMaxResponse);
  28.       MemoLogin.Text:=MiniMaxResponse.DataString;
  29.     finally
  30.       HTTPClient.RequestBody.Free;
  31.       HTTPClient.Free;
  32.       MiniMaxResponse.Free;
  33.     end;
  34.   end
  35. end;
« Last Edit: December 06, 2022, 09:35:48 pm by ksabolc »

PierceNg

  • Sr. Member
  • ****
  • Posts: 293
    • SamadhiWeb
Re: OAUTH2 authorization port to Lazarus
« Reply #4 on: December 07, 2022, 01:34:57 am »
Code: Pascal  [Select][+][-]
  1. procedure TMiniMaxAPI.Button2Click(Sender: TObject);
  2.  
  3. var
  4.   Params: string = '{"client_id": "****", "client_secret": "****", "grant_type": "password", "username": "*****", "password": "*****", "scope": "minimax.rs"}';
  5.  
  6. begin
  7.     HTTPClient.AddHeader('Content-type','application/x-www-form-urlencoded');
  8.     HTTPClient.RequestBody := TRawByteStringStream.Create(Params);
  9.     HTTPClient.Post(PostURL, MiniMaxResponse);
  10. end;

Based on the snippet, you want to send content type 'application/x-www-form-urlencoded', 'params' is a JSON-looking string, and I don't think 'TRawByteStringStream.Create('json-ish string')' gives you the correct encoding.

If you know the server accepts JSON, simplest thing to try is to set content type to 'application/json', otherwise look at the method FormPost.

Also, OAuth2 best current practice recommends against using the password grant type because it is weak security.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8530
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: OAUTH2 authorization port to Lazarus
« Reply #5 on: December 07, 2022, 03:43:40 am »
Short answer: your Pascal code isn't doing the same thing as the PHP version.
Code: PHP  [Select][+][-]
  1. <?php
  2. $params = array(
  3.     'client_id'=> '****',
  4.     'client_secret'=> '****',
  5.     'grant_type'=> 'password',
  6.     'username'=> '****',
  7.     'password'=> '****',
  8.     'scope' => 'minimax.rs');
  9.  
  10. $request = array(
  11. ...
  12.         'content'=> http_build_query($params),
  13.  
http_build_query builds a url encoded string of the $params array, which will be:
Code: [Select]
client_id=%2A%2A%2A%2A%2A&client_secret=%2A%2A%2A%2A%2A&grant_type=password&username=%2A%2A%2A%2A%2A&password=%2A%2A%2A%2A%2A&scope=minimax.rs
and not:
Code: Javascript  [Select][+][-]
  1. {"client_id": "****", "client_secret": "****", "grant_type": "password", "username": "*****", "password": "*****", "scope": "minimax.rs"}
  2.  
as in your Pascal code. One of the FormPost variant accepts TStrings, you can assign the params there and it will be encoded properly like this:
Code: Pascal  [Select][+][-]
  1. var
  2.   LParams: TStrings;
  3.   LResponse: String;
  4. ...
  5. LParams := TStringList.Create;
  6. LResponse := TStringList.Create;
  7. with LParams do
  8.   try
  9.     Values['client_id'] := '****';
  10.     Values['client_secret'] := '*****';
  11.     ... // and so on
  12.     LResponse := HTTPClient.FormPost(PostURL, LParams);
  13.     ... // do something with LResponse
  14.   finally
  15.     LParams.Free;
  16.   end;
  17.  
alternatively you can build the url encoded strings manually, but you have to EncodeURLElement() both the keys and values by hand.

 

TinyPortal © 2005-2018