"ETIMEDOUT connection failed" on nodeJs server after creating new token - javascript

The error appeared after generating a new token with an additional scope. May occur with any request to googleapis.com.
I repeatedly generated new tokens with different scopes, but this did not affect anything.
I tried to make requests via POSTMAN when an error occurred, but the requests always succeeded
What could be causing this behaviour?
My connection method:
connect(config) {
const keepaliveAgent = new Agent.HttpsAgent();
instance.defaults = {
maxRedirects: 120,
agent: keepaliveAgent,
retryConfig: {
retry: 5,
httpMethodsToRetry: ['GET', 'PUT', 'HEAD', 'OPTIONS', 'DELETE', 'POST'],
statusCodesToRetry: [[500, 509, 503, 504, 529, 598, 599]],
shouldRetry: (err) => {
console.log('err', err);
if (err.message.includes('ETIMEDOUT') || err.message.includes('Socket timeout')) return true;
else return false;
},
},
};
return new Promise(async (resolve, reject) => {
if (!config || Object.keys(config).length === 0) {
return reject(new Error('Google Docs settings not found'));
}
this.auth = new google.auth.OAuth2(config.client, config.secret, config.redirect);
const exists = await fw.exists(TOKEN_PATH);
if (exists) {
const token = await fw.read(TOKEN_PATH);
this.auth.setCredentials(JSON.parse(token));
} else {
const token = await this.__generateToken(this.auth);
this.auth.setCredentials(token);
}
this.drive = google.drive({
version: 'v3',
auth: this.auth,
});
this.data = google.docs({
version: 'v1',
auth: this.auth,
});
this.script = google.script({
version: 'v1',
auth: this.auth,
});
resolve();
});
}
I should also note that I am using retryConfig, but this is not the main solution I am looking for.
I tried using the agentkeepalive library. expecting this to reduce the chance of an error occurring. Experimented with the config but all I got was a slightly faster response.

Related

How to mock jsonwebtoken + jwsks-rsa for custom lambda Authroizer

I am using lambda custom authoriser in front of api endpoint.
so whenever a request comes on that endpoint api gateway calls authoriser to validate jwt token and based on validation it generates a policy.
Also jwt tokens are generated by auth0 api, i know there is a library https://www.npmjs.com/package/mock-jwks which mocks auth0 jwt token but it a http request to endpoint which is not possible in my case
the code is pretty self explanatory howver i stuck with mocking jsonwebtoken and jwks-rsa library? what could be the ideal way to test such kind of function?
my authorizer.js
require('dotenv').config();
const jwks = require('jwks-rsa');
const jwt = require('jsonwebtoken');
const createPolicyDocument = (effect) => {
const policy = {
Version: '2012-10-17',
Statement: [
{
Effect: effect,
Action: 'execute-api:Invoke',
Resource:
'xxxxxxxxxxxxxxxxx',
},
],
};
return policy;
};
// Extract the Bearer token from the event sent by lambda and return it to the authorizer
const extractToken = (event) => {
const tokenWithBearer = event.authorizationToken;
if (!tokenWithBearer) {
throw new Error(' "event.authorization" paramters is missing');
}
const bearer = tokenWithBearer.split(' ');
if (!bearer) {
throw new Error('Invalid token');
}
return bearer[1];
};
const jwtVerifyOptions = {
audience: process.env.AUDIENCE,
issuer: process.env.TOKEN_ISSUER,
};
const client = jwks({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 10,
jwksUri: process.env.JWKS_URI,
});
function verifyToken(token) {
return new Promise((resolve, reject) => {
const tempDecodedToken = jwt.decode(token, { complete: true });
console.log(token);
console.log(tempDecodedToken);
const { kid } = tempDecodedToken.header;
client.getSigningKey(kid, (err, key) => {
if (err) {
console.log('signinin key get error', err);
reject('Deny');
}
const signingKey = key.publicKey || key.rsaPublicKey;
console.log(signingKey);
jwt.verify(token, signingKey, jwtVerifyOptions, (error, decoded) => {
if (error) {
console.log('jwt verify error', error);
reject('Deny');
}
console.log(decoded);
resolve({ response: 'Allow', decoded });
});
});
});
}
module.exports.auth = async (event, context, callback) => {
try {
const token = extractToken(event);
const tokenResponse = await verifyToken(token);
console.log(tokenResponse);
if (tokenResponse.response === 'Allow') {
return {
principalId: tokenResponse.decoded.sub,
policyDocument: createPolicyDocument('Allow'),
context: { scope: tokenResponse.decoded.scope },
};
}
return {
policyDocument: createPolicyDocument('Deny'),
};
} catch (err) {
return {
policyDocument: createPolicyDocument('Deny'),
};
}
};

