Authorization header not working for second request in same scenario - karate

My Requirement -
Create a issue using Post Request.
Read the issueId from the response and delete that Issue ID.
Feature file which is NOT working:
Feature: To Delete a issue after creating it
Background:
* header Authorization = 'Bearer '+ tokenId
Scenario:
Given url baseUrl+'/projects/5/issues?title=Issues%20with%20auth&labels=bug'
When method POST
Then status 201
* def issueToBeDeleted = response.iid
Given url baseUrl+'/projects/5/issues/'+ issueToBeDeleted
When method DELETE
Then status 204
Feature which is working:
Feature: To Delete a issue after creating it
Background:
* header Authorization = 'Bearer '+ tokenId
Scenario:
Given url baseUrl+'/projects/5/issues?title=Issues%20with%20auth&labels=bug'
When method POST
Then status 201
* def issueToBeDeleted = response.iid
* header Authorization = 'Bearer '+ tokenId
Given url baseUrl+'/projects/5/issues/'+ issueToBeDeleted
When method DELETE
Then status 204
I had to call Authorization header again to make delete request. I assumed, if its defined in background then it should be called for all the requests. Am I making any mistake here?
Thanks,
Abhi

Yes, you should be doing:
* configure headers = { Authorization: "#('Bearer ' + tokenId)" }
Please read the docs: https://github.com/karatelabs/karate#http-header-manipulation

Related

How to get access token using Karate oauth 2.0 Authorization implicit grant type

I tried to automate using karate framework following steps which I did in postman.
How I tried in Postman:
On Authorization tab select OAuth 2.0
Select Header Prefix Bearer
Grant-Type is "Implicit"
I put Callback URL
I put Auth URL
I put Client ID
Select "Client Authentication" as Send as Basic Auth Header.
I used following code in order to get Access token
Background:
* url 'Auth URL'
Scenario: Verify the user details using OAuth2 Implicit grant type
* form field callbackurl = 'callbackurl'
* form field grant_type = 'implicit'
* form field client_id = 'client id'
* form field username = 'username'
* form field password = 'password'
* method post
* status 200
* print response
* def accessToken = response.access_token
* path 'resource'
* header Authorization = 'Bearer ' + accessToken
# * param access_token = accessToken
* method post
* status 200
In output I got
// UserpoolId is not available on frontend for springboard. We do not use userPoolId
// anyway other than put in context data.
var userPoolId = "";
var clientId = getUrlParameter("client_id");
I do not know where I am wrong. Please provide your help. Thanks!

status":401,"error":"Unauthorized","message":"","path":"/oauth/token"} /feature/HomeOuath

Feature: oauth test using
nephos-qe-sec.az.staples.com/oauth
Background:
url 'https://<<>>/oauth/token'
Scenario: oauth flow
header Content-Type = 'application/x-www-form-urlencoded'
configure ssl = true
form field grant_type = 'client_credentials'
request 'client_id=<<>>&client_secret=<<>>'
method post
status 200
def accessToken = response.access_token
Getting 401 error when running from Karate Framework.
Tried with getting the similar error.
form field client_id = '<<>>'
form field client_secret = '<<>>'
401 Snapshot

Why does karate configure headers behave differently to setting headers directly in the background?

