Authentication Routine Using JSON
Authentication Routine Using JSON
New poster, long time RPG developer but somewhat new to interfacing with web servers. HTTPAPI_VERSION 1.48
I have a simple application that needs to POST a couple static JSON fields (or one JSON field with JSON formatting) to an authentication server which should retrieve a token if authenticated, POST the token with a request to a web service and store the retrieved file in the IFS. We've used HTTPAPI for other applications and I have been able to post to a web service and retrieve a file to the IFS. The issue is the authentication. I'm attempting to use the http_mfd_encoder routines to create a .JSON tempfile but I can't even get this program to compile. I started with code from example7 and I've attempted to modify it for encoding JSON.
(variable definitions same as EXAMPLE7)
tempFile = http_tempfile();
enc = http_mfd_encoder_open( tempFile // line 66
: 'application/json' // line 67
: ContentType
: '<root§httpapi.org>'
: 'application/json' );
if (enc = *NULL);
msg = http_error();
dsply msg;
msg = http_error();
dsply msg;
return;
endif;
http_mfd_encoder_addvar_s(enc:'clientId':'#####')
http_mfd_encoder_addvar_s(enc:'clientSecret':'xxxxxxx');
http_mfd_encoder_close( enc );
rc = http_url_post_stmf('https://xxxx/authenicate'
: tempFile
: '/tmp/http_result.txt'
: HTTP_TIMEOUT
: HTTP_USERAGENT
: ContentType );
if (rc <> 1);
msg = http_error();
dsply msg;
return;
endif;
QCMDEXC('DSPF ''/tmp/http_result.txt''': 200);
unlink('/tmp/http_result.txt');
unlink(tempFile);
The compile lists 3 errors:
*RNF7542 30 3782 006700 Parameter 2 is not valid as a parameter passed by reference.
*RNF5407 20 3781 006600 More parameters were passed in the prototyped call than are allowed.
*RNF5407 20 3781 006600 More parameters were passed in the prototyped call than are allowed.
Is the content type application/json not allowed or are there other errors?
Can the static json code be imbedded in variables as I've done or would it be better to have them stored in a .json file in the IFS?
Any help would be appreciated. If there are examples somewhere that I missed, please point me to them.
Thanks,
Mark
I have a simple application that needs to POST a couple static JSON fields (or one JSON field with JSON formatting) to an authentication server which should retrieve a token if authenticated, POST the token with a request to a web service and store the retrieved file in the IFS. We've used HTTPAPI for other applications and I have been able to post to a web service and retrieve a file to the IFS. The issue is the authentication. I'm attempting to use the http_mfd_encoder routines to create a .JSON tempfile but I can't even get this program to compile. I started with code from example7 and I've attempted to modify it for encoding JSON.
(variable definitions same as EXAMPLE7)
tempFile = http_tempfile();
enc = http_mfd_encoder_open( tempFile // line 66
: 'application/json' // line 67
: ContentType
: '<root§httpapi.org>'
: 'application/json' );
if (enc = *NULL);
msg = http_error();
dsply msg;
msg = http_error();
dsply msg;
return;
endif;
http_mfd_encoder_addvar_s(enc:'clientId':'#####')
http_mfd_encoder_addvar_s(enc:'clientSecret':'xxxxxxx');
http_mfd_encoder_close( enc );
rc = http_url_post_stmf('https://xxxx/authenicate'
: tempFile
: '/tmp/http_result.txt'
: HTTP_TIMEOUT
: HTTP_USERAGENT
: ContentType );
if (rc <> 1);
msg = http_error();
dsply msg;
return;
endif;
QCMDEXC('DSPF ''/tmp/http_result.txt''': 200);
unlink('/tmp/http_result.txt');
unlink(tempFile);
The compile lists 3 errors:
*RNF7542 30 3782 006700 Parameter 2 is not valid as a parameter passed by reference.
*RNF5407 20 3781 006600 More parameters were passed in the prototyped call than are allowed.
*RNF5407 20 3781 006600 More parameters were passed in the prototyped call than are allowed.
Is the content type application/json not allowed or are there other errors?
Can the static json code be imbedded in variables as I've done or would it be better to have them stored in a .json file in the IFS?
Any help would be appreciated. If there are examples somewhere that I missed, please point me to them.
Thanks,
Mark
-
- Site Admin
- Posts: 856
- Joined: Sun Jul 04, 2021 5:12 am
Re: Authentication Routine Using JSON
I'm having a hard time gleaning what you are trying to do.
http_mfd_encoder_open() and the other http_mfd_xxx routines are used to create multipart/form-data documents. It is not capable of creating a JSON document. The second parameter (your line 67) is an OUTPUT parameter, it must contain a variable to contain the content-type that gets calculated by the http_mfd_encoder_open() routine. It cannot be used as input, yet you are hard-coding an input value to it.
There are many ways to create JSON. The open source YAJL tool is the one I use most often.
But.. is your question how to create JSON? this is where I'm lost... are you trying to create JSON, or do you have it already and trying to create a multipart document? What does your expected output look like?
http_mfd_encoder_open() and the other http_mfd_xxx routines are used to create multipart/form-data documents. It is not capable of creating a JSON document. The second parameter (your line 67) is an OUTPUT parameter, it must contain a variable to contain the content-type that gets calculated by the http_mfd_encoder_open() routine. It cannot be used as input, yet you are hard-coding an input value to it.
There are many ways to create JSON. The open source YAJL tool is the one I use most often.
But.. is your question how to create JSON? this is where I'm lost... are you trying to create JSON, or do you have it already and trying to create a multipart document? What does your expected output look like?
Re: Authentication Routine Using JSON
After working with the authentication server web developer, we have determined that sending JSON to his authentication routine is not required. He was able to CURL and URL encode the variables to the server and retrieve the (JSON) security token. This is his CURL and JSON output which I'm attempting to emulate.
curl -X POST -k -H "Content-Type: application/x-www-form-urlencoded" -d "clientId=################" -d "clientSecret=##################################" https://xxxxxxxxxxx.com/api/authenticate
{ "Expires": 300, "AccessToken": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"}
This is now almost identical to the recent OATH2 post and I've used most of the code from that example. I'm now getting an "HTTP/1.1 400 Bad Request" error. We've tried several different variations of the code in an attempt to get it to accept the request.
I tried changing the size of ResultStr to 16384 but I got a compile error: The type and attributes of parameter 4 do not match those of the prototype.
I think this is the relevant portion from the log file:
senddoc(): entered
clientID=#######################&clientSecret=#####################################
recvresp(): entered
HTTP/1.1 400 Bad Request
Any help would be appreciated.
-markl
curl -X POST -k -H "Content-Type: application/x-www-form-urlencoded" -d "clientId=################" -d "clientSecret=##################################" https://xxxxxxxxxxx.com/api/authenticate
{ "Expires": 300, "AccessToken": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"}
This is now almost identical to the recent OATH2 post and I've used most of the code from that example. I'm now getting an "HTTP/1.1 400 Bad Request" error. We've tried several different variations of the code in an attempt to get it to accept the request.
I tried changing the size of ResultStr to 16384 but I got a compile error: The type and attributes of parameter 4 do not match those of the prototype.
I think this is the relevant portion from the log file:
senddoc(): entered
clientID=#######################&clientSecret=#####################################
recvresp(): entered
HTTP/1.1 400 Bad Request
Code: Select all
H DFTACTGRP(*NO)
H BNDDIR('HTTPAPI':'YAJL')
/include yajl_h
/copy httpapi_h
/copy ifsio_h
dcl-s clientid varchar(4096) inz('#####################');
dcl-s clientsecret varchar(4096) inz(
'###########################################################');
dcl-s sendData varchar(16384);
dcl-ds authResult qualified;
Expires int(10);
AccessToken varchar(4096);
end-ds;
dcl-s ResultStr varchar(16000000);
d QCMDEXC pr extpgm('QCMDEXC')
d command 200A const
d length 15P 5 const
d msg s 52A
d rc s 10I 0
http_debug(*on);
*inlr = *on;
//
// Build the variables
//
sendData = 'clientID=' + http_urlEncode(clientid)
+ '&clientSecret=' + http_urlEncode(clientsecret);
//
// post the credentials to retrieve the token
//
rc = http_req( 'POST'
:'https://xxxxxxxxxxxxxx.com/api/authenticate'
: *omit
: resultStr // String to receive the results
: *omit
: sendData
: 'application/x-www-form-urlencoded');
//
// error checking
//
if (rc <> 1);
msg = http_error();
dsply msg;
return;
endif;
msg = resultStr;
dsply msg;
data-into authResult %DATA(resultStr)
%PARSER('YAJLINTO');
//
// delete temp files
//
unlink(resultstr);
unlink(sendData);
return;
-markl
Re: Authentication Routine Using JSON
I would check case sensitivity on the parameters first.
Is this code "AI generated"?? You seem to "unlink" string variables??
Is this code "AI generated"?? You seem to "unlink" string variables??
-
- Site Admin
- Posts: 856
- Joined: Sun Jul 04, 2021 5:12 am
Re: Authentication Routine Using JSON
markl wrote: ↑Mon Jan 27, 2025 8:46 pm After working with the authentication server web developer, we have determined that sending JSON to his authentication routine is not required. He was able to CURL and URL encode the variables to the server and retrieve the (JSON) security token. This is his CURL and JSON output which I'm attempting to emulate.
curl -X POST -k -H "Content-Type: application/x-www-form-urlencoded" -d "clientId=################" -d "clientSecret=##################################" https://xxxxxxxxxxx.com/api/authenticate
{ "Expires": 300, "AccessToken": "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"}
so you are posting a form with two variables. That's easy enough.
FWIW: It is called OAUTH2 (Open Authentication version 2) not OATH2.
it needs a 4-byte prefix, so VARCHAR(16384:4). You'll get the compile error with a 2-byte prefix.
that part looks like the same as the curl example.
Code: Select all
H DFTACTGRP(*NO)
H BNDDIR('HTTPAPI':'YAJL')
/include yajl_h
/copy httpapi_h
/copy ifsio_h
dcl-s clientid varchar(4096) inz('#####################');
dcl-s clientsecret varchar(4096) inz(
'###########################################################');
dcl-s sendData varchar(16384);
dcl-ds authResult qualified;
Expires int(10);
AccessToken varchar(4096);
end-ds;
dcl-s ResultStr varchar(16000000);
d QCMDEXC pr extpgm('QCMDEXC')
d command 200A const
d length 15P 5 const
d msg s 52A
d rc s 10I 0
http_debug(*on);
*inlr = *on;
//
// Build the variables
//
sendData = 'clientID=' + http_urlEncode(clientid)
+ '&clientSecret=' + http_urlEncode(clientsecret);
//
// post the credentials to retrieve the token
//
rc = http_req( 'POST'
:'https://xxxxxxxxxxxxxx.com/api/authenticate'
: *omit
: resultStr // String to receive the results
: *omit
: sendData
: 'application/x-www-form-urlencoded');
//
// error checking
//
if (rc <> 1);
msg = http_error();
dsply msg;
return;
endif;
msg = resultStr;
dsply msg;
data-into authResult %DATA(resultStr)
%PARSER('YAJLINTO');
//
// delete temp files
//
unlink(resultstr);
unlink(sendData);
return;
-markl
[/quote]
I don't understand the use of unlink() here. FWIW: unlink() is used to delete a file from the IFS. You are passing strings containing data to it, not filenames, so it doesn't make any sense at all.
I don't see anything wrong with what you've posted. But of course, you've removed most of what was in the log file.
-
- Site Admin
- Posts: 856
- Joined: Sun Jul 04, 2021 5:12 am
Re: Authentication Routine Using JSON
Thank you for the response.
I did find a difference in case but that didn't make a difference - same error: HTTP/1.1 400 Bad Request
The unlink opcode is new to me. I misinterpreted one of the examples I was reviewing. They're for IFS files. I removed that code.
Any other suggestions?
I did find a difference in case but that didn't make a difference - same error: HTTP/1.1 400 Bad Request
The unlink opcode is new to me. I misinterpreted one of the examples I was reviewing. They're for IFS files. I removed that code.
Any other suggestions?
-
- Site Admin
- Posts: 856
- Joined: Sun Jul 04, 2021 5:12 am
Re: Authentication Routine Using JSON
I feel like there's more going on here that you haven't shown us. Is that true?
If this is everything, then I'm not sure what to do next other than ask you how I can reproduce it. If I can run both curl and HTTPAPI I can tell what's different.
If this is everything, then I'm not sure what to do next other than ask you how I can reproduce it. If I can run both curl and HTTPAPI I can tell what's different.
Re: Authentication Routine Using JSON
This issue has been resolved. I had an error in the clientId. The web developer said he was sending a "Bad Request - ClientId/ClientSecret invalid." but I was only seeing "HTTP/1.1 400 Bad Request"
Now that the web service is returning the authorization token, I'm trying to use the YAJL DATA-INTO procedure to parse the JSON data and I'm getting an error with that process. I posted that issue in the YAJL-ILE forum.
Thanks for your help,
markl
Now that the web service is returning the authorization token, I'm trying to use the YAJL DATA-INTO procedure to parse the JSON data and I'm getting an error with that process. I posted that issue in the YAJL-ILE forum.
Thanks for your help,
markl
-
- Site Admin
- Posts: 856
- Joined: Sun Jul 04, 2021 5:12 am