Azure function doesn't return response after async function is complete

I'm trying to develop a function in VS Code that takes an url as input and returns the response after processing is complete. However, when this function is run, it returns nothing. I tried testing similar code in Webstorm and and confirm that it console.logs the results just fine. I'm new to node and promises so not sure what I'm doing wrong.
Edit - added return keyword before driver.get as per the suggestion from #hellikiam. Also added a simple log statement to confirm that the results available yet not being returned in body.
var AxeBuilder = require('#axe-core/webdriverjs'),
WebDriver = require('selenium-webdriver');
const chromedriver = require('chromedriver');
const chrome = require("selenium-webdriver/chrome");
const screen = {
width: 640,
height: 480
};
chrome.setDefaultService(new chrome.ServiceBuilder(chromedriver.path).build());
var driver = new WebDriver.Builder()
.forBrowser('chrome')
.setChromeOptions(new chrome.Options().headless().windowSize(screen))
.build();
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
const url = (req.query.url || (req.body && req.body.url));
return driver.get(url).then(function () {
new AxeBuilder(driver).analyze(function (err, results) {
resultsJson = JSON.stringify(results);
console.log(resultsJson)
context.res = {
status: 200, /* Defaults to 200 */
body: resultsJson,
headers: {
'Content-Type': 'application/json'
}
};
if (err) {
// Handle error somehow
}
});
});
context.done();
}
you didn't returned anything from exported module.
return driver.get(url).then(function () {//add return statement in here.
new AxeBuilder(driver).analyze(function (err, results) {
resultsJson = JSON.stringify(results);
context.res = {
status: 200, /* Defaults to 200 */
body: resultsJson,
headers: {
'Content-Type': 'application/json'
}
};
if (err) {
// Handle error somehow
}
});
});
I found the other problem. What you want to return is inside callback function.
You should wrap the callback with promise to get the result outside of the callback. Try this out brother.
return new Promise((resolve, reject) =>{
driver.get(url).then(function () {//add return statement in here.
new AxeBuilder(driver).analyze(function (err, results) {
resultsJson = JSON.stringify(results);
context.res = {
status: 200, /* Defaults to 200 */
body: resultsJson,
headers: {
'Content-Type': 'application/json'
}
};
resolve(resultsJson)//Any value you want to return
if (err) reject(err)
});
});
})
Calling this function outside of module with await statement
const foo = require('./my/path/foo')
(async()=>{
const params = 'my param'
const bar = await foo(params)
console.log(bar)
})()

DyanmoDB getItem not providing any response within Async Lambda

I have been trying to make a getItem request in an async Lambda function to dynamo DB, and I am not receiving any response at all. Any troubleshooting or help would be greatly appreciated.
in general, I am trying to make a request to a dynamodb table using the AWS SDK getItem, however, when I run my code there is no response for the await ddb.getItem function
so I am kinda lost as to what could be causing this.
// Load AWS SDK
const AWS = require("aws-sdk");
// Set the region
AWS.config.update({ region: "us-east-1" });
// Create the DyanmoDB service object
const ddb = new AWS.DynamoDB({ apiVersion: "2012-08-10" });
const handler = async (
event,
context,
callback,
test = false,
testObjFunc = {
test: () => {
Error("Testing enabled");
}
}
) => {
const response = {
isBase64Encoded: false,
statusCode: 200,
headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*" },
multiValueHeaders: {},
body: JSON.stringify({ responseBody })
};
try {
// Parameters for DynamodDB getItem call
const dbParams = {
TableName: "Table_Name",
Key: {
personID: { S: "value" }
},
ProjectionExpression: "value_to_return"
};
// DynamoDB call to check for item
const results = await ddb.getItem(dbParams).promise();
console.log("success");
console.log(results);
} catch (error) {
response.statusCode = 500;
}
return response;
};
module.exports.handler = handler;
You have put the getitem call in try block, as you are not receiving any response means something is gone wrong in the try block.

