How to use HTTPAPI for OAuth 2.0 protocol authentication

Discussions related to HTTPAPI (An HTTP Client Package for RPG programming.) http://www.scottklement.com/httpapi/
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by Scott Klement »

So is your question "why are they requiring a redirect_uri?" If so, you are asking the wrong person -- this error is coming from the API, not from me. You have to ask Stamps (or whomever it is that provides the API) why they are sending this error when you've previously discussed not using a redirect URI..
sbehera00
Posts: 16
Joined: Mon Jul 22, 2024 10:29 pm

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by sbehera00 »

Hello Scott/John,
showing log to provider, they realized they have given me wrong information as far as what parameters required to call oauth/token for authorizaion code based call vs refresh_token based call. Here are the parameters and now i am getting access/refresh token. But my rc value after http_Req call is 1, i was expecting 200. Also in the debug log "SetError() #13: HTTP/1.1 200 OK", what this mean?

PostString = '{ "grant_type": "authorization_code", ' +
'"client_id":' + #Qd + %Trim(UEPCID) + #Qd + ',' +
'"client_secret":' + #Qd + %Trim(UEPCSC) + #Qd + ',' +
'"code":' + #Qd + %Trim(#Aut_Code) + #Qd + ',' +
'"redirect_uri":' + #Qd + %Trim(urr) + #Qd + '}';
rc = http_req('POST': urt: *omit : result : *omit : postsstring);
If rc > 199 and rc < 300 ;
Exsr ReadRefTkn;
Else;
ExSr ReadTknError;
EndIf;

