user2158382
user2158382

Reputation: 4510

Twilio-Ruby Validation Failing

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

Answers (3)

Thomas Lotze
Thomas Lotze

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

Apprentice Programmer
Apprentice Programmer

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

xmjw
xmjw

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

Related Questions