OAUTH2 authorization port to Lazarus lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- ksabolc · 2022-12-06 20:07 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i '****',    'client_secret'=> '****',    'grant_type'=> 'password',    'username'=> '****',    'password'=> '****',    'scope' => 'minimax.rs'); $request = array(  'http' => array(        'method'=> 'POST',        'header'=> array(          'Content-type: application/x-www-form-urlencoded',            ),        'content'=> http_build_query($params),        'timeout'=> 10        )    ); print_r($params);echo "
";echo "
";print_r($request);echo "
";echo "
";print_r(stream_context_create($request));echo "
";echo "
"; if (!$response = file_get_contents('https://moj.minimax.rs/RS/aut/oauth20/token', false, stream_context_create($request))) {            die('auth error');} $token = json_decode($response); print_r($response);echo "
";echo "
"; $request = array(    'http' => array(        'method'=> 'GET',        'header'=> 'Authorization: Bearer ' . $token->access_token,        'timeout'=> 10        )    );if (!$response = file_get_contents('https://moj.minimax.rs/RS/api/api/cur rentuser/orgs', false, stream_context_create($request))) {    die('orgs error');} $orgs = json_decode($response, true); print_r($orgs);?> ---------------------------------------------------------------------- marcov · 2022-12-06 20:10 So where is your lazarus code? ---------------------------------------------------------------------- Thaddy · 2022-12-06 20:17 OAUTH2 is already supported through the Google API bindings in the standard distribution of FreePascal and also through some MS bindings. ---------------------------------------------------------------------- ksabolc · 2022-12-06 20:33 Quote from: marcov on December 06, 2022, 09:10:47 pmSo where is your lazarus code? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMiniMaxAPI.Button2Click(Sender: TObject); var  HTTPClient: TFPHTTPClient;  Params: string = '{"client_id": "****", "client_secret": "****", "grant_type": "password", "username": "*****", "password": "*****", "scope": "minimax.rs"}';  MiniMaxResponse: TStringStream;  PostURL: string;  nParamsLength: integer;  sParamsLength: string; begin  PostURL := '';  PostURL := PostURL + 'https://moj.minimax.rs/RS/AUT/OAuth20/Token';  nParamsLength:= length(PostURL);  Str(nParamsLength, sParamsLength);  MiniMaxResponse := TStringStream.Create;  if Length(EditCode.Text) > 0 then  begin    //ParamList.Create;    HTTPClient := TFPHTTPClient.Create(nil);    HTTPClient.AllowRedirect := True;    HTTPClient.AddHeader('Content-type','application/x-www-form- urlencoded');    HTTPClient.AddHeader('Accept', 'application/json');  HTTPClient.RequestBody := TRawByteStringStream.Create(Params);    HTTPClient.AddHeader('Content-Length','0');    try      HTTPClient.Post(PostURL, MiniMaxResponse);      MemoLogin.Text:=MiniMaxResponse.DataString;    finally      HTTPClient.RequestBody.Free;      HTTPClient.Free;      MiniMaxResponse.Free;    end;  endend; ---------------------------------------------------------------------- PierceNg · 2022-12-07 00:34 Quote from: ksabolc on December 06, 2022, 09:33:03 pmCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TMiniMaxAPI.Button2Click(Sender: TObject); var  Params: string = '{"client_id": "****", "client_secret": "****", "grant_type": "password", "username": "*****", "password": "*****", "scope": "minimax.rs"}'; begin    HTTPClient.AddHeader('Content- type','application/x-www-form-urlencoded');    HTTPClient.RequestBody := TRawByteStringStream.Create(Params);    HTTPClient.Post(PostURL, MiniMaxResponse);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 · 2022-12-07 02:43 Short answer: your Pascal code isn't doing the same thing as the PHP version. Quote from: ksabolc on December 06, 2022, 09:07:38 pmCode: PHP  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i '****',    'client_secret'=> '****',    'grant_type'=> 'password',    'username'=> '****',    'password'=> '****',    'scope' => 'minimax.rs'); $request = array(...        'content'=> http_build_query($params), 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: Quote from: ksabolc on December 06, 2022, 09:33:03 pmCode: Javascript  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {"client_id": "****", "client_secret": "****", "grant_type": "password", "username": "*****", "password": "*****", "scope": "minimax.rs"} 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][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  LParams: TStrings;  LResponse: String;...LParams := TStringList.Create;LResponse := TStringList.Create;with LParams do  try    Values['client_id'] := '****';    Values['client_secret'] := '*****';    ... // and so on    LResponse := HTTPClient.FormPost(PostURL, LParams);    ... // do something with LResponse  finally    LParams.Free;  end; alternatively you can build the url encoded strings manually, but you have to EncodeURLElement() both the keys and values by hand.