2010-10-11 7 views
3

Ces derniers jours, je me suis cogné la tête contre le mur en soutenant la possibilité d'ajouter un contact à l'API Google Contacts dans mon application Rails 3. En dépit de nombreux faux départs, j'ai finalement fait quelques progrès en utilisant la gemme Ruby OAuth, et en suivant le tutoriel ici: http://everburning.com/news/google-analytics-oauth-and-ruby-oh-my/Ruby OAuth Nightmare: Utilisation de l'API Contacts

Lorsque je suis cela dans la console, je vais plus loin que dans mon application Rails. Je peux créer un jeton d'accès, m'authentifier auprès du service de Google avec la portée spécifique de l'API Contacts et appliquer le jeton oauth_verifier pour obtenir un jeton d'accès. Mais quand vient le temps de pousser les données, je reçois cette erreur:

response = at.post("https://www.google.com/m8/feeds/contacts/default/full", gdata) 
=> #<Net::HTTPUnauthorized 401 Unknown authorization header readbody=true> 

Où la « readbody = true » en-tête viennent, et comment pourrais-je me débarrasser?

Mais c'est pire dans l'application Rails. J'ai une action du contrôleur (« googlecontacts ») qui crée le jeton de demande et conduit l'utilisateur vers le site d'authentification avec Google:

def googlecontacts 

@card = Card.find_by_short_link(params[:id]) 

@consumer = OAuth::Consumer.new( 
    'anonymous', 
    'anonymous', 
    { 
    :site => 'https://www.google.com', 
    :request_token_path => '/accounts/OAuthGetRequestToken', 
    :access_token_path => '/accounts/OAuthGetAccessToken', 
    :authorize_path => '/accounts/OAuthAuthorizeToken', 
    :signature_method => 'HMAC-SHA1', 
    :oauth_version => '1.0' 
    }) 

@request_token = @consumer.get_request_token(
    {:oauth_callback => 'http://monkey.dev/cards/google_auth?redir='[email protected]_link}, 
    {:scope => "https://www.google.com/m8/feeds/"} 
) 

session[:request_token] = @request_token 

redirect_to @request_token.authorize_url 

end 

Cela semble fonctionner; Je reçois un objet de jeton de demande opérationnel et l'utilisateur est redirigé vers le service Google pour s'authentifier. L'URL de rappel ("google_auth") doit prendre le jeton oauth_verifier pour créer un jeton d'accès. Voici le début du contrôleur:

def google_auth 

    @access_token = session[:request_token].get_access_token(:oauth_verifier=>params[:oauth_verifier]) 

Et voici où ça craps. L'erreur sur cette dernière ligne est:

You have a nil object when you didn't expect it! 
You might have expected an instance of Array. 
The error occurred while evaluating nil.[] 

Mais les valeurs qui sont là - la session [:] request_token et les params [: oauth_verifier] - sont présents et pris en compte dans cette action! Je ne peux pas comprendre ce qui est nul ici.

Donc je suppose que je dois d'abord résoudre ce second problème, mais aussi des points bonus pour répondre au premier problème. :-)

Merci d'avoir lu.

Aaron.

+0

Bah, je trouve le problème. J'utilisais du code d'un développeur précédent, et il avait caché une redéfinition de la méthode Marshal dans environment.rb. Retiré cela et tout a disparu. Les heures gaspillées! –

+0

Juste une note: "readbody = true" n'est pas un en-tête. Cela fait partie de l'implémentation Ruby de l'objet réponse. Cela n'a jamais été envoyé par l'une ou l'autre des parties et cela n'a rien à voir avec le problème que vous aviez. –

Répondre

0

Essayez de définir/obtenir les données de session avec une chaîne qui n'est pas le symbole, c'est-à-dire session["request_token"], et non session[:request_token]. Je sais que j'ai déjà eu ce problème par le passé.

+0

Désolé, ça n'aide pas. Les valeurs de session sont clairement visibles dans l'action (un appel à "logger.debug" REQUEST: "+ @request_token.inspecter "donne les bonnes données", et la même chose avec la valeur params.Ma suspicion tombe sur l'appel à get_access_token parce que je ne peux pas trouver quelque chose de mal avec la ligne! Mais je ne sais pas comment dépanner le code dans le gem ... –

+0

Et dans 'google_auth', est-ce que' session [: request_token] 'a aussi les données correctes? Si c'est le cas, publiez la totalité de la trace de la pile. –

0

Unknown authorization header signifie généralement que votre signature ne correspond pas à ce que vous avez envoyé. Je ne recommande pas la gemme oauth. Il est plein de bugs et de problèmes étranges et n'échappe pas correctement à certains paramètres.

La gemme Signet est la gemme officiellement prise en charge pour accéder aux API Google dans Ruby.

est ici comment vous mettre en œuvre ce avec Sceau:

require 'signet/oauth_1/client' 
require 'addressable/uri' 
card = Card.find_by_short_link(params[:id]) 
callback = Addressable::URI.parse('http://monkey.dev/cards/google_auth') 
callback.query_values = {'redir' => card.short_link} 

client = Signet::OAuth1::Client.new(
    :temporary_credential_uri => 
    'https://www.google.com/accounts/OAuthGetRequestToken', 
    :authorization_uri => 
    'https://www.google.com/accounts/OAuthAuthorizeToken', 
    :token_credential_uri => 
    'https://www.google.com/accounts/OAuthGetAccessToken', 
    :client_credential_key => 'anonymous', 
    :client_credential_secret => 'anonymous', 
    :callback => callback 
) 

session[:temporary_credential] = (
    client.fetch_temporary_credential!(:additional_parameters => { 
    :scope => 'https://www.google.com/m8/feeds/' 
    }) 
) 
redirect_to(client.authorization_uri) 
Questions connexes