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.