DebugLog:
senddoc(): entered
{ "grant_type": "authorization_code", "client_id":"aShxEuP...
recvresp(): entered
HTTP/1.1 200 OK
Date: Fri, 02 Aug 2024 16:42:35 GMT
SetError() #13: HTTP/1.1 200 OK
recvresp(): end with 200
recvdoc parms: chunked 0
header_load_cookies() entered
chunk size = 1017
get_chunk_size returned 1017
calling comm_blockread
{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCI
comm_blockread returned 1017
get_chunk_size(): entered
0

chunk size = 0
get_chunk_size returned 0
http_close(): entered


For my next step to make label API:
I have to call https://api.testing.stampsendicia.com/sera/v1/labels, according to documentation, i got to pass following in header
Headers:
Authorization: Bearer [Your Access Token]
Content-Type: application/json

I am doing http_req but do not see how to pass 2 pieces of header information in to http_req?
Note: postdata has body detail jason
rc = http_req( 'POST': url: *omit : result : *omit : postdata);
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by Scott Klement »

sbehera00 wrote: Fri Aug 02, 2024 6:00 pm showing log to provider, they realized they have given me wrong information as far as what parameters required to call oauth/token for authorizaion code based call vs refresh_token based call. Here are the parameters and now i am getting access/refresh token. But my rc value after http_Req call is 1, i was expecting 200. Also in the debug log "SetError() #13: HTTP/1.1 200 OK", what this mean?
This means the request was successful. http_req() always returns 1 if it was successful. 200 is the HTTP status code for success.
sbehera00 wrote: Fri Aug 02, 2024 6:00 pm PostString = '{ "grant_type": "authorization_code", ' +
'"client_id":' + #Qd + %Trim(UEPCID) + #Qd + ',' +
'"client_secret":' + #Qd + %Trim(UEPCSC) + #Qd + ',' +
'"code":' + #Qd + %Trim(#Aut_Code) + #Qd + ',' +
'"redirect_uri":' + #Qd + %Trim(urr) + #Qd + '}';
rc = http_req('POST': urt: *omit : result : *omit : postsstring);
If rc > 199 and rc < 300 ;
Exsr ReadRefTkn;
Else;
ExSr ReadTknError;
EndIf;
This will work fine as long as there are no special characters in your data that need to be escaped, and the document is always run from a system with the same CCSID that it was compiled on.

However, you should consider using a JSON tool will work in all situations. I provide the open source YAJL (which can be used with the DATA-GEN and DATA-INTO opcodes) as a way to create and/or interpret JSON documents for free https://www.scottklement.com/yajl/

IBM also provides one in the SQL environment that can be called from RPG. I personally don't like the SQL one, but it works.
sbehera00 wrote: Fri Aug 02, 2024 6:00 pm For my next step to make label API:
I have to call https://api.testing.stampsendicia.com/sera/v1/labels, according to documentation, i got to pass following in header
Headers:
Authorization: Bearer [Your Access Token]
Content-Type: application/json

I am doing http_req but do not see how to pass 2 pieces of header information in to http_req?
Content-type is a required header, as such it is a parameter to http_req. You cannot send data (legitmately) without also sending a content-type, so HTTPAPI will always add it for you. If you don't pass it (which seems to be the case, above) httpapi will use the default value in CONFIG_H (which I believe is text/xml)

Authorization in HTTPAPI is handled by calling a routine named HTTP_setAuth. This must be called prior to the request.

Code: Select all

HTTP_setAuth( HTTP_AUTH_BEARER: '': YourAccessToken);

rc = http_req( 'POST': url: *omit : result : *omit : postdata: 'application/json');
sbehera00
Posts: 16
Joined: Mon Jul 22, 2024 10:29 pm

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by sbehera00 »

Hello Scott,
thank you very much for your help. All authorization part is working fine now only the issue is for label API call, I need to pass Idempotency-Key in header. Question is
1. How to generate Idempotency-Key in as400 ?
2. How to pass Idempotency-Key in the header ?

note: from previous conversation, i am using YAJL tool to read (yajl_string_load_tree, yajl_object_find ) data returned from http_req but not while sending the request. Not sure what is use/difference/advantages of yajl_string vs DATA-GEN and DATA-INTO opcodes.

Debug log:
recvdoc(): Receiving 181 bytes.
{"error_reference_id":"0bba9a9a-4d90-4580-9d94-d95c46299c47","errors":[{"error_code":"800002","error_message":"Idempotency-Key header not found for enforced idempotent endpoint."}]}
SetError() #13: HTTP/1.1 400 Bad Request
http_close(): entered
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by Scott Klement »

sbehera00 wrote: Tue Aug 06, 2024 7:50 pm thank you very much for your help. All authorization part is working fine now only the issue is for label API call, I need to pass Idempotency-Key in header. Question is
1. How to generate Idempotency-Key in as400 ?
2. How to pass Idempotency-Key in the header ?
Idempotency Key is only used by a few APIs, it is not a common requirement. The 3 or so APIs I've seen it used in all generate it completely differently, so I can't say "generate it with X", because you have to know the specific API and what its requirement is.

Once you've generated your Idempotency Key, you can add the header using the HTTP_POINT_ADDL_HDR xproc. (Like any other custom header.)
sbehera00 wrote: Tue Aug 06, 2024 7:50 pm note: from previous conversation, i am using YAJL tool to read (yajl_string_load_tree, yajl_object_find ) data returned from http_req but not while sending the request. Not sure what is use/difference/advantages of yajl_string vs DATA-GEN and DATA-INTO opcodes.
The YAJL subprocedures are more versatile and allow for the entire JSON specification.

DATA-INTO is somewhat easier to code and understand, but doesn't support 100% of the options of JSON.
DATA-GEN generates JSON... so it's like the yajl_genOpen, yajl_addChar, etc routines.
sbehera00
Posts: 16
Joined: Mon Jul 22, 2024 10:29 pm

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by sbehera00 »

Hello Scott,
here is what provider documentation says
"Idempotency-keys must be a randomly-generated version-4 UUID. Most programming languages support generating random UUIDs out-of-the-box. If an invalid Idempotency-key is included with an request, an error will be returned."
If you can provode some help on how to generate this?

To proceed testing with label API, i got one time key from online and hardcoded to my code. When i run through debug, do see it waits for 20-30 second at the label API call then times out with error "SetError() #44: CommTCP_read: Socket has been shut down.".
I am thinking i may be passing Idempotency-key as additional header info incorrectly. Do not know how exactly to use xproc to pass additional info. Attaching my code and log, if you can help, please?

Code:
// Retrieve access token
rc = http_req('POST': urt: *omit : result : *omit : poststring);
// Set Authority
HTTP_setAuth( HTTP_AUTH_BEARER: '': #Acc_Token);
HTTP_XPROC( HTTP_POINT_ADDL_HEADER: %paddr(AddHeaders));
// Call label API
rc = http_req( 'POST': url: *omit : result : *omit : postdata :
'application/json');
........
P AddHeaders B
D AddHeaders PI
D addHdr 500A varying

/free
// Got the Idemp key from online for one time use until figured out how to generate in RPG
#Idemp_Code = '89b70a96-f5ff-4b7b-9172-259add9b53b6';
addHdr = #Qd + %Trim(#Idemp_Code) + #Qd;
/end-free
P E

Debug Log:
senddoc(): entered
{ "grant_type": "refresh_token", "client_id":"CID","client_secret":"CS","refresh_token":"RT"}
recvresp(): entered
HTTP/1.1 200 OK
chunk size = 953
get_chunk_size returned 953
calling comm_blockread
{"access_token":"RAT","scope":"offline_access","expires_in":900,"token_type":"Bearer"}
comm_blockread returned 953
chunk size = 0
get_chunk_size returned 0
http_close(): entered
HTTPAPI Ver 1.43 released 2021-04-19
NTLM Ver 1.4.0 released 2014-12-22
OS/400 Ver V7R3M0
http_setauth(): entered
POST /sera/v1/labels HTTP/1.1
Host: api.testing.stampsendicia.com
User-Agent: http-api/1.43
Content-Type: application/json
Accept: application/json
Content-Length: 879
Authorization: Bearer
senddoc(): entered
{ "from_address" : { "company_name" :
recvresp(): entered
SetError() #44: CommTCP_read: Socket has been shut down.
recvresp(): end with err
http_close(): entered
Scott Klement
Site Admin
Posts: 872
Joined: Sun Jul 04, 2021 5:12 am

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by Scott Klement »

  • That's not a valid HTTP header. When you use the additional headers xproc, you need to code correctly for the HTTP protocol. HTTPAPI is allowing you to insert anything you want, it's your responsibility to know how to do it correctly for the protocol. It's very powerful, but somewhat dangerous.
  • In this case, you're not providing the header name, separator or the CRLF that terminates the header.
  • I have no idea what #Qd is... but I doubt it belongs here
  • Ugh! fixed format!

Code: Select all

     D*ame+++++++++++ETDsFrom+++To/L+++IDc.Keywords+++++++++++++++++++++++++
     P AddHeaders      B
     D AddHeaders      PI
     D addHdr                     32767A   varying

      /free

       // Got the Idemp key from online for one time use until figured out how to generate in RPG
       #Idemp_Code = '89b70a96-f5ff-4b7b-9172-259add9b53b6';
       addHdr = 'Idempotency-Key: ' + %Trim(#Idemp_Code) + x'0d25';

      /end-free
     P                 E 
sbehera00
Posts: 16
Joined: Mon Jul 22, 2024 10:29 pm

Re: How to use HTTPAPI for OAuth 2.0 protocol authentication

Post by sbehera00 »

Hello Scott,
did correct as you mentioned, all working fine now.

Thank you very much for your help...
Post Reply