Question
· Feb 20, 2019

Bearer Token Authorization issue with RESTFul API from Ensemble REST Operation EnsLib.REST.Operation

Hi dev community,

I am currently working on a project to send documents to a RESTful based API that supports bearer 
Token Authorization.

When we try to fire a JSON request from our EnsLib.Rest.Operation towards the 3rd party API with a 
valid Token we keep receiving Authorization Error codes HTTP 401 back.

If we use the same request and same Token from a test utility such as Postman the request is 
successful and we are able to move past the authorization stage.

We are inputting the Token in the header of the HTTP request as specified by the 3rd party API 
specification. We therefore are using the following code from the operation side, being tHttpRequest%Net.HttpRequest  object:

set tSC = tHttpRequest.SetHeader("Authorization","Bearer "_$ZSTRIP(pRequest.Token,"<>W"))
   
We can see below the token in the HTTP header that is being fired towards the API:

HTTP HEADER: 
User-Agent: Mozilla/4.0 (compatible; Cache;)
Host: localhost
Accept-Encoding: gzip
Authorization: Bearer 
Khoqt0CHmlbolPd2OAxtroUCQXlLCg-1U8zM9XyuutxwHA8ZCkS-uDuv9SMD0SZX9Eut-KOopyQqwjsx7MLgvGo9s4_LXDyCTzKd
hEqkUubEGJqyACnCc2qGUC8Arm7NYC05qLX6irvXgfPoqJNr9qz_ZK0Iaq4b3M92wgCgYP4_0MZZCAq-F1yDlI_jENOxIuseRuq7
KuDDlTy6fOl3EMBSjR4k-heTTO4vjSyGklOTTXNamql4fd8sRigPVkRP7Vgh4vosn96K9A9xmw-GqrIu_dJqa-1hrzMFp47jIBpF
JQaLfYiKsPvPJAswjCViCVIpDh6-J8LzV7iAhX9yYQ

The question is if we might be missing something in order to set up the EnsLib.Rest.Operation to use Bearer token 
Authorization and whether there is any workaround.

Kind Regards,

Discussion (4)2
Log in or sign up to continue

Hi there,

We have been trying to replicate the same type of header as in POSTMAN -requests from POSTMAN work  fine and we are able to publish to the API- currently we are sending the following:

ENSEMBLE HTTP HEADER: 
User-Agent: Mozilla/4.0 (compatible; Cache;)
host: api-demo.docmansandpit.com
accept-encoding: gzip, deflate
authorization: Bearer 1mIiqOSRtnhHKJ1486gkiVhHglkzZiIviseCYxvdYR9PXbZ1Eg5EgZWKtuBFtdubLlQ8j1vVz-GDY0vzeZadFhYbCBMXVrcPYVI8qVhT8OmxHW4QaFZea-0_elL6iX6T71rDYvMm5R0kYwNduBvkqMXQyEtDkCpFlQE1ollPRtGwm1qCgTF1dH0OcsUt5cL2Z37ESO9zqE5EXmIM4h6tuOBJaS7SiF5xaUyhmZUkpTBDwJi72V39SDIGJg6FU0qP2DYUOe7mppBE2STwj9jjyRB0x3r02XBwotJ9tG6G1tbLxkiEJwIUUOqX_NJKeV1mCi2kY-2KV1ZEC9G2BPniuA
cache-control: no-cache

POSTMAN HTTP HEADER:
cache-control:"no-cache"
postman-token:"85d29666-2e8d-41c2-b8a3-3d77cd070494"
content-type:"application/json"
authorization:"Bearer 
1mIiqOSRtnhHKJ1486gkiVhHglkzZiIviseCYxvdYR9PXbZ1Eg5EgZWKtuBFtdubLlQ8j1vVz-GDY0vzeZadFhYbCBMXVrcPYVI8
qVhT8OmxHW4QaFZea-0_elL6iX6T71rDYvMm5R0kYwNduBvkqMXQyEtDkCpFlQE1ollPRtGwm1qCgTF1dH0OcsUt5cL2Z37ESO9z
qE5EXmIM4h6tuOBJaS7SiF5xaUyhmZUkpTBDwJi72V39SDIGJg6FU0qP2DYUOe7mppBE2STwj9jjyR
B0x3r02XBwotJ9tG6G1tbLxkiEJwIUUOqX_NJKeV1mCi2kY-2KV1ZEC9G2BPniuA"
user-agent:"PostmanRuntime/6.4.1"accept:"*/*"
host:"api-demo.docmansandpit.com"
accept-encoding:"gzip, deflate"
content-length:1255

