Ruby(rails)でアクセストークンを取得する際の大まかな流れ
1. アプリ登録時に発行されたAPI_KEY、API_SECRETを使って、リクエストトークンを発行する
2. リクエストトークンをパラメーターにして、twitterの認証画面にリダイレクトする
3. ユーザーがリダイレクト先でアプリを認証
4. 認証完了後、パラメーターにoauth_tokenとoauth_verifierを持って、帰ってくる
5. アプリ登録時に発行されたAPI_KEY、API_SECRET、4で手に入った値を使ってアクセストークンを取得する
以上となります。
ソースコード
エラーハンドリングとか、かなり雑です。参考程度にご利用ください。
「とりあえず動け」な発想の元に作ったのでメソッド化とか無視してます。
get_access_token.rb
def index
request_tokens = get_request_token
oauth_token = request_tokens["oauth_token"]
redirect_url = "https://api.twitter.com/oauth/authenticate?oauth_token=#{oauth_token}"
session[:oauth_token] = oauth_token
redirect_to redirect_url
end
def callback
oauth_token = params[:oauth_token]
oauth_verifier = params[:oauth_verifier]
denied = params[:denied]
if denied.present?
render text: "Procedure canceled."
return
end
if session[:oauth_token].blank? || session[:oauth_token] != oauth_token
render text: "oauth_token is not matched."
return
end
res = get_access_token(oauth_token, oauth_verifier)
res_oauth_token = res["oauth_token"]
res_oauth_token_secret = res["oauth_token_secret"]
res_user_id = res["user_id"]
screen_name = res["screen_name"]
x_auth_expires = res["x_auth_expires"]
str = "res_oauth_token: #{res_oauth_token}, res_oauth_token_secret: #{res_oauth_token_secret},"+
"res_user_id #{res_user_id}, screen_name #{screen_name}, x_auth_expires #{x_auth_expires}"
render text: str
end
def get_request_token
api_key = 'hogehogehogehoge'
api_secret = 'fugofugofugofugo'
access_token = ''
access_token_secret = ''
callback_url = 'http://127.0.0.1:3000/callback'
params = {
"oauth_callback" => callback_url,
"oauth_consumer_key" => URI.escape(api_key),
"oauth_nonce" => URI.escape(SecureRandom.uuid),
"oauth_signature_method" => URI.escape('HMAC-SHA1'),
"oauth_timestamp" => URI.escape(Time.now.to_i.to_s),
"oauth_version" => URI.escape('1.0')
}
signature_key = "#{URI.escape(api_secret)}&#{URI.escape(access_token_secret)}"
method = 'POST'
request_url = 'https://api.twitter.com/oauth/request_token'
request_oauth_header = sort_and_concat(params, "&")
signature_data = "#{URI.escape(method)}&#{escape(request_url)}&#{escape(request_oauth_header)}"
hash = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, signature_key, signature_data)
signature = escape(Base64.strict_encode64(hash))
params["oauth_signature"] = signature
header_params = sort_and_concat(params, ',')
twitter_uri = URI.parse(request_url)
https = Net::HTTP.new(twitter_uri.host, twitter_uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(twitter_uri)
req["Authorization"] = "OAuth #{header_params}"
https.set_debug_output $stderr
res = https.request(req)
#res.code + "/" +res.body
param_hash = Hash.new
array = res.body.split('&')
array.each { |e|
param = e.split('=')
param_hash[param[0]] = param[1]
}
return param_hash
end
def get_access_token(oauth_token, oauth_verifier)
oauth_token_secret = session[:oauth_token_secret]
if oauth_token_secret.blank?
return "oauth_token_secret is not arrive in session."
end
api_key = 'hogehogehogehoge'
api_secret = 'fugofugofugofugo'
access_token = ''
access_token_secret = ''
params = {
"oauth_consumer_key" => URI.escape(api_key),
"oauth_nonce" => URI.escape(SecureRandom.uuid),
"oauth_signature_method" => URI.escape('HMAC-SHA1'),
"oauth_timestamp" => URI.escape(Time.now.to_i.to_s),
"oauth_token" => oauth_token,
"oauth_verifier" => URI.escape(oauth_verifier),
"oauth_version" => URI.escape('1.0')
}
signature_key = "#{URI.escape(api_secret)}&#{URI.escape(access_token_secret)}"
method = 'POST'
request_url = 'https://api.twitter.com/oauth/access_token'
request_oauth_header = sort_and_concat(params, "&")
signature_data = "#{URI.escape(method)}&#{escape(request_url)}&#{escape(request_oauth_header)}"
hash = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, signature_key, signature_data)
signature = escape(Base64.strict_encode64(hash))
params["oauth_signature"] = signature
header_params = sort_and_concat(params, ',')
twitter_uri = URI.parse(request_url)
https = Net::HTTP.new(twitter_uri.host, twitter_uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(twitter_uri)
req["Authorization"] = "OAuth #{header_params}"
https.set_debug_output $stderr
res = https.request(req)
param_hash = Hash.new
if res.code == "200"
array = res.body.split('&')
array.each { |e|
param = e.split('=')
param_hash[param[0]] = param[1]
}
else
param_hash["error_msg"] = res.body
end
return param_hash
end
def sort_and_concat(params, delimiter)
params = params.sort
str = params.collect{|k, v| "#{k}=#{v}"}.join(delimiter)
return str
end
def escape(str)
return ERB::Util.url_encode(str)
end
参考
Twitter APIの使い方まとめを参考にして書いています。どこのサイトもgemを使って書いているので、助かりました!