Recent

Author Topic: OAUTH2 authorization port to Lazarus  (Read 378 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: 10479
  • 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: 12566
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.
Writing code in an overly complex way is usually merely a complete misunderstanding of the goal you are trying to achieve.

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: 287
    • 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: 8523
  • 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