The 3rd party API keeps responding with 401:  Unauthorized codes back.

We had a look at the documentation for the %Net.HttpRequest class and it states it supports BASIC Http authorization (user:password), does that mean that the http request class doesn't support Token Authorization?

Kind Regards.

Hi Neil,

Thanks for your answer.

I believe it's just the way the POSTMAN console outputs the headers.

Good news is that we finally got it working. After playing a bit with %Net.HttpRequest class we created a utility test class method -  below - where we stopped using the ..Adapter.PostURL() method of the adapter class and called the Post() method of the http request class. We played a bit with the parameters in the header and voila!  we were able to move past the authorization stage:

ClassMethod CallDocmanAPI(pURL As %String, pToken As %String) As %Status
{

Set pOutput=$$$NULLOREF
Set tAdapter = ##class(EnsLib.HTTP.OutboundAdapter).%New()
set tStream = ..TestJsonReader()
!,tStream.Read(tStream.Size)
do tStream.Rewind()

!,"URL : "_pURL

Set pResponse = ##class(UCLH.SIP.Test.REST.DocmanResponse).%New()

#dim tHttpRequest As %Net.HttpRequest
#dim tHttpResponse As %Net.HttpResponse

set tHttpRequest = ##class(%Net.HttpRequest).%New()
set tHttpRequest.ContentType="application/json"
set tHttpRequest.ContentCharset="UTF-8"
set tHttpRequest.FollowRedirect=1
Set tHttpRequest.Https=1
Set tHttpRequest.Port=443
set tSC = tHttpRequest.SetHeader("content-type", "application/json")
set tSC = tHttpRequest.SetHeader("accept","*/*")
set tSC = tHttpRequest.SetHeader("authorization","Bearer "_pToken)
set tSC = tHttpRequest.SetHeader("host","api-demo.docmansandpit.com")
set tSC = tHttpRequest.SetHeader("accept-encoding","gzip, deflate")
set tSC = tHttpRequest.SetHeader("cache-control","no-cache")
set tHttpRequest.SSLConfiguration="TestDocman" 
set tSC = tHttpRequest.EntityBody.CopyFrom(tStream)

!,"HTTP HEADER: ",!,tHttpRequest.ReturnHeaders()
try {
Set tSC=tHttpRequest.Post(pURL,2,1)
Throw:$$$ISERR(tSC) ##class(%Exception.StatusException).CreateFromStatus(tSC)
}
catch (ex) {
Set tSC = ex.AsStatus()
!,$System.Status.GetErrorCodes(tSC)_" : "_$System.Status.GetErrorText(tSC)
Quit 
}
Quit tSC
}

Kind Regards.

Hi,

 just had a look at our code for a similar use and we're doing almost exactly the same:

Do pHTTPRequest.SetHeader("Authorization", "Bearer " _ tOAuthToken)

and that's working fine so I'm not sure why yours is failing (apart from OAuth2 interfaces seem to be very picky).

Btw I'm not sure why but your Postman example headers seem to have picked up a lot of spurious double quotes.

Probably not the same sort of token and probably nothing to do with your problem... but to create a bearer token for the interface I recently wrote I had to do:

s authstring=$TR($SYSTEM.Encryption.Base64Encode(headJSONstring,1),"=")_"."_$TR($SYSTEM.Encryption.Base64Encode(paylJSONstring,1),"=")_"."

s request.Authorization=" Bearer "_authstring

I had set the flag so that the Base64Encode didn't add CR/LF and strip padded ='s from the end and also the other end want a space before the word Bearer as well as after. I don't know if that's standard.

I also only used a standard Ens.BusinessOperation with an EnsLib.HTTP.OutboundAdapter to send my REST requests.