10

公式の aweber gemを使用して、OAuth 経由で Rails アプリを Aweber と統合しようとしています。

Rails コンソールでフローに従えば、問題なくアクセス トークンを取得できます。

oauth = AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
puts oauth.request_token.authorize_url
# => https://auth.aweber.com/1.0/oauth/authorize?oauth_token=xxxxxxxxxxxxxx

次に、その URL にアクセスして資格情報を入力し、確認コードを取得して、Rails コンソールに戻ります。

oauth.authorize_with_verifier 'xxxxxx'
# => #<OAuth::AccessToken>

成功!

問題は、これをコンソールだけでなく現実の世界で実行したいということです。つまり、Ruby コードを 2 つの別個のアクションに分割する必要があります。まず、Aweber の Oauth ページにリダイレクトするコントローラー アクションがあります。

def aweber
  oauth = AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
  redirect_to  oauth.request_token(oauth_callback: "http://127.0.0.1:3000/auth/aweber/callback").authorize_url
end

次に、ユーザーが資格情報を入力してリダイレクトされた後にアクセス トークンを取得するアクションがあります。

def aweber_callback
  oauth = AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
  oauth.authorize_with_verifier(params[:oauth_verifier]) 
end

このようにすると、最終行 ( authorize_with_verifier) で常に が発生し#<OAuth::Unauthorized: 401 Unauthorized>ます。

oauth問題は、変数を 2 回初期化していることです。つまり、2 つの無関係なAWeber::Oauth...のインスタンスがあり、authorize_url を生成した AWeber::Oauth のインスタンスのみがアクセス トークンを取得できます。しかし、コントローラーの 2 つの完全に異なるスレッドとインスタンスを扱っているため、両方で同じインスタンスを取得することはできません。aweber_callbackaweber

を調べるoauthと、内部変数oauth.request_token.params["oauth_token"]oauth.request_token.params["oauth_token_secret"]がそれぞれ で異なることがわかりoauthます。これが問題の原因であると推測しています。oauth_tokenparams ( ) から「正しい」値を取得できますparams[:oauth_token]が、正しい oauth_token_secret を取得する方法がわかりません (このようにインスタンス変数を手動で設定するのは非常にハックに感じられ、おそらく最善の方法ではないことは言うまでもありません)。

アクセス トークンを生成するにはどうすればよいですか?

4

2 に答える 2

7

oauth_token_secretをセッションに保存することで、ようやくこれが機能するようになりました。(そして、私は Aweber のドキュメントと API のセットアップに非常に感銘を受けていないと言わざるを得ません。これには本来の 10 倍の時間がかかりました。)

Gemfile

gem 'aweber', '~> 1.6.1', require: "aweber"

ルート

get "auth/aweber", to: "integrations#aweber", as: :aweber
get "auth/aweber/callback", to: "integrations#aweber_callback", as: :aweber_callback

統合コントローラー

def aweber
  oauth = get_aweber_oauth

  request_token = oauth.request_token(oauth_callback: aweber_redirect_uri)
  session[:aweber_oauth_token_secret] = request_token.secret

  redirect_to request_token.authorize_url
end


def aweber_callback
  oauth = get_aweber_oauth

  oauth.request_token = OAuth::RequestToken.from_hash(
    oauth.consumer,
    oauth_token: params[:oauth_token],
    oauth_token_secret: session[:aweber_oauth_token_secret],
  )

  access_token = oauth.authorize_with_verifier(params[:oauth_verifier])

  # TODO save access_token.token and access_token.secret
end

private

def get_aweber_oauth
  AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
end

def aweber_redirect_uri
  @_aweber_callback_uri ||= begin
    if Rails.env.production?
      redirect_host = "http://myproductionurl.com"
    else
      redirect_host = "http://127.0.0.1:3000"
    end
    "#{redirect_host}#{Rails.application.routes.url_helpers.aweber_callback_path}"
  end
end

access_token.token次のステップは、データベースに保存.secretすることです。これにより、次のような将来のリクエストでユーザーを承認できるようになります。

oauth = AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
oauth.authorize_with_access(current_user.aweber_token, current_user.aweber_secret)
aweber = AWeber::Base.new(oauth)
# Make calls using "aweber"...

omniauth-aweberジェムとジェムを組み合わせて使用​​してみましたが、機能しませんでした (このアプリで他のジェムを使用していて、一貫性を保つことができればよかったomniauthので、これは残念です)。 omniauth-xxxgem/auth/aweberはプロセスの一部を自動的に処理しますが、リダイレクトされた後、/auth/aweber/callback/取得する方法がわかりませんoauth_token_secret- リクエスト パラメータ、セッション、または Cookie にはありません。

私は今自分の質問に答えましたが、上記の明らかな改善を思い付くことができる人、またはそれをすべてomniauth-aweber.

于 2015-05-12T05:27:04.210 に答える
1

AWeber API Ruby Library を読むと、このビットが目立ちます

毎回確認したくない場合はどうすればよいですか?

一度検証すると、oauth オブジェクトには oauth.access_token.token と oauth.access_token.secret が含まれます。これらは、URL を介して検証することなくアプリケーションを承認するために使用できます。

... oauth.authorize_with_verifier('verification_code') puts 'Access
token: ' + oauth.access_token.token puts 'Access token secret: ' +
oauth.access_token.secret The token and secret can then be saved, and

承認は次のように実行できます。

require 'aweber'
oauth = AWeber::OAuth.new('consumer_key', 'consumer_secret')
#Rather than authorizing with the verification code, we use the token and secret 
oauth.authorize_with_access(YOUR_ACCESS_TOKEN, YOUR_ACCESS_TOKEN_SECRET) 
aweber = AWeber::Base.new(oauth)

それでは、これを実行してみましょう:

サインインを完了するのに十分な時間、各ユーザーのオブジェクトをメモリに保持し、有効期限が切れるまで使用するためにトークンとシークレットを保存するクラスを作成できます。

current_user は、ユーザーを一意に識別するものであることに注意してください。この時点でユーザーがまだログインしていない場合は、セッション ID を使用できます

class AWeberSignIn
    
    def self.start_signing user
        oauth = Rails.cache.fetch("#{user}/aweber", expires_in: 5.minutes) do
            AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
        end
        oauth.request_token(oauth_callback: "http://127.0.0.1:3000/auth/aweber/callback").authorize_url
    end

    def self.authorize_with_verifier user, oauth_verifier
        oauth = Rails.cache.fetch("#{user}/aweber")
        oauth.authorize_with_verifier(oauth_verifier)
        [oauth.access_token.token, oauth.access_token.secret]
    end

    def self.get_base_from_token token, secret
        oauth = AWeber::OAuth.new(ENV["AWEBER_CONSUMER_KEY"], ENV["AWEBER_CONSUMER_SECRET"])
        oauth.authorize_with_access(token, secret)
        AWeber::Base.new(oauth)
    end
end

このクラスを使用すると、コントローラー メソッドは次のようになります。

def aweber
  redirect_to  AWeberSignIn.start_signin current_user #Assuming you have a current_user helper. Use whatever gives you a unique value per user
end

def aweber_callback
  token, secret = AWeberSignIn.authorize_with_verifier(current_user, params[:oauth_verifier]) 
  #Do something with token and secret. Maybe save it to User attributes?
  #You can then use them to get a AWeber base object via AWeberSignIn.get_base_from_token token, secret
end

これは低レベルの Rails キャッシングを使用していることに注意してください。デフォルトとは異なるものが必要な場合は、キャッシュ技術を設定してください

于 2015-05-12T04:35:15.340 に答える