-->

Twitter Application Only Auth

2019-03-31 15:17发布

问题:

I'm trying to get an Application Only Auth token following the steps of this link: https://dev.twitter.com/docs/auth/application-only-auth

I'm using Ruby on Rails and Rest Client to make the POST request needed and I'm setting the headers (I think) properly.

The step-by-step says:

URL encode the consumer key and the consumer secret according to RFC 1738. Note that at the time of writing, this will not actually change the consumer key and secret, but this step should still be performed in case the format of those values changes in the future.

Concatenate the encoded consumer key, a colon character ":", and the encoded consumer secret into a single string.

Base64 encode the string from the previous step.

And my code is:

require 'rest_client'

    key = URI::encode('app_key')
    secret = URI::encode('app_secret')
    encoded = Base64.encode64("#{key}:#{secret}")

    res = RestClient::Resource.new "https://api.twitter.com/oauth2/token/"
    response = ''

    options = {}
    options['Authorization'] = "Basic #{encoded}"
    options['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'

    res.post('grant_type=client_credentials', options) do |response, request, result|
        response << "#{CGI::escapeHTML(response.inspect)}<br /><br />"
        response << "#{CGI::escapeHTML(request.inspect)}<br /><br />"
        response << "#{CGI::escapeHTML(result.inspect)}<br />"
    end

    render :text => txt

And I print out this:

"{\"errors\":[{\"label\":\"authenticity_token_error\",\"code\":99,\"message\":\"Unable to verify your credentials\"}]}"

#<RestClient::Request:0x9ece5d8 @method=:post, @headers={"Authorization"=>"Basic bXlfa2V5Om15X3NlY3JldA==\n", "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8"}, @url="https://api.twitter.com/oauth2/token/", @cookies={}, @payload="", @user=nil, @password=nil, @timeout=nil, @open_timeout=nil, @block_response=nil, @raw_response=false, @verify_ssl=false, @ssl_client_cert=nil, @ssl_client_key=nil, @ssl_ca_file=nil, @tf=nil, @max_redirects=10, @processed_headers={"Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate", "Authorization"=>"Basic bXlfa2V5Om15X3NlY3JldA==\n", "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8", "Content-Length"=>"29"}, @args={:method=>:post, :url=>"https://api.twitter.com/oauth2/token/", :payload=>"grant_type=client_credentials", :headers=>{"Authorization"=>"Basic bXlfa2V5Om15X3NlY3JldA==\n", "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8"}}>

#<Net::HTTPForbidden 403 Forbidden readbody=true>

My key and secret are valid. Am I missing something?

Thanks!


EDIT:

Updating with the solution I've found.

The problem was on the Base64 convertion and string encoding.

I had to add a forced encoding parameter to the key+secret combination, for UTF-8 convertion:

encoded = Base64.encode64("#{key}:#{secret}".force_encoding('UTF-8'))

The Rails Base64.encode64 inserts a line break every 60 encoded characters.

The workaround was:

For Ruby 1.9+ (strict_ was included in Ruby 1.9)

Base64.strict_encode64(string)

For Ruby 1.9-

Base64.encode64(string).gsub('/\n/') # To remove the line break

回答1:

Are you trying to implement Authorization with Tweeter (as OAuth Provider). Instead of writing it from the scratch following the API documentation, I would suggest to use OmniAuth. The setup & boilerplate code is fairly easy to use.

Read more about it at http://www.omniauth.org/ & https://github.com/intridea/omniauth/wiki

Let us know, if that helped you or not.