Reputation: 4510
I am using the twilio-ruby gem to validate that the request are coming from twilio, but it always incorrectly unvalidates a twilio request. Here is what I have so far
class CallsController < ApplicationController
before_filter :authenticate_request
private
# This action validates that the request are coming from twilio. It uses the twilio-ruby gem
# to validate that the twilio signature, url, and params are correctly from twilio
def authenticate_request
twilio_signature = request.headers['HTTP_X_TWILIO_SIGNATURE']
validator = Twilio::Util::RequestValidator.new(ENV['TWILIO_AUTH'])
verified = validator.validate(request.url, params, twilio_signature)
unless verified
response = Twilio::TwiML::Response.new do |r|
r.Say 'Unvalidated request'
r.Hangup
end
render :xml => response.text
end
end
end
Upvotes: 2
Views: 782
Reputation: 41
While using twilio_params = params.reject {|k,v| k.downcase == k} will work for some requests, sometimes Twilio does include non-uppercased params in the POST request (e.g., when sending digits after a Gather response). I've found that request.POST
or env['rack.request.form_hash']
works for me:
so, in context:
class CallsController < ApplicationController
before_filter :authenticate_request
private
# This action validates that the request are coming from twilio. It uses the twilio-ruby gem
# to validate that the twilio signature, url, and params are correctly from twilio
def authenticate_request
twilio_signature = request.headers['HTTP_X_TWILIO_SIGNATURE']
twilio_params = request.POST
validator = Twilio::Util::RequestValidator.new(ENV['TWILIO_AUTH'])
verified = validator.validate(request.url, twilio_params, twilio_signature)
unless verified
response = Twilio::TwiML::Response.new do |r|
r.Say 'Unvalidated request'
r.Hangup
end
render :xml => response.text
end
end
end
Upvotes: 2
Reputation: 1515
If anybody is having problems since then, the fix is that the params from rails does not work/match up with the params that twilio has
add this line and put it into the validate function and it should work
twilio_params = params.reject {|k,v| k.downcase == k}
Upvotes: 1
Reputation: 3434
Twilio Evangelist here.
It's hard to tell why this isn't working for you - but I have been able to replicate the same problem with your code. I'm not sure if it's the same cause though. If you read the Twilio specification for how this works, the URL is included in the secure hash to validate the request.
I'm using nginx to direct traffic to my application, which is forwarding from port 80 to port 3000. My Twilio webhook is http://example.com/voice
, but because of this server setup, my app is receiving the URL as http://example.com:3000/voice
.
You can get round this by removing the port number from the URL to make it match the Twilio request (there are other ways, such as hard coding the URL into the validation that may also work):
content_type 'text/xml'
twilio_signature = request.headers['HTTP_X_TWILIO_SIGNATURE']
validator = Twilio::Util::RequestValidator.new(ENV['TWILIO_AUTH'])
url = request.url
url.slice! ":3000"
verified = validator.validate(url, params, twilio_signature)
unless verified
response = Twilio::TwiML::Response.new do |r|
r.Say 'Unvalidated request'
r.Hangup
end
response.text
end
I can't be sure if this is exactly you problem, so if this doesn't help, can you post more information about the incoming request parameters etc? Be careful not to post your actual URL or Twilio credentials though!
Hope this helps.
Upvotes: 1