Trying to sign a jwt returns undefined

I'm learning node and I'm migrating my current API from python. I'm trying to create a jwt token to authenticate in a third party API, however my function returns undefined. The jwt method I'm using to sign the token is async, so I guess my function doesn't wait until jwt returns the token.
This is my function to sign and create the jwt token:
function token() {
const payload = {
iat: Math.floor(new Date() / 1000),
exp: Math.floor(new Date() / 1000) + 30,
sub: "api_key_jwt",
iss: "external",
jti: crypto.randomBytes(6).toString("hex")
};
return jwt.sign(payload, privatekey, { algorithm: "RS256" }, function(
err,
token2
) {
return token2;
});
}
So, when I call it:
exports.genToken = function() {
const header = {
"x-api-key": api
};
const data = {
kid: api,
jwt_token: token()
};
async function authorization(req, res) {
try {
const auth = await rp({
url: authurl,
method: "POST",
headers: header,
body: data
});
res.send(auth.body);
} catch (error) {
res.send(404).send();
}
}
return {
"x-api-key": api,
Authorization: "Bearer " + authorization()
};
};
jwt_token returns undefined. What am I doing wrong, and how can I fix it?
Thanks in advance guys!
Edit: console.log(token2) returns the signed token. So the problem is returning the token from the token() function
You're trying to return from a callback which doesn't work. Change your token function to return Promise then you can use the async/await like:
function token() {
...
return new Promise((resolve, reject) => {
jwt.sign(payload, privatekey, { algorithm: "RS256" }, function(err, token2) {
if (err) reject(err);
else resolve(token2)
});
})
}
// note async
exports.genToken = async function() {
...
const data = {
kid: api,
jwt_token: await token()
};
...
}

ES6 node async/await unexpected identifier

I have the following code that worked when running against babel. Now that I'm using harmony I get the following error:
let adResult = await ad.isUserValid(domainPath, password);
^^
SyntaxError: Unexpected identifier
The following class function:
class ActiveDirectoryHelper {
constructor(options) {
this.config = options.config
this.ad = null;
}
connect() {
var config = {
url: this.config.url,
baseDN: this.config.baseDN,
attributes: this.config.attributes
};
if (this.config.account.user.length > 0) {
config.username = this.config.account.user;
config.password = this.config.account.password;
}
this.ad = new ActiveDirectory(config);
}
async isUserValid(user, password) {
return new Promise((resolve, reject) => {
this.ad.authenticate(user, password, (err, auth) => {
if (err) {
reject({
code: 500,
message: "Unknown authentication error",
entry: {}
});
}
if (auth) {
resolve({
code: 200,
message: "OK",
entry: {
user: user,
password: password
}
});
} else {
reject({
code: 400,
message: "Authentication failed",
entry: {}
});
}
});
});
}
...
exports.ActiveDirectoryHelper = ActiveDirectoryHelper;
I use the class as follows:
const ad = new ActiveDirectoryHelper({
config: adConfig
});
ad.connect();
const domainPath = domain.length > 0 ? `${domain}\\${user}` : user;
const adResult = await ad.isUserValid(domainPath, password);
I run the code using the following parameters:
node --harmony --use_strict --harmony-async-await user.js <my parameters>
If I take the await when calling the method:
const adResult = ad.isUserValid(domainPath, password);
then I don't have the error but it also doesnt wait till the method finishes.
I've googled the error and it seems like your only able to use await within a function that async is in. But without await outside of the method call, it doesnt wait till its finished. Any ideas?
It is because you can't use await unless it's in an async function.
See this link for details:
'await Unexpected identifier' on Node.js 7.5

Categories

Resources