Pregunta

I manually requesting a request token from twitter and pass the callback to the default page for a device, but get an error

Started GET "/users/auth/twitter/callback?device=mobile&oauth_token=mVpOFb1ruczKw7LzbgQYX73nq81hiw5OEBSOpob5rJk&oauth_verifier=WzBwpFdf7rYDH4DDWNbIfYPkHrIUzam9Ld6vskQrzNA" for 127.0.0.1 at 2014-02-03 18:00:03 +0400 

omniauth: (twitter) Authentication failure! invalid_credentials: OAuth :: Unauthorized, 401 Unauthorized

If I log in through Devise, all without errors. Instructions took here. Why is this happening?

class Api::TwitterController < ApplicationController
  def get_auth_token
    consumer_key = OAUTH_KEYS[Rails.env]['twitter']['client_id'] # Obtainable from your destination site's API admin panel
    consumer_secret = OAUTH_KEYS[Rails.env]['twitter']['secret_key'] # As above
    callback_url = user_omniauth_callback_url(:twitter, device: :mobile)
    method = 'POST'
    uri = 'https://api.twitter.com/oauth/request_token'
    params = set_params(consumer_key)
    params['oauth_callback'] = url_encode(callback_url)
    params['oauth_signature'] = url_encode(sign(consumer_secret + '&', signature_base_string(method, uri, params)))
    token_data = parse_string(request_data(header(params), uri, method))
    auth_token, auth_token_secret = [token_data['oauth_token'], token_data['oauth_token_secret']] # save these values, they'll be used again later
    redirect_to "https://api.twitter.com/oauth/authorize?oauth_token=#{auth_token}"
  end

  private

  # where parse_string is simply
  def parse_string(str)
    ret = {}
    str.split('&').each do |pair|
      key_and_val = pair.split('=')
      ret[key_and_val[0]] = key_and_val[1]
    end
    ret
  end

  def set_params(consumer_key)
    params = {
      'oauth_consumer_key' => consumer_key, # Your consumer key
      'oauth_nonce' => generate_nonce, # A random string, see below for function
      'oauth_signature_method' => 'HMAC-SHA1', # How you'll be signing (see later)
      'oauth_timestamp' => Time.now.getutc.to_i.to_s, # Timestamp
      'oauth_version' => '1.0' # oAuth version
    }
  end

  def generate_nonce(size=7)
    Base64.encode64(OpenSSL::Random.random_bytes(size)).gsub(/\W/, '')
  end

  def signature_base_string(method, uri, params)
    # Join up the parameters into one long URL-safe string of key value pairs
    encoded_params = params.sort.collect{ |k, v| url_encode("#{k}=#{v}") }.join('%26')
    # Join the above with your method and URL-safe destination URL
    method + '&' + url_encode(uri) + '&' + encoded_params
  end

  # I'm a PHP developer primarily, hence the name of this function!
  def url_encode(string)
   CGI::escape(string)
  end

  # where sign is:
  def sign(key, base_string)
    digest = OpenSSL::Digest::Digest.new('sha1')
    hmac = OpenSSL::HMAC.digest(digest, key, base_string)
    Base64.encode64(hmac).chomp.gsub(/\n/, '')
  end

   # where header is:
  def header(params)
    header = "OAuth "
    params.each do |k, v|
      header += "#{k}=\"#{v}\", "
    end
    header.slice(0..-3) # chop off last ", "
  end

  def request_data(header, base_uri, method, post_data=nil)
    url = URI.parse(base_uri)
    http = Net::HTTP.new(url.host, 443) # set to 80 if not using HTTPS
    http.use_ssl = true # ignore if not using HTTPS
    if method == 'POST'
      # post_data here should be your encoded POST string, NOT an array
      resp, data = http.post(url.path, post_data, { 'Authorization' => header })
    else
      resp, data = http.get(url.to_s, { 'Authorization' => header })
    end
    resp.body
  end
end
¿Fue útil?

Solución

Problem solved, it was necessary to add some data in the session

auth_token, auth_token_secret = [token_data['oauth_token'], token_data['oauth_token_secret']]
session['oauth'] ||= {}
session['oauth']['twitter'] ||= {}
session['oauth']['twitter']['request_token'] = auth_token
session['oauth']['twitter']['request_secret'] = auth_token_secret
session['oauth']['twitter']['callback_confirmed'] = true
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top