How to parameterize Bearer token authorization in Jmeter - jmeter

I have a jmeter login script where user logs in and logs out. The detailed screenshots are attached below.
Request data is as attached:
In the response date , the authorization token is generated:
And the regular expression for the same is as below:
I am passing the value as parameter in 55/users:
When I'm running the script it is failing:
Here is the response data:

Use Header Manager to pass the Token as a Header so you would have:
See for more details:
https://stackoverflow.com/a/43283700/460802
If you're looking to learn jmeter correctly, this book will help you.

A bit easier JMeter setup (login/get):
Thread Group
HTTP Request, Body Data: { "Login":"some", "Password":"credentials" }
HTTP Header Manager: content-type application/json
JSON Extractor - Names of created variables: Token; JSON Path expression: tokenName (root level in my case)
HTTP Request
HTTP Header Manager: content-type -> application/json; Authorization -> Bearer ${Token}
Response Assertion: Fields to Test = Response Code; Pattern Matching Rules = Equals, Not; Pattern to Test 401
View Results Tree to check results
Local IE Ajax version in case...
<SCRIPT>
var baseUri = 'https://localhost:port';
var tokenUri = '/something';
var getUri = '/restrictedData';
var token;
var form = { "Login":"some", "Password":"credentials" };
postRequest(baseUri + tokenUri, form, gotToken)
function gotToken(progress) {
var response = progress.srcElement;
if (response.status != 200) {
document.body.innerText = "Error:\n" + response.response;
return;
}
token = JSON.parse(response.response);
console.log(JSON.stringify(token));
var restricted = getRequest(baseUri + getUri, token.tokenName, gotRestricted);
}
function gotRestricted(progress) {
var jsonStr = progress.srcElement.response;
var jsonObj = JSON.parse(jsonStr);
document.body.innerText = JSON.stringify(token,null,2) + '\n\n' + JSON.stringify(jsonObj,null,2);
}
function getRequest(url, token, callback) {
var xhr = new XMLHttpRequest();
xhr.onloadend = callback;
xhr.open('GET', url);
xhr.setRequestHeader('contentType', 'application/json')
if (token) xhr.setRequestHeader("Authorization", "Bearer " + token);
xhr.send();
return xhr;
}
function postRequest(url, body, callback) {
var xhr = new XMLHttpRequest();
xhr.onloadend = callback;
xhr.open('POST', url);
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(JSON.stringify(body));
return xhr;
}
</SCRIPT>

Add Bearer ${token} in HTTP Header Manager available under failing HTTP Request.

If you already have the bearer token and just want to use in in header manager then,
in HTTP HEADER MANAGER tab, put these values under NAME and VALUE column respectively.
Name: Authorization
Value: Bearer "add your actual token without quotes"

Once you've extracted the token from the token API request, use this token in the HTTP Authorization Header manager for subsequent API's. Example below:
Header Name: Header Value Authorization: Bearer ${generated_token}
Where "generated_token" is a variable containing the extracted token.

I got cUrl from my API and then I imported it.

use Authorization as parameter name and value should be
Bearer ${variable_name}

Related

Adding multiple headers to graphql client (apollo-boost)

const client = new ApolloClient({
uri,
onError: (e: any) => {
console.log('error: ', e); // Failed to fetch
console.log(e.operation.getContext()); // it does show it has x-abc-id
},
request: operation => {
const headers: { [x: string]: string } = {};
const accessToken = AuthService.getUser()?.accessToken;
const activeClientId = UserService.getActiveClientId();
headers['x-abc-id'] = activeClientId;
if (accessToken) headers['Authorization'] = `Bearer ${accessToken}`;
operation.setContext({ headers });
}
});
The problem here is when i just add Authorization header it makes the POST call and shows the expected error.
But when i add x-abc-id header which is also expected by backend it only makes OPTIONS call (no post call)
P.S. On postman adding both headers works completely fine.
Found what the issue was, thought to share if it help.
Postman does not perform OPTIONS call before sending request to backend.
In OPTIONS call, 👇represents what client call contains: [authorization, content-type, x-abc-id]
BUT what does server expects: 👇
Just authorization, content-type
So it's a calls headers mismatch (nothing related to Apollo).
x-abc-id header explicitly has to be allowed in CORS configuration on backend.
Thanks to Pooria Atarzadeh

