I'm trying to make script to generate my authentication bearer token for collections. so I don't have to pass token each time and I will Inherit auth from parent. But I don't know where I'm wrong in script, I'm not able to generate token and it giving me error
There was an error in evaluating the Pre-request Script: Error: No data, empty input at 1:1 ^
Here is my script,
var expiresOn = pm.variables.get('ExpiresOn');
if (!expiresOn || new Date(expiresOn) <= new Date()) {
var clientId = '565v7677676vfdrd';
var apiToken = '6565fdvdrdfd';
var request = {
url: 'http://.../auth/token',
method: 'POST',
header: 'Content-Type:application/Json',
body: {
mode: 'application/json',
raw: clientId + apiToken
}
};
}
};
pm.sendRequest(request, function (err, res) {
if (res !== null) {
var json = res.json();
pm.environment.set('Access_Token', json.access_token)
var expiresOn = new Date(0);
expiresOn.setUTCSeconds(json.expires_on);
pm.environment.set('ExpiresOn', expiresOn);
}
});
}
const echoPostRequest = {
url: 'https://example.com/sign_in?client_id=dbdsA8b6V6Lw7wzu1x0T4CLxt58yd4Bf',
method: 'POST',
header: 'Accept: application/json\nUser-Agent: Example/2019.10.31-release (Android 6.0.1; LGE Nexus 5)\nUDID: 1d2c7e65f34b3882f8e42ab8d6a82b4b\nContent-Type: application/json; charset=utf-8\nHost: api-mobile.example.com',
body: {
mode: 'application/json',
raw: JSON.stringify(
{
client_id:'dbdsA8b6V6Lw7wzu1x0T4CLxt58yd4Bf',
client_secret:'aBK1xbehZvrBw0dtVYNY3BuJJOuDFrYs',
auth_method:'password',
create_if_not_found:false,
credentials:{identifier:'username',password:'pass'},
signature:'2:a899cdc0'
})
}
};
var getToken = true;
if (!pm.environment.get('accessTokenExpiry') ||
!pm.environment.get('currentAccessToken')) {
console.log('Token or expiry date are missing')
} else if (pm.environment.get('accessTokenExpiry') <= (new Date()).getTime()) {
console.log('Token is expired')
} else {
getToken = false;
console.log('Token and expiry date are all good');
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function (err, res) {
console.log(err ? err : res.json());
if (err === null) {
console.log('Saving the token and expiry date')
var responseJson = res.json();
pm.environment.set('currentAccessToken', responseJson.access_token)
var expiryDate = new Date();
expiryDate.setSeconds(expiryDate.getSeconds() + responseJson.expires_in);
pm.environment.set('accessTokenExpiry', expiryDate.getTime());
}
});
}
The above example is a Postman Pre-request script to fetch access_token, and the expire time of the token. I think this example will help you to solve the issue.
Please check the console of the postman
Open Postman Console by pressing Ctrl+Alt+C on Windows (Cmd + Alt+ C on mac)
Syntax error
When running your script I got the following error:
There was an error in evaluating the Pre-request Script: SyntaxError: Unexpected token ';'
It should be something like this in order to run correctly:
var expiresOn = pm.variables.get('ExpiresOn');
if (!expiresOn || new Date(expiresOn) <= new Date()) {
var clientId = '565v7677676vfdrd';
var apiToken = '6565fdvdrdfd';
var request = {
url: 'https://api.domain.io/api/user/session',
method: 'POST',
header: 'Content-Type:application/Json',
body: {
mode: 'application/json',
raw: clientId + apiToken
}
};
}
pm.sendRequest(request, function (err, res) {
if (res !== null) {
var json = res.json();
pm.environment.set('Access_Token', json.access_token)
var expiresOn = new Date(0);
expiresOn.setUTCSeconds(json.expires_on);
pm.environment.set('ExpiresOn', expiresOn);
}
});
Additional options
I used one of these two options to get the bearer token for my collection:
https://gist.github.com/bcnzer/073f0fc0b959928b0ca2b173230c0669#file-postman-pre-request-js
https://community.postman.com/t/how-to-automatically-set-a-bearer-token-for-your-postman-requests/10126/2
A bit modified Sebin Sunny's answer tested with JWT against Azure + resource (/audience).
In headers of request use Authorization {{$randomLoremSentence}}
const echoPostRequest = {
url: 'https://login.microsoftonline.com/{tenant}/oauth2/token',
method: 'POST',
body: {
mode: 'formdata',
formdata: [
{ key: 'grant_type', value: 'client_credentials' },
{ key: 'client_Id', value: '*******************************' },
{ key: 'client_secret', value: '*******************************' },
{ key: 'resource', value: '*******************************' }
]
}
};
var getToken = true;
var token = pm.globals.get('$randomLoremSentence') || '';
var exp = pm.globals.get('accessTokenExpiry');
var exps = new Date(exp);
if (token.indexOf('Bearer ') < 0) {
console.log('Token or expiry date are missing')
} else if (exp <= (new Date()).getTime()) {
console.log('Token is expired - ${exps}')
} else {
getToken = false;
console.log(`Token ${token.substr(0,10)}...${token.substr(-5)} and expiry ${exps} date are all good`);
}
if (getToken === true) {
pm.sendRequest(echoPostRequest, function (err, res) {
console.log(err ? err : res.json());
if (err === null) {
var responseJson = res.json();
var token = responseJson.access_token;
console.log(`Saving the token ${token.substr(0,5)}...${token.substr(-5)} and expiry ${exps} date`)
pm.globals.set('$randomLoremSentence', "Bearer " + token);
var expiryDate = new Date(responseJson.expires_on * 1000);
pm.globals.set('accessTokenExpiry', expiryDate.getTime());
}
});
}
//pm.globals.set('$randomLoremSentence', 0); // reset token 2 test
Related
I am trying to grab a token and pass it into the GET requests.
The below works, but it's grabbing a token every single time a request runs. Ideally I want to grab it once per run and pass it to the requests.
Any ideas on how to make that happen from the below code?
import http from "k6/http";
import { sleep } from "k6";
import { check } from "k6";
import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
export let options = {
insecureSkipTLSVerify: true,
noConnectionReuse: false,
vus: 5,
duration: "10s",
};
var client_id = "clientId123";
var secret = "secret123";
var scope = "scope123";
export default () => {
var body =
"grant_type=client_credentials&client_id=" +
client_id +
"&client_secret=" +
secret +
"&scope=" +
scope;
var tokenResponse = http.post( "https://login.microsoftonline.com/tenantID123/oauth2/v2.0/token", body, { headers: { ContentType: "application/x-www-form-urlencoded"}});
var result = JSON.parse(tokenResponse.body);
var token = result.access_token;
check(tokenResponse, {
'is status 200': (r) => r.status === 200
})
var resp1 = http.get("url_1", {
headers: { Authorization: `Bearer ${token}` },
});
var resp2 = http.get("url_2", {
headers: { Authorization: `Bearer ${token}` },
});
check(resp1, {
'is status 200': (r) => r.status === 200,
})
check(resp2, {
'is status 200': (r) => r.status === 200,
})
};
In k6 lifecycle there are 4 stages. You need to use the proper one for your need.
Get exactly one token for the whole test
Can use setup function
export function setup(){
var client_id = "clientId123";
var secret = "secret123";
var scope = "scope123";
var body =
"grant_type=client_credentials&client_id=" +
client_id +
"&client_secret=" +
secret +
"&scope=" +
scope;
var tokenResponse = http.post(
"https://login.microsoftonline.com/tenantID123/oauth2/v2.0/token",
body,
{ headers: { ContentType: "application/x-www-form-urlencoded" } }
);
var result = JSON.parse(tokenResponse.body);
var token = result.access_token;
return {token}
}
export default (data) => {
var token = data.token;
// Rest ...
}
Get one token for every VU (Virtual User)
Can use "init code."
// ...
var body =
"grant_type=client_credentials&client_id=" +
client_id +
"&client_secret=" +
secret +
"&scope=" +
scope;
var tokenResponse = http.post(
"https://login.microsoftonline.com/tenantID123/oauth2/v2.0/token",
body,
{ headers: { ContentType: "application/x-www-form-urlencoded" } }
);
var result = JSON.parse(tokenResponse.body);
var token = result.access_token;
export default () => {
var resp1 = http.get("url_1", {
headers: { Authorization: `Bearer ${token}` },
});
// ...
};
I have some code that's supposed to generate a new token if certain conditions are met.
In IE the token generator returns a 200 (and console logs the token) but in Chrome and Firefox I'm getting 401 errors (console logging the token shows null).
I've been looking up reasons as to why this is, but for some reason most of the SO posts I've come across have issues with IE and tokens and not Chrome.
permissionToCallAPI = new Promise(function(resolve, reject) {
function sessionGet(key) {
let stringValue = window.sessionStorage.getItem(key);
if (stringValue !== null) {
try {
const { value, expirationDateStr } = JSON.parse(stringValue);
if (value && expirationDateStr) {
let expirationDate = new Date(value.expirationDateStr);
if (expirationDate > new Date()) {
return value;
}
isAuthorized(value)
.then(resp => {
console.log("Valid Token");
return value;
})
.catch(err => {
throw "Failed Authentication.";
});
}
} catch (e) {
console.log(e);
window.sessionStorage.removeItem(key);
return null;
}
}
return null;
} // sessionGet()
// add into session
function sessionSet(key, value, expirationInMin) {
if (!expirationInMin) {
expirationInMin = 59;
}
var expirationDate = new Date(
new Date().getTime() + 60000 * expirationInMin
);
var newValue = {
value: value,
expirationDate: expirationDate.toISOString()
};
window.sessionStorage.setItem(key, JSON.stringify(newValue));
}
let _token = sessionGet("tokenSet");
console.log(_token); // null in Chr (not IE)
if (_token == null) {
$.ajax({
url: _RestHost + "/User/GenerateToken",
method: "GET", // using POST gets an error
cache: false,
withCredentials: true,
headers: {
"Content-Type": "application/json",
"X-Requested-With": "XMLHttpRequest",
"Authorization": _token
},
success: function(data) {
sessionSet("tokenSet", data.AuthToken);
resolve(data.AuthToken);
},
error: function(err) {
reject(err);
}
});
} else {
resolve(_token);
}
});
I'm writing a node.js script to generate a GitHub installation access token. Here's what I've got:
const axios = require("axios");
var fs = require('fs');
var jwt = require("jsonwebtoken");
var gitInstallationAccessToken = {
genJWTToken: function(callback) {
var private_key = fs.readFileSync("/path/to/my/pemfile.pem");
const now = Math.round(Date.now() / 1000);
const payload = {
iat : now,
exp : now + (10 * 60),
iss : 7233
};
const token = jwt.sign(payload, private_key, { algorithm: 'RS256' })
callback(token);
},
genInstallationAccessToken: function(token, callback) {
var jwt = gitInstallationAccessToken.genJWTToken(function(token) {
return token;
});
console.log("JWT: ", jwt)
var instance = axios({
method: "post",
url: "https://api.github.com/installations/:installation_id/access_tokens",
headers: {
"Accept" : "application/vnd.github.machine-man-preview+json",
"Authorization" : `Bearer ${jwt}`
}
})
.then(function(response) {
console.log("Response: ",response.data);
callback(response);
})
.catch(function(error) {
console.warn("Unable to authenticate");
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
if (error.response) {
console.warn(`Status ${error.response.status}`);
console.warn(`${error.response.data.message}`);
}
});
}
}
module.exports = gitInstallationAccessToken;
gitInstallationAccessToken.genInstallationAccessToken(function(response) {
console.log("response: ", response)
});
My JWT token is getting generated by genJWTToken. I can see that if I add a console.log("Token: ", token) before the callback in genJWTToken.
I now need to use that token in genInstallationAccessToken but I'm clearly calling it wrong. As the following returns undefined:
var jwt = gitInstallationAccessToken.genJWTToken(function(token) {
return token;
});
console.log("JWT: ", jwt)
How do I fix this?
I think you should consider refactoring this and use chained promises it will be easier to understand and control..
Something like this:
function getToken() {
return new Promise(function(resolve, reject) {
resolve('token')
})
}
function chainPromise() {
var token
getToken().then((response) => {
token = response
console.log(token)
}).then(() => {
console.log('I am here and also see: ', token)
})
}
chainPromise()
You should then be able to track down the path of your token quite easily
I'm following these tutorial:
https://developer.wordpress.com/docs/oauth2/
https://developer.wordpress.com/docs/wpcc/
https://github.com/Automattic/wpcom-connect-examples/blob/master/express.js/app.js
So I setup Meteor.loginWithWordpresscom with the following code:
Accounts.oauth.registerService('wordpresscom');
if (Meteor.isClient) {
Meteor.loginWithWordpresscom = function(options, callback) {
// support a callback without options
if (! callback && typeof options === "function") {
callback = options;
options = null;
}
var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);
Wordpresscom.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
Accounts.addAutopublishFields({
forLoggedInUser: ['services.wordpresscom'],
forOtherUsers: ['services.wordpresscom.username']
});
}
And then I request credential with the following code:
Wordpresscom = {};
Wordpresscom.requestCredential = function (options, credentialRequestCompleteCallback) {
if (!credentialRequestCompleteCallback && typeof options === 'function') {
credentialRequestCompleteCallback = options;
options = {};
}
var config = ServiceConfiguration.configurations.findOne({service: 'wordpresscom'});
if (!config) {
credentialRequestCompleteCallback && credentialRequestCompleteCallback(
new ServiceConfiguration.ConfigError());
return;
}
var credentialToken = Random.secret();
var loginStyle = OAuth._loginStyle('wordpresscom', config, options);
var loginUrl =
'https://public-api.wordpress.com/oauth2/authorize' +
'?client_id=' + config.clientId +
'&redirect_uri=http://localhost:3000/connected' +
'&response_type=token' +
'&grant_type=authorization_code' +
'&scope=global'
OAuth.launchLogin({
loginService: "wordpresscom",
loginStyle: loginStyle,
loginUrl: loginUrl,
credentialRequestCompleteCallback: credentialRequestCompleteCallback,
credentialToken: credentialToken,
popupOptions: {width: 900, height: 450}
});
};
At the server, I request accessToken and identity with following code:
Wordpresscom = {};
OAuth.registerService('wordpresscom', 2, null, function(query) {
var accessToken = getAccessToken(query);
var identity = getIdentity(accessToken);
return {
serviceData: {
id: identity.ID,
accessToken: OAuth.sealSecret(accessToken),
email: identity.email,
username: identity.username,
displayName: identity.display_name,
avatar: identity.avatar_URL
},
options: {profile: {
name: identity.display_name,
displayName: identity.display_name,
avatar: identity.avatar_URL
}}
};
});
var getAccessToken = function (query) {
var config = ServiceConfiguration.configurations.findOne({service: 'wordpresscom'});
if (!config)
throw new ServiceConfiguration.ConfigError();
var response;
try {
response = HTTP.post(
"https://public-api.wordpress.com/oauth2/token", {
params: {
code: query.code,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: 'http://localhost:3000/connected',
grant_type: 'authorization_code'
}
});
} catch (err) {
throw _.extend(new Error("Failed to complete OAuth handshake with WordPress.com. " + err.message),
{response: err.response});
}
if (response.data.error) { // if the http response was a json object with an error attribute
throw new Error("Failed to complete OAuth handshake with WordPress.com. " + response.data.error);
} else {
console.log('getAccessToken');
return response.data.access_token;
}
};
var getIdentity = function (accessToken) {
console.log('getIdentity');
try {
return HTTP.get(
"https://public-api.wordpress.com/rest/v1/me", {
headers: {
/*"User-Agent": userAgent,*/
"Authorization": 'Bearer ' + accessToken
},
params: {access_token: accessToken}
}).data;
} catch (err) {
throw _.extend(new Error("Failed to fetch identity from WordPress.com. " + err.message),
{response: err.response});
}
};
Wordpresscom.retrieveCredential = function(credentialToken, credentialSecret) {
return OAuth.retrieveCredential(credentialToken, credentialSecret);
};
When I fire Meteor.loginWithWordpresscom popup window show up to ask user whether to approve or deny my app with this link http://localhost:3000/connected?code=a8kiRGwRPC
I get code a8kiRGwRPC to request access_token
After I approve, it redirect to http://localhost:3000/connected#access_token=w%5EQ7CFcvZQx3t%28OjspIs84v13BsbyUGROzrYh3%23aiLJQ%25NB%2AZ7jMjNX2%29m7%23t5J4&expires_in=1209600&token_type=bearer&site_id=0
Just like that. No new user stored in Meteor.users database
Any help would be appreciated
Thanks
I am using a Node JS server and trying to get an access token from Adwords API. To perform the POST request i use curler from npm(https://www.npmjs.org/package/curler). Here is the code sample:
var login = 'mymail#gmail.com';
var pass = 'mypassword';
var data = JSON.stringify({
Email: login,
Passwd : pass,
accountType: 'GOOGLE',
service: 'adwords',
source: 'adwordstest'
});
var options = {
method: "POST",
url: 'https://www.google.com/accounts/ClientLogin',
headers: {
'Content-Type': 'application/json'
},
data: data,
timeout: 5000,
connectionTimeout: 5000
};
var startDate = Date.now();
curl.request(options, function(err, res, bodyData) {
var duration = (Date.now() - startDate);
if (err) {
console.log(err);
}
else {
console.log('statusCode: %s', res.statusCode);
console.log('bodyData: %s', bodyData);
}
console.log("curler (libcurl) performed http request in %s ms. dnsTime: %s, connectTime: %s, preTransferTime: %s, startTransferTime: %s, totalTime: %s", duration, res.dnsTime, res.connectTime, res.preTransferTime, res.startTransferTime, res.totalTime);
});
The response I get is
statusCode: 403
bodyData: Error=BadAuthentication
which basicly says that login information is wrong, which is not. Can't figure out whether i've chosen the wrong implementation, or just missing a header or something.
Here is the code I use to get a fresh access token: https://github.com/ErikEvenson/googleads-node-lib/blob/v0.0.17/services/adWordsService.js#L206-L241. The access token ends up in credentials.access_token.
self.refresh = function(done) {
// check if current credentials haven't expired
if (self.credentials && Date.now() < self.credentials.expires) {
// behave like an async
setTimeout(function() {done(null);}, 0);
return;
} else {
// throw away cached client
self.client = null;
var qs = {
refresh_token: self.options.ADWORDS_REFRESH_TOKEN,
client_id: self.options.ADWORDS_CLIENT_ID,
client_secret: self.options.ADWORDS_SECRET,
grant_type: 'refresh_token'
};
request.post(
{
qs: qs,
url: self.tokenUrl
},
function(error, response, body) {
self.credentials = JSON.parse(body);
self.credentials.issued = Date.now();
self.credentials.expires = self.credentials.issued -
self.credentials.expires_in;
done(error);
}
);
return;
}
};