I've built a custom authorizer lambda function with NodeJS, which I've configured to authorize another lambda function in AWS. This other function is triggered from an HTTP endpoint, and has the URL that I configured in my Twilio Messaging Service as the webhook URL with a GET method.
I have to use GET, because AWS does not include a POST request's headers into the input param of the authorizer function, and I need the header in order to get the X-Twilio-Signature.
In the authorizer function, I'm invoking the Twilio Node Helper validateRequest(token, signature, url, params)
function and providing my auth token, the Twilio signature from the request header, and the exact same URL as configured in the webhook (no query params, no frills, just an https url with a path to the api resource).
However, the params is where I think things are breaking down and why the validation fails.
Since I'm using a GET method for the webhook, does that mean that when Twilio created the signature hash on their end, there was no POST data appended (per their docs on https://www.twilio.com/docs/api/security), or should I provide all the form data which they provide in the querysting of my GET request??
No matter what I've tried, my validation keeps failing as if the params I'm using are different than what Twilio did to create the signature.
I've created a simple test to see if I can validate the request using the params and signature of an actual HTTP request I made, but it never seems to work. Here's my simple test:
const token = '[my auth token]';
const url = 'https://my-api.company.io/sms/receive';
const signature = '[twilio header signature]';
const params = {
MessagingServiceSid: '[sid to my msg svc]',
ApiVersion: '2010-04-01',
SmsSid: 'SM6b3e14ea5e87ff967adb0c00c81406b8',
SmsStatus: 'received',
SmsMessageSid: 'SM6b3e14ea5e87ff967adb0c00c81406b8',
NumSegments: '1',
ToState: 'TX',
From: '+19998675309',
MessageSid: 'SM6b3e14ea5e87ff967adb0c00c81406b8',
AccountSid: '[my account sid]',
ToZip: '75229',
ToCity: 'DALLAS',
FromCountry: 'US',
FromCity: 'IRVING',
To: '[my twilio number]',
FromZip: '75014',
ToCountry: 'US',
Body: 'Super duper',
NumMedia: '0',
FromState: 'TX'
};
const result = twilio.validateRequest(token, signature, url, params);
console.log(result);
UPDATE To respond to an answer from Phil (Twilio Dev Evangelist), here's what I see in the logs from my authorizer function when I switch to using a POST webhook URL (this wouldn't fit in a comment, so I'm editing the Q).
Note that this payload does not have any of the above mentioned parameters which are provided by Twilio in the body of the POST request and which I'd presumably need to provide to the twilio.validateRequest
function:
{
type: 'REQUEST',
methodArn: 'arn:aws:execute-api:us-east-1:********:********/dev/POST/receive',
resource: '/receive',
path: '/sms/receive',
httpMethod: 'POST',
headers: {
Accept: '*/*',
'CloudFront-Viewer-Country': 'US',
'CloudFront-Forwarded-Proto': 'https',
'CloudFront-Is-Tablet-Viewer': 'false',
'CloudFront-Is-Mobile-Viewer': 'false',
'User-Agent': 'TwilioProxy/1.1',
'X-Forwarded-Proto': 'https',
'CloudFront-Is-SmartTV-Viewer': 'false',
Host: 'api.myredactedcompany.io',
'X-Forwarded-Port': '443',
'X-Amzn-Trace-Id': 'Root=**************',
Via: '1.1 ***************.cloudfront.net (CloudFront)',
'Cache-Control': 'max-age=259200',
'X-Twilio-Signature': '***************************',
'X-Amz-Cf-Id': '****************************',
'X-Forwarded-For': '[redacted IP addresses]',
'Content-Length': '492',
'CloudFront-Is-Desktop-Viewer': 'true',
'Content-Type': 'application/x-www-form-urlencoded'
},
queryStringParameters: {},
pathParameters: {},
stageVariables: {},
requestContext: {
path: '/sms/receive',
accountId: '************',
resourceId: '*****',
stage: 'dev',
requestId: '5458adda-ce2c-11e7-ba08-b7e69bc7c01c',
identity: {
cognitoIdentityPoolId: null,
accountId: null,
cognitoIdentityId: null,
caller: null,
apiKey: '',
sourceIp: '[redacted IP]',
accessKey: null,
cognitoAuthenticationType: null,
cognitoAuthenticationProvider: null,
userArn: null,
userAgent: 'TwilioProxy/1.1',
user: null
},
resourcePath: '/receive',
httpMethod: 'POST',
apiId: '*******'
}
}