Karate: Problem with requests using bearer token | Karate is showing "org/apache/commons/codec/binary/Base64" in response instead of HTTP 401 [duplicate] - karate

We're automating our test with karate framework. In one of our features we need to decode a token and get a scope in the response. Everything works well, except this code in js.
function(token) {
return JSON.parse(new Buffer(token.split('.')[1],'base64').toString('ascii')).scope;
}
Error:
Caused by: <eval>:2 ReferenceError: "Buffer" is not defined
Caused by: jdk.nashorn.internal.runtime.ECMAException
In official tutorials it is said that javascript is 'native' to karate, so we don't understand why Buffer is not recognized? What we should do? Thanks for any help

I was able to successfully base64Decode a JWT token payload to JSON using the following code without the need for a Java method:
Background:
* def parseJwt =
"""
function(token) {
var base64Url = token.split('.')[1];
var base64Str = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var Base64 = Java.type('java.util.Base64');
var decoded = Base64.getDecoder().decode(base64Str);
var String = Java.type('java.lang.String')
return new String(decoded)
};
"""
Scenario: JWT Token
Given path 'jwt/authenticate'
And header x-goog-authenticated-user-email = 'email'
And request {}
When method get
Then status 200
* json result = parseJwt(responseHeaders['Set-Cookie'][0])
* match result == {permissions: [1,2,3], iss: "us", exp: "#number", email: "email"}
Note: It does seem to be required to use json rather than def as Karate does better if it parses the string to json itself. Also, you may obtain the token from a header rather than a cookie as in this example if so, just change the responseHeader that you are looking for.

I'm pretty sure that Buffer is advanced / non-standard or NodeJS so it probably is not supported by the JVM JS engine (Nashorn).
Here's my recommendation. For this case, do the work using Java utilities.
For example, look at the Karate basic-auth example in the doc which uses Base64 encoding.
If it is really complex, simply create a Java static function, it will be much easier to test as a side-benefit. Hope this helps !

With respect to the post Karate: Problem with requests using bearer token | Karate is showing "org/apache/commons/codec/binary/Base64" in response instead of HTTP 401
My query was marked duplicate hence posting an answer/solution which we have found in our project.
We did some debugging in karate core about the error. It seemed a dependency was missing.
We added the dependency in the POM.xml
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
Afterwards the problem was resolved and we started getting HTTP 401.
I am not sure it can be added to the karate core.

Related

How to solve HTTPError: 400 Client Error: Bad Request for URL inRobot Frame work

