Een GET coderen met OAuth in Ruby Twitter API

Ik probeer een eenvoudige ruby on Rails-webapp te schrijven die zich via oAuth bij Twitter aanmeldt en de gebruikerslijst van volgers krijgt, zonder een bestaande oAuth-bibliotheek te gebruiken . Gebruikmakend van hun gids op https://dev.twitter.com/docs/auth/oauth , Ik heb het voor elkaar gekregen om correct in te loggen en dus een volgende outh_token en oauth_token_secret te hebben. Wanneer ik echter probeer de GET-aanvraag voor de volgers van de ingelogde gebruiker te coderen, ontvang ik een 401 "Deze methode vereist authenticatie."

Met behulp van mijn code en hun voorbeeldgegevens, kan ik zien dat ik de juiste handtekening goed genereer. Ik kan de signature_base_string verkeerd genereren, maar aangezien het goed werkt bij het inloggen, zie ik niet hoe het de tweede keer verkeerd kan zijn. De methoden maken deel uit van een klasse, dus de consument-sleutel en het geheim zijn duidelijk klassenvariabelen.

Relevante code is hieronder. Het is de uitvoer van de HTTP GET in 'volgers' die de 401 geeft. Ik hoop dat dit iets belachelijk voor de hand liggend is dat ik gewoon mis omdat ik hier te lang naar kijk! Ik weet dat ik de juiste waarden heb doorgegeven aan de functie als parameters. Bedankt.

  def followees(auth_token, auth_token_secret, user_id)
    method = 'GET'
    base_uri = 'https://api.twitter.com/1/friends/ids.json'
    params = {
      'cursor' => '-1',
      'oauth_consumer_key' => @@consumer_key,
      'oauth_nonce' => generate_nonce, #not shown, no need!
      'oauth_signature_method' => 'HMAC-SHA1',
      'oauth_token' => auth_token,
      'oauth_timestamp' => Time.now.to_i.to_s,
      'oauth_version' => '1.0',
      'user_id' => user_id
    }
    signature_base_string = signature_base_string(method, base_uri, params)
    params['oauth_signature'] = url_encode(sign(@@consumer_secret + '&' + auth_token_secret, signature_base_string))
    header = header(params)
    base_uri += '?cursor=-1&user_id=' + user_id
    url = URI.parse(base_uri)
    http = Net::HTTP.new(url.host, 443)
    http.use_ssl = true
    resp, data = http.get(url.path, { 'Authorization' => header })
  end

  def signature_base_string(method, uri, params)
    encoded_params = params.sort.collect{ |k, v| url_encode("#{k}=#{v}") }.join("%26")
    method + '&' + url_encode(uri) + '&' + encoded_params
  end

  def url_encode(string)
    CGI::escape(string)
  end

  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

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

1 antwoord

Ik heb het uitgezocht. Nodig een pauze om een ​​stap terug te doen! Kortom, de laatste regel in de volgees was niet inclusief de GET-gegevens, dus

resp, data = http.get(url.path, { 'Authorization' => header })

had moeten zijn

resp, data = http.get(url.to_s, { 'Authorization' => header })

Ik had de code gekopieerd voor POSTing, vandaar dat alleen url.path daar werd gebruikt.

1
toegevoegd