Cannot call aws API Gateway via ajax

I am using aws APi gateway and api gateway custom authorizer. The code that I have for api gateway custom authorizer is as follows:
console.log('Loading function');
exports.handler = (event, context, callback) => {
var token = event.authorizationToken;
// Call oauth provider, crack jwt token, etc.
// In this example, the token is treated as the status for simplicity.
switch (token.toLowerCase()) {
case 'allow':
callback(null, generatePolicy('user', 'Allow', event.methodArn));
break;
case 'deny':
callback(null, generatePolicy('user', 'Deny', event.methodArn));
break;
case 'unauthorized':
callback("Unauthorized"); // Return a 401 Unauthorized response
break;
default:
callback("Error: Invalid token");
}
};
var generatePolicy = function(principalId, effect, resource) {
var authResponse = {};
authResponse.principalId = principalId;
if (effect && resource) {
var policyDocument = {};
policyDocument.Version = '2012-10-17'; // default version
policyDocument.Statement = [];
var statementOne = {};
statementOne.Action = 'execute-api:Invoke'; // default action
statementOne.Effect = effect;
statementOne.Resource = resource;
policyDocument.Statement[0] = statementOne;
authResponse.policyDocument = policyDocument;
}
// Can optionally return a context object of your choosing.
authResponse.context = {};
authResponse.context.stringKey = "stringval";
authResponse.context.numberKey = 123;
authResponse.context.booleanKey = true;
return authResponse;
as you can see it is just a simple mock up example provided in aws website.
Then I configured my get method in API gateway using this authorizer. Also in method execution I added a custom hedear called authorizationToken which will be used by authorizer.
When I use the postman everything is good:
However when I try to call it via ajax as follows I get the following error:
XMLHttpRequest cannot load https://590vv3bkda.execute-api.us-east-1.amazonaws.com/hamedstg/tjresource/story. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401.
Here is my ajax call:
$.ajax(
'https://590vv3bkda.execute-api.us-east-1.amazonaws.com/xxxxxxx',
{
method : 'GET',
headers : {
'authorizationToken' : 'allow'
},
beforeSend : function(xhr) {
xhr.setRequestHeader('authorizationToken', 'allow');
}
}).then(function(data) {
console.log(data);
});
Also it is noteworthy that I enabled CORS on the api in aws.
Can anyone help?
Did you add any methods or resources since enabling CORS? If so, then run the CORS wizard again and redeploy to your stage.
Also, make sure that the OPTIONS method on your resource does not require/use the customer authorizer. OPTIONS needs to be open to all as the browser will call it on your behalf for pre-flight CORS checks in some cases.
There is also a known issue that when an API Gateway call fails for any reason, the CORS headers are not set and thus you'll get that "No 'Access-Control-Allow-Origin' header is present" error, when the root cause is something entirely different. Try turning on developer logging on your browser, get the exact request sent to the API (it may be an OPTIONS method) and try the same request as a test invoke from the API Gateway console. That will let you look at the output and the logs to determine if there is another issue.

Ionic 2 ASP APi token request

I'm Trying to retrieve a bearer token from my ASP API from my ionic2 app.
I have enabled CORS on the API as shown below:
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
This enabled me to form a POST request from my ionic 2 app to my API in order to register a user. This works wonderfully.
The request I used for this is as shown below:
let headers = new Headers({
'Content-Type': 'application/json'
});
let options = new RequestOptions({
headers: headers
});
let body = JSON.stringify({
Email: credentials.email,
Password: credentials.password,
ConfirmPassword: credentials.confirmPassword
});
return this.http.post('http://localhost:34417/api/Account/Register', body, options)
However when I try to retrieve a token from my API I receive the following error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access.
The request I'm using to try and retrieve the token is as follows:
let body = "grant_type=password" + "&userName=" + credentials.email + "&password=" + credentials.password;
let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' });
let options = new RequestOptions({ headers: headers });
return this.http.post('http://localhost:34417/token', body, options)
This is the only request that is throwing this error, all other requests to my API work fine.
Have I missed anything, or am I doing something wrong?
var cors = new EnableCorsAttribute("*", "*", "*");
Looks like you are setting Access-Control-Allow-Origin as *.
Check MDN CORS Requests with credentials.
Credentialed requests and wildcards
When responding to a credentialed request, the server must specify an
origin in the value of the Access-Control-Allow-Origin header, instead
of specifying the "*" wildcard.
You will have to set a specific url if you use credentials.
Or if you only intend to use only for ionic 2, you could avoid the cors issue by setting a proxy.
According to the official blog:
The proxies settings contain two things: the path you use to access them on your local Ionic server, and the proxyUrl you’d ultimately like to reach from the API call.
{
"name": "ionic-2-app",
"app_id": "my_id",
"proxies": [
{
"path": "/api",
"proxyUrl": "http://localhost:34417/api"
}
]
}
Ionic serve command by default will start server on localhost:8100.
The set proxy will hit your http://localhost:34417/api.
Your path in the requests will be to the localhost:8100/api instead of your actual server.

Cross domain put call does not work with Access-Control-Allow-Origin

I am facing problem related to cross domain PUT call , i have allowed Access-Control-Allow-Origin from server side put still it doesn't work.
#PUT
#Path("/getresponse/{caller}")
#Produces({MediaType.APPLICATION_JSON})
public Response getResponseData(#PathParam("caller") String caller ,#QueryParam("ticket")String ticket ,#FormParam("formParam") String data){
ResponseBuilder resp;
System.out.println("name of caller is -> "+ caller);
System.out.println("query param ticket -> "+ ticket);
System.out.println("form param data->" + data);
Employee emp = new Employee();
emp.setAge(23);
emp.setName("data");
Gson gson = new Gson();
String responseJson = gson.toJson(emp);
resp=Response.ok(responseJson);//header("Access-Control-Allow-Origin", "*")
resp.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");
return resp.build();
}
whenever i call it from jquery ajax method it says
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource
I have same replica of above service but with POST signature when i call that service it calls service without any problem
Post service code is
#POST
#Path("/getresponses/{caller}")
#Produces({MediaType.APPLICATION_JSON})
public Response getResponseData1(#PathParam("caller") String caller ,#QueryParam("ticket")String ticket ,#FormParam("formParam") String data){
ResponseBuilder resp;
System.out.println("name of caller is -> "+ caller);
System.out.println("query param ticket -> "+ ticket);
System.out.println("form param data->" + data);
Employee emp = new Employee();
emp.setAge(23);
emp.setName("data");
Gson gson = new Gson();
String responseJson = gson.toJson(emp);
resp=Response.ok(responseJson);//header("Access-Control-Allow-Origin", "*")
resp.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST");
return resp.build();
}
My client side code is
$(document).ready(function(){
// for post service
$('#sendcall').on('click',function(e){
var dataTosend ="formParam=data to send";
$.ajax({
url: 'http://someip:8099/Jqgrid/rest/getdata/getresponses/data?ticket=tick',
contentType : 'application/x-www-form-urlencoded',
data :dataTosend,
type: 'POST',
success: function(data){
alert(data);
}
});
});
//for PUT service
$('#sendcall2').on('click',function(e){
var datatosend ="formParam=data to send";
$.ajax({
url: 'http://someip:8099/Jqgrid/rest/getdata/getresponse/aliahsan?ticket=tick',
contentType : 'application/x-www-form-urlencoded',
data :datatosend,
type: 'PUT',
crossDomain:true,
beforeSend: function (xhr) {
console.log('header added');
},
success: function(data){
alert(data);
}
});
});
});
Please help me in this regard why PUT is not working with this.
Any help will be greatly appreciated
Instead of adding all the CORS headers inside your resource method, use a Jersey filter, as described in this post. The reason for this, is the CORS preflight request, which is defined in HTTP access control (CORS) as:
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send.
So the request is an OPTIONS request and it expects back the the "Accept-Xxx" CORS headers to determine what is allowed by the server. So putting the headers in the resource method has no affect as the the request is made with the OPTIONS HTTP method, which you don't have a resource method for. This generally leads to a 405 Method Not Allowed error sent to the client.
When you add the headers in the filter, every request goes through this filter, even the OPTIONS request, so the preflight gets the according headers.
As for the PUT, also described in the above linked document (continuing from the above quote)
Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
This is why the POST request doesn't face the same problem.

Figuring out who has authenticated with basicAuth on Node while processing a POST request

I am using basicAuth to authenticate POSTs on a specific address.
On the client side I am using a command of the form:
$.ajax({
type: "POST",
accepts: "text/plain",
url: "http://localhost:3000/somewhere",
data: JSON.stringify(something),
contentType: "application/json; charset=UTF-8",
dataType: "json",
success: function(data) {
window.alert("Received back: '" + data + "'");
},
username: theUsername,
password: "a password"
});
This is working fine, in the sense that the username stored in theUsername passes the authentication mechanism that I have on node. While the user is authenticated I can print a console.log statement and see who has actually authenticated (I am not validating the password at the moment). But then the actual processing starts for the POST request. However, at that point how can I figure out the username and the password used in the original request? I tried to look on the headers of the request but I don't see anything there.
When you receive a Basic authentication request you should be able to read the "authorization" header in req.headers.authorization You have to pull out the the base64 encoded credentials and then decode them. Presumably, in Express you use req.header("authorization") or req.get("authorization")
For a standalone example, take a look at https://gist.github.com/charlesdaniel/1686663 which I have copied underneath for future reference
var http = require('http');
var server = http.createServer(function(req, res) {
// console.log(req); // debug dump the request
// If they pass in a basic auth credential it'll be in a header called "Authorization" (note NodeJS lowercases the names of headers in its request object)
var auth = req.headers['authorization']; // auth is in base64(username:password) so we need to decode the base64
console.log("Authorization Header is: ", auth);
if(!auth) { // No Authorization header was passed in so it's the first time the browser hit us
// Sending a 401 will require authentication, we need to send the 'WWW-Authenticate' to tell them the sort of authentication to use
// Basic auth is quite literally the easiest and least secure, it simply gives back base64( username + ":" + password ) from the browser
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"');
res.end('<html><body>Need some creds son</body></html>');
}
else if(auth) { // The Authorization was passed in so now we validate it
var tmp = auth.split(' '); // Split on a space, the original auth looks like "Basic Y2hhcmxlczoxMjM0NQ==" and we need the 2nd part
var buf = new Buffer(tmp[1], 'base64'); // create a buffer and tell it the data coming in is base64
var plain_auth = buf.toString(); // read it back out as a string
console.log("Decoded Authorization ", plain_auth);
// At this point plain_auth = "username:password"
var creds = plain_auth.split(':'); // split on a ':'
var username = creds[0];
var password = creds[1];
if((username == 'hack') && (password == 'thegibson')) { // Is the username/password correct?
res.statusCode = 200; // OK
res.end('<html><body>Congratulations you just hax0rd teh Gibson!</body></html>');
}
else {
res.statusCode = 401; // Force them to retry authentication
res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"');
// res.statusCode = 403; // or alternatively just reject them altogether with a 403 Forbidden
res.end('<html><body>You shall not pass</body></html>');
}
}
});
server.listen(5000, function() { console.log("Server Listening on http://localhost:5000/"); });

Resources