PDA

View Full Version : Consuming RestAPI Data with Basic Authentication in 18.2



ajmsrs
13-Aug-2019, 06:41 PM
I'm trying to get data from a Rest API that requires "Basic Authentication". I am able to access the data from Python so i know my credentials are valid. In dataflex 18.2 I am able to use a cHttpTransfer to access data from Rest APIs with no authentication with no problem. My question is this-- is setting the psUsername and psPassword properties of an cHttpTransfer object equivalent to "basic authentication". Because when I set those to my known valid credentials the API tells me that I have not authenticated. If that is not sufficient authentication, is there a nice complete example somewhere of how to do basic authentication with only 18.2 objects? Unfortunately the mailchimp example uses the Json objects which I don't have.

Alternatively is there some low level debugging technique that would allow me to see what's going on with the transfer? I'm kinda stuck on how to debug this.

Thanks!

Mike Peat
14-Aug-2019, 02:40 AM
Hi ajmsrs

Yes, setting psUsername and psPassword is equivalent to Basic Authentication, however I have found that while it works OK the first time, if you then try using a different set of credentials it seems to cache the original ones (this may be a bug - I'm not sure).

Instead, I prefer to set it explicitly in the HTTP headers, as follows:



Send ClearHeaders of oHttp // oHttp is an object of the cHttpTransfer class, BTW - I usually have this line in a Procedure Reset in that

If (sAuth = "Basic") Begin // oCreds holds the psUserName; oPassword holds the psPassword obviously
Move (Value(oCreds) + ":" + Value(oPassword)) to sToken
Move (Base64Encode(AddressOf(sToken), Length(sToken))) to pCreds
Move pCreds to sToken
Move (Free(pCreds)) to bOK
Get AddHeader of oHttp "Authorization" ("Basic" * sToken) to bOK // This does the same as setting psUsername and psPassword
End


See if that helps.

Mike

starzen
14-Aug-2019, 03:17 AM
Basic Authentication can be a bit tricky especially when relying on the automated implementation

Basic Auth works in 2 different modes

Direct Authentication
the authentication header is set manually and sent all the time with the request

Challenge Response Model
the automated implementation or the way the browser works is with the challenge response model. The way this works is that the first request to the server does not send authentication information at all. The server then responds with a 401 (not authorized) response which causes the client to resend the request with the authentication information.

so if you are using the challenge/response model and your server doesnt respond with a 401 the client will never send the authentication information

to work around this issue you can just set the authentication headers manually

to debug you can use Fiddler or Wireshark. Fiddler is easier to use and plenty for all http communication. Wireshark is more complex but can look at a lot more than fiddler

ajmsrs
14-Aug-2019, 02:40 PM
That did it. Thanks!

ajmsrs
14-Aug-2019, 03:04 PM
can't delete a post here? oh well

jason
3-Feb-2020, 07:33 PM
Hi ajmsrs,

You may have likely solved this problem by now, but if not or anyone else has stumbled across this and would like to achieve this then please see below.

You will need to add the "Authorization" header to the cHttpTransfer object.
The value is "Basic <Base64 Encoded with padding result of user:password>"

For example, using the basic auth test API on this page:
https://docs.postman-echo.com/?version=latest

Username: postman
Password: password

In Notepad++, type in postman:password then select the text (avoid any spaces etc) -> Plugins -> MIME Tools -> Base 64 Encode with padding.
Then you have the encoded Base64 value ready to send in the header: Basic cG9zdG1hbjpwYXNzd29yZA==

Example code:


Function AddHeader String sHeaderName String sHeaderValue Returns Integer


// Add Authorization header -> "Basic user:password(Base64 Encode with padding)"
Get AddHeader of hoHttp "Authorization" "Basic cG9zdG1hbjpwYXNzd29yZA==" to iRes


EDIT: Didn't realise there were responses here. (Threaded view :P). Sorry to dig this up.