LoginSignup
4
4

More than 5 years have passed since last update.

Rubyでgemを使わずに、twitterのアクセストークンを取得

Last updated at Posted at 2015-10-23

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を使って書いているので、助かりました!

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4