0

below code works fine when running locally, but "getAccessToken ()" does not work as expected when running inside an aws lambda function, when doing "POST" to /webhook endpoint. I am using node 8.10, "aws-serverless-express": "^3.3.6", "express": "^4.16.4" and "node-fetch": "^2.5.0", basically it print the correct jwt token but node-fetch does not return anything, sample log.

START RequestId: c8efba59-1869-4eaa-b9d8-aa15a7507d52 Version: $LATEST 2019-05-27T19:55:32.328Z c8efba59-1869-4eaa-b9d8-aa15a7507d52 start getExecution 2019-05-27T19:55:32.328Z c8efba59-1869-4eaa-b9d8-aa15a7507d52 exectution_url: 2019-05-27T19:55:32.328Z c8efba59-1869-4eaa-b9d8-aa15a7507d52 https://cloudmanager.adobe.io/somevalidurl 2019-05-27T19:55:32.328Z c8efba59-1869-4eaa-b9d8-aa15a7507d52 start getAccessToken END RequestId: c8efba59-1869-4eaa-b9d8-aa15a7507d52 REPORT RequestId: c8efba59-1869-4eaa-b9d8-aa15a7507d52 Duration: 6657.00 ms Billed Duration: 6700 ms Memory Size: 128 MB Max Memory Used: 37 MB

I made sure lambda timeout is 30 seconds, tried to disable "node-fetch" timeout by setting it to 0 and , used a middleware for all the routes "app.use(timeout("30000"))" also for that specific webhook request timeout. (I receive the 200 pong response immediately but getexectuion async function does not work properly)

const express = require('express')
const bodyParser = require('body-parser')
const crypto = require('crypto')
const jsrsasign = require('jsrsasign')
const fetch = require('node-fetch')
const timeout = require('connect-timeout')

const URL  = require('url').URL
const URLSearchParams = require('url').URLSearchParams



//require('dotenv').config()
const app = express()



async function getAccessToken () {
  console.log("start getAccessToken")
  const EXPIRATION = 60 * 60 // 1 hour

  const header = {
    'alg': 'RS256',
    'typ': 'JWT'
  }



  const payload = {
    'exp': Math.round(new Date().getTime() / 1000) + EXPIRATION,
    'iss': process.env.ORGANIZATION_ID,
    'sub': process.env.TECHNICAL_ACCOUNT_ID,
    'aud': `https://ims-na1.adobelogin.com/c/${process.env.API_KEY}`,
    'https://ims-na1.adobelogin.com/s/ent_cloudmgr_sdk': true
  }

  const jwtToken = jsrsasign.jws.JWS.sign('RS256', JSON.stringify(header), JSON.stringify(payload), process.env.PRIVATE_KEY)
  //console.log("jwt token:")
  //console.log(jwtToken)

  const body = new URLSearchParams({
      client_id: process.env.API_KEY,
      client_secret: process.env.CLIENT_SECRET,
      jwt_token: jwtToken
    })


   const response = await fetch('https://ims-na1.adobelogin.com/ims/exchange/jwt', {
    method: 'POST',
    options: { timeout: 0},
    timeout: 0,
    size: 0,
    body: body
  })//.catch(error => {
    //        console.log("an error happend in fetchg")
    //        console.log(error)
    //})


  const json = await response.json()

  if ((response.status !== 200) && (response.status !== 201)) {
      console.error(`Invalid response status ${ response.status }.`);
      throw json;
  }

  console.log("access_token:")
  console.log(json['access_token'])
  return json['access_token']
}

async function makeApiCall (accessToken, url, method) {
  console.log("start make api call")
  const response = await fetch(url, {
    'method': method,
    'headers': {
      'x-gw-ims-org-id': process.env.ORGANIZATION_ID,
      'x-api-key': process.env.API_KEY,
      'Authorization': `Bearer ${accessToken}`
    }
  })

  console.log("finish make api call")
  const json = await response.json()
  return json
}

function getLink (obj, linkType) {
  return obj['_links'][linkType].href
}

async function getExecution (executionUrl) {
  console.log("start getExecution")
  console.log("exectution_url:")
  console.log(executionUrl)
  const accessToken = await getAccessToken()
  console.log("access-token:")
  console.log(accessToken)
  const execution = await makeApiCall(accessToken, executionUrl, 'GET')
  console.log(execution)
  console.log("aaaa")
  const program = await makeApiCall(accessToken, new URL(getLink(execution, 'http://ns.adobe.com/adobecloud/rel/program'), executionUrl))
  console.log(execution)
  console.log("here")
  execution.program = program

  return execution
}


//app.use(bodyParser.json())

app.use(bodyParser.json({
  verify: (req, res, buf, encoding) => {
    const signature = req.header('x-adobe-signature')
    if (signature) {
      const hmac = crypto.createHmac('sha256', process.env.CLIENT_SECRET)
      hmac.update(buf)
      const digest = hmac.digest('base64')

      if (signature !== digest) {
        throw new Error('x-adobe-signature HMAC check failed')
      }
    } else if (!process.env.DEBUG && req.method === 'POST') {
      throw new Error('x-adobe-signature required')
    }
  }
}))

app.use(timeout("30000"))



app.post('/webhook', (req, res) => {

  req.setTimeout(120000, function(){
      console.log('Request has timed out.');
         res.send(408);
  });
  res.writeHead(200, { 'Content-Type': 'application/text' })
  res.end('pong')


    getExecution("https://cloudmanager.adobe.io/<somevalidurl>").then(execution => {
    console.log(`Execution for ${execution.program.name} started`)
    })




})



module.exports = app;

//const port = process.env.PORT || 3000

//app.listen(port, () =>
//  console.log(`App is listening on port ${port}.`)
//)

  • You are misunderstanding the concept of lambda architecture and are writing node based code for serverless. You also did not share the error message. I would suggest you to check the principles of serverless architecture. – Cleriston May 28 '19 at 03:42
  • I shared the log message, code does not simply execute after getAccessToken(), when executing curl post to /webhook endpoint. – Lina Sharifi May 28 '19 at 12:28
  • So you may be having issues of Async usage. I normally use Promise, so I can't help much, but I would track around this. – Cleriston May 28 '19 at 23:09
  • thanks @Cleriston +1 – Lina Sharifi May 29 '19 at 15:08
  • I found the working answer (though not fully understood it) . The webhook need to be async too, so instaed if `app.post('/webhook', (req, res) => {}` should be `app.post('/webhook', async (req, res) => {}` – Lina Sharifi May 29 '19 at 15:37
  • I am glad I could help you to track the issue. You can upvote the comment. Good luck in you project. – Cleriston May 30 '19 at 00:45

0 Answers0