I know there are many similar kinds of questions available but none of them worked.
Can someone tell me if there is any kind of syntax error for the Testcase below
Create Token
Create Session testsession ${baseUrl} verify=true
${body}= create dictionary clientId=unittest.cc.client clientSecret=RyDQ$xxxxxRtv
${header}= create dictionary Content-Type=application/json
${resp}= POST On Session testsession ${reqUri} json=${body} headers=${header} params=${ApiKeyParameter}
${source data}= Evaluate json.loads("""${resp.content}""") json
${token}= Set Variable ${source data['accessToken']}
#No errors Uptill this much - Bearer token creation was successful after that getting error while using it
${header}= create dictionary Authorization=${tpre} ${token} Content-Type=application/json cookies=ss-id=KF84fFy4txxxxxxxxx76i; ss-pid=StDTDxxxxxxxxxxxxn7r
${body}= get file API/data.txt
log to console ${header}
${resp}= post on session testsession /orders json=${body} headers=${header}
log to console ${resp.status_code}
The problem is every time I run the test I am getting a 400 error. Below is the Python code provided by POSTMAN and the screenshots of the headers used. Now I am not sure of how to get the HOST header in my python or maybe robot framework.
Please let me know if any additional details are needed. I am not sure of headers in the URL formation while get or post request is done
Is there any way to find that out?
import requests
import JSON
url = "https://domain:10001/orders?format=json"
payload = json.dumps({ Can ignore this part
})
headers = {
'Authorization': 'Bearer xxx',
'Content-Type': 'application/json',
'Cookie': 'ss-id=xxx; ss-pid=xxx'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
If you all ever come across this kind of issue don't forget to check the body of the JSON / XML you are sending.
Mine resolved as I was saving the dump JSON in a text file so while reading from the file my code was adding some extra spaces in front so I was getting a 400 error.
For further information try logging the Response Content it must show you the error message.

Karate DSL - Converting a PNG response to Base64 [duplicate]

We're automating our test with karate framework. In one of our features we need to decode a token and get a scope in the response. Everything works well, except this code in js.
function(token) {
return JSON.parse(new Buffer(token.split('.')[1],'base64').toString('ascii')).scope;
}
Error:
Caused by: <eval>:2 ReferenceError: "Buffer" is not defined
Caused by: jdk.nashorn.internal.runtime.ECMAException
In official tutorials it is said that javascript is 'native' to karate, so we don't understand why Buffer is not recognized? What we should do? Thanks for any help
I was able to successfully base64Decode a JWT token payload to JSON using the following code without the need for a Java method:
Background:
* def parseJwt =
"""
function(token) {
var base64Url = token.split('.')[1];
var base64Str = base64Url.replace(/-/g, '+').replace(/_/g, '/');
var Base64 = Java.type('java.util.Base64');
var decoded = Base64.getDecoder().decode(base64Str);
var String = Java.type('java.lang.String')
return new String(decoded)
};
"""
Scenario: JWT Token
Given path 'jwt/authenticate'
And header x-goog-authenticated-user-email = 'email'
And request {}
When method get
Then status 200
* json result = parseJwt(responseHeaders['Set-Cookie'][0])
* match result == {permissions: [1,2,3], iss: "us", exp: "#number", email: "email"}
Note: It does seem to be required to use json rather than def as Karate does better if it parses the string to json itself. Also, you may obtain the token from a header rather than a cookie as in this example if so, just change the responseHeader that you are looking for.
I'm pretty sure that Buffer is advanced / non-standard or NodeJS so it probably is not supported by the JVM JS engine (Nashorn).
Here's my recommendation. For this case, do the work using Java utilities.
For example, look at the Karate basic-auth example in the doc which uses Base64 encoding.
If it is really complex, simply create a Java static function, it will be much easier to test as a side-benefit. Hope this helps !
With respect to the post Karate: Problem with requests using bearer token | Karate is showing "org/apache/commons/codec/binary/Base64" in response instead of HTTP 401
My query was marked duplicate hence posting an answer/solution which we have found in our project.
We did some debugging in karate core about the error. It seemed a dependency was missing.
We added the dependency in the POM.xml
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
Afterwards the problem was resolved and we started getting HTTP 401.
I am not sure it can be added to the karate core.

Is anyone using Karate for Salesforce API testing? [duplicate]

Karate has been super helpful to validate our rest apis which gives json response. Now we have apis which gives us response in avro format. May also need to send the payload in avro format. How can i test the rest endpoints which gives response in AVRO format using karate? Is there any easy way I can tweak and get it done. Thanks!
Here's my suggestion, and in my opinion this will work very well.
Write a simple Java utility, maybe a static method that can take JSON and convert it to AVRO and vice versa.
Now you can define all your request data as JSON - but just before you make the request to the server, convert it to AVRO. I am not sure if the server call is HTTP or not. If it is HTTP - then you know what to do in Karate, just send binary as the request body etc.
Else you may not even use the Karate HTTP DSL like method, request etc. You have to write one more Java helper that will take your JSON (or AVRO) and make the call to the server (specific for your project) and return the response, converted back to JSON. For example:
* def Utils = Java.type('com.myco.avro.Utils')
* def json = { hello: 'world' }
* def req = Utils.toAvro(json)
* def res = Utils.send(req)
# you can combine this with the above
* def response = Utils.fromAvro(res)
* match response == { success: true }
Yes, you might be using Karate mostly for matching, reporting, environments etc. Which is still valuable ! Many people don't realize that HTTP is just 10% of what Karate can do for you.

JWT Bearer token in ABCchrome header

I am using ABCPdf 11 to convert html to pdf, my html page which needs to be converted required JWT token so that needs to be passed to ABCChrome so it can use the JWT token.
I have tried the following but the auth still fails:
doc.HtmlOptions.HttpAdditionalHeaders = $"Authorization: Bearer {accessToken}";
I followed example from here: https://www.websupergoo.com/helppdfnet/default.htm?page=source%2F5-abcpdf%2Fxhtmloptions%2F2-properties%2Fhttpadditionalheaders.htm
From the description in the above URL, I have also tried the below options:
doc.HtmlOptions.NoCookie = true;
doc.HtmlOptions.Media = MediaType.Screen;
After adding HttpAdditionalHeaders and when I get the http status from the pdf library I do get 401 http status code which confirms the
var imageId = doc.AddImageUrl(model.Url);
var status = doc.HtmlOptions.ForChrome.GetHttpStatusCode(imageId);
The status here is 401 - unauthorized
The HttpAdditionalHeaders property is not currently supported by the ABCChrome Engine. The only HtmlOptions supported by ABCChrome are specified here.
There are a few things you could try:
Check whether the target server supports sending the web token via GET request parameters - I guess you've probably done this already :-)
Make the AddImageUrl request URL to an intermediary web server (even a local HttpServer) to a script which can fetch the page for you based on any GET parameters.
If the service you are attempting to access accepts ajax requests you could try using javascript to inject the response into a page using XMLHttpRequest.setRequestHeader(). NB if you use a local file (e.g. file://) for this you may come across some Chromium enforced JavaScript security issues.
I do know that WebSupergoo offer free support for all their licenses, including trial licenses.
Good luck.
Emailed ABCPdf support and unfortunately ABCChrome does not support HttpAdditionalHeaders property so the work around is to download the html ourselves and convert that to PDF, see example below:
var imageId = doc.AddImageHtml(html); // <- html downloaded from auth url
Also don't forget to add paging:
// add all pages to pdf
while (doc.Chainable(imageId))
{
doc.Page = doc.AddPage();
imageId = doc.AddImageToChain(imageId);
}
for (int i = 1; i <= doc.PageCount; i++)
{
doc.PageNumber = i;
doc.Flatten();
}

Cannot JSON.parse serverless event.body

I’ve been working on a simple function with the serverless framework that gets some data in a http POST, does some analysis and sends the results back. I got it working locally on my machine using serverless-offline but when it comes to deploying it I’m getting an error parsing the event.body.
Logging out the event.body it’s a string that looks like this:
----------------------------267253304929569989286258
Content-Disposition: form-data; name="text"
TEST
----------------------------267253304929569989286258--
so it makes sense that the parse is failing but I have no idea why this error it happening.
Any suggestions? I’ve tried a bunch of different things but am completely stumped.
Thanks in advance!
You can't JSON.parse that event.body cause it isn't JSON. It looks like whatever POSTed that data is using a multipart form POST style request rather than sending JSON. How are you invoking the HTTP POST?
I had the same issue and after a lot of debugging noticed 2 important things:
1.When the content type is application/x-www-form-urlencoded you might need to parse the data in a different way:
const qs = require('querystring');
module.exports.run = async event => {
try {
const data = qs.parse(event.body);
console.info('DATA:', data);
} catch(e) {
console.error(e.message);
}
}
2.When the Content-Type of the request is multipart/form-data the parsing will be even more complicated. I will suggest extra dependency to parse it like multiparty or any other of your choice
Thank you #Brian Winant! I am putting the answer here as a screenshot so it's clearer. In Postman, do the following:
AWS Lambda would return event.body as encoded query strings if the content-type is x-www-urlencoded. To have it return a JSON string you can then parse, send JSON data and set content-type as application/json.