I wrote a test that calls an api endpoint once and retrieves an etag in the response. After that I do a second call and I am setting the etag value to the if-none-match header. The test looks like the following:
Feature: Retrieve station properties
Background:
* url baseUrl
* def contentType = 'application/vnd.whatever'
* def accessToken = 'ey.foobar.123'
* configure headers = { Authorization: '#("Bearer " + accessToken)', Accept: '#(contentType)' }
Scenario: Fetch station properties once and expect a 304 on the sub-sequent request
Given path '/api/station-properties'
When method GET
Then status 200
And headers {ETag: '#notnull'}
And def etag = responseHeaders['ETag'][0]
Given path '/api/station-properties'
And header If-None-Match = etag
When method GET
Then status 304
This basically works but I was not happy with the configure headers line as I may add additional headers later on. Thus I thought about using a different method to set the headers:
Feature: Retrieve station properties
Background:
* url baseUrl
* def contentType = 'application/vnd.whatever'
* def accessToken = 'ey.foobar.123'
* header Authorization = 'Bearer ' + accessToken
* header Accept = contentType
Scenario: Fetch station properties once and expect a 304 on the sub-sequent request
Given path '/api/station-properties'
When method GET
Then status 200
And headers {ETag: '#notnull'}
And def etag = responseHeaders['ETag'][0]
Given path '/api/station-properties'
And header If-None-Match = etag
When method GET
Then status 304
In this case though, the headers (Authorization and Accept) are set on the first api call but on the second call they are not.
Why is this the case?
Yes, the rule is configure is to "persist" for multiple HTTP calls. So just make this change in the Background:
* configure headers = ({ Authorization: 'Bearer ' + accessToken, Accept: contentType })
Well, yes - do what you were doing earlier. Now it should work.

Advice for implementing custom authentication scheme [duplicate]

First of all, thanks for build karate it's a very useful for test API's and UI's. We are using it to test a lot of our endpoints but we would like to know if there is a way or which is the best approach to handle requests with signature as part of the request in the header.
In our case we have two headers:
ApiKey: this value is always the same
Signature: this value depends on the request body content
Is there any way to inject the signature value just before the request is executed based on the request body content?
Here you can see two samples of the requests
Sample 1:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'YYY'
And request { }
When method POST
Then status 200
Sample 2:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'ZZZ'
And request { name: 'John' }
When method POST
Then status 200
Thanks
Karate has a "hook" for generating headers, but as of now it is not "aware" of the currently built request body + headers: https://github.com/intuit/karate#configure-headers
We got a similar request here, and are thinking of adding this capability: How to retrieve raw request contents before making a REST call in Karate DSL?
Maybe the OAuth examples will give you the way forward for your case for now: https://stackoverflow.com/a/55055111/143475
Feel free to raise an enhancement request, and we can get this in to the next version (with your help to test it). I'm thinking - what if you are able to call karate.get('request') from within the header JS function.
But for now all you need to do is do something like this:
* def body = { some: 'json' }
* karate.set('requestBody', body)
* url someUrl
* request body
* method post
And in the header.js function
function fn() {
var body = karate.get('requestBody');
var sign = Utils.sign(body);
return { Signature: sign };
}
EDIT: this will be implemented in Karate 1.0 onwards: https://github.com/intuit/karate/issues/1385

How to handle requests with signatures on karate tests?

First of all, thanks for build karate it's a very useful for test API's and UI's. We are using it to test a lot of our endpoints but we would like to know if there is a way or which is the best approach to handle requests with signature as part of the request in the header.
In our case we have two headers:
ApiKey: this value is always the same
Signature: this value depends on the request body content
Is there any way to inject the signature value just before the request is executed based on the request body content?
Here you can see two samples of the requests
Sample 1:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'YYY'
And request { }
When method POST
Then status 200
Sample 2:
* url 'https://dev.sample.com'
* path '/api/user/getAll'
* header Content-Type = 'application/json'
* header ApiKey = 'XXX'
* header Signature = 'ZZZ'
And request { name: 'John' }
When method POST
Then status 200
Thanks
Karate has a "hook" for generating headers, but as of now it is not "aware" of the currently built request body + headers: https://github.com/intuit/karate#configure-headers
We got a similar request here, and are thinking of adding this capability: How to retrieve raw request contents before making a REST call in Karate DSL?
Maybe the OAuth examples will give you the way forward for your case for now: https://stackoverflow.com/a/55055111/143475
Feel free to raise an enhancement request, and we can get this in to the next version (with your help to test it). I'm thinking - what if you are able to call karate.get('request') from within the header JS function.
But for now all you need to do is do something like this:
* def body = { some: 'json' }
* karate.set('requestBody', body)
* url someUrl
* request body
* method post
And in the header.js function
function fn() {
var body = karate.get('requestBody');
var sign = Utils.sign(body);
return { Signature: sign };
}
EDIT: this will be implemented in Karate 1.0 onwards: https://github.com/intuit/karate/issues/1385