「TwitterDevelopers」におけるOAuthページの簡単な和訳まとめ
[履歴] [最終更新] (2015/08/09 15:41:56)
最近の投稿
注目の記事

概要

(元ページ https://dev.twitter.com/docs/auth/oauth)

TwitterではOAuth認証によるAPI利用が可能です。TwitterAPIにはv1.1とv1.0が存在していますが、v1.1を使用するようにしてください。TwitterAPIv1.1においてサポートされているOAuthのバージョンは「OAuth 1.0A」です。TwitterAPIv1.1のOAuth認証は以下の二つに大別できます。

  • Application-user authentication: アプリケーションが、あるTwitterユーザーの権限でAPIを利用するための認証
  • Application-only authentication: アプリケーションが、Twitterユーザーの権限なしでAPIを利用するための認証

TwitterAPIv1.1のAPI群には、前者の認証方法だけをサポートしているものと、両者をサポートしているものがあります。例えば「ツイートする」というAPIは前者しかサポートしていませんが、「あるユーザーのツイートを取得する」というAPIは両者をサポートしています。APIには一般に呼び出し頻度について制限が設けられていますが、同じAPIでも両者の認証方法をサポートしているものについては、どちらの認証でAPIアクセスしているかによって、その頻度の制限値に違いがあります。あるAPIの利用頻度の制限は、各APIのドキュメントページに記載されています。

APIリクエストをOAuth認証で行うとは?

(元ページ https://dev.twitter.com/docs/auth/authorizing-request)

APIリクエストはHTTPのGETまたはPOSTで行われます。例えばAPIリクエストをOAuthで行い"Hello"とツイートすることは、以下のHTTP POSTを行うことと同義です。HTTPについてはこちらのまとめをご参照ください。

APIリクエスト例 <*1>

POST /1/statuses/update.json?include_entities=true HTTP/1.1
Accept: */*
Connection: close
User-Agent: OAuth gem v0.4.4
Content-Type: application/x-www-form-urlencoded
Authorization: 
        OAuth oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog", 
              oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg", 
              oauth_signature="tnnArxj06cWHq44gCs1OSKk%2FjLY%3D", 
              oauth_signature_method="HMAC-SHA1", 
              oauth_timestamp="1318622958", 
              oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb", 
              oauth_version="1.0"
Content-Length: 76
Host: api.twitter.com

status=Hello

Authorizationヘッダーで指定されている7つの値の有無が、単なるAPIリクエストであるか、OAuthを利用してのAPIリクエストであるかの違いです。当然ながら、TwitterAPIはOAuth認証を必要としますので、これらの7つの値を適切に含めてAPIアクセスしなければなりません。

oauth_consumer_key

どのアプリケーションがAPIリクエストを行っているかをサーバ側が識別するための値です。名称に「key」とありますが、秘密鍵ではなくアプリケーションのIDですので、盗聴されても問題にはならない値です。アプリケーション開発者がこちらのページから事前にTwitterに申請を行うことで取得しておく必要のある値です。

oauth_nonce

「nonce」という英単語には「その場限りの」といった意味があります。ここでは特に「使い捨て乱数データ、ワンタイムパスワード」を意味しています。アプリケーション側でAPIリクエスト毎にユニークな値を生成しておけばよく、その生成方法に厳密な規則はありません。同じAPIリクエストが重複して送られてきた場合にサーバ側で無視できるようにするための値です。サーバ側にはAPI利用頻度の制限があるため、サーバ側を守るための値というよりはむしろ、クライアントアプリケーション側を守るための値と考えられます。

oauth_signature

今回送信しようとしているAPIリクエストが

  • 確かにoauth_consumer_keyというIDのアプリケーションからのものであること <*A>
  • oauth_consumer_keyというIDのアプリケーションが然るべき手続を経ていること <*B>

を保証するための値です。これによって、以下の三つを回避できます。

  • oauth_consumer_keyを盗聴した他のアプリケーションがなりすましをする危険性 (クライアント側を守る)
  • 通信の途中でAPIリクエストの内容が改竄される危険性 (クライアント側を守る)
  • 必要な手続を経ていない状態で、アプリケーションによってAPI利用がなされる危険性 (サーバ側を守る)

具体的には、「oauth_consumer_keyとセットでアプリケーション開発者に付与される秘密鍵 (oauth_consumer_key_secret) <*A>」および「然るべき手続を経た後にアプリケーションに付与される秘密鍵 (oauth_token_secret) <*B>」を "&" で結合した文字列によって、前述の「APIリクエスト例 <*1>」のほぼすべてを一行の文字列に加工したもののMAC値 (メッセージ認証コード、つまり鍵に依存したハッシュ値) を計算した値です。より詳細な生成方法は https://dev.twitter.com/docs/auth/creating-signature に記載されています。

oauth_signature_method

「oauth_signature」のMAC値を計算する際のアルゴリズムを指定します。受信した内容をもとにサーバ側でもMAC値を計算して「oauth_signature」と一致することを確認する必要があるため、どのアルゴリズムで計算したのかという情報が必要になるのです。

oauth_timestamp

APIリクエストが生成された時刻です。エポックタイムです。大昔のAPIリクエストが何故か再送されてきた場合に、それらを無視するためにサーバ側で使用されます。

oauth_token

然るべき手続を経た後にアプリケーション側に oauth_token_secret (<*B>) とセットで付与される、その手続の内容を表現した文字列です。oauth_tokenの値から、サーバ側はこのAPIリクエストがどのような手続を経た後のものなのかを確認できます。具体的には、「あるTwitterユーザの許可を得る」という手続が完了した状態でのAPIアクセスであるのか、といったことをサーバ側が知ることができます。特にこの具体例の場合の oauth_token を access_token と称します。oauth_token には他にも「access_tokenを要求する準備をする」という手続を表現した request_token というものもあります。また、特に事前の手続を必要としないAPIの場合はoauth_tokenは空欄の状態でのOAuth認証となります。

oauth_version

利用するOAuthのバージョンです。TwitterAPIv1.1では1.0をサポートしているため、必ず 1.0 という値になります。

アクセストークンおよびその秘密鍵の入手方法

(元ページ https://dev.twitter.com/docs/auth/obtaining-access-tokens)

前述の通り、oauth_tokenの特殊な例としてアクセストークン (access_token) があり、その秘密鍵 (access_token_secret) とセットで、あるTwitterユーザーの権限でAPIを利用できます。アクセストークンには様々な入手方法があります。

Sign in with Twitter

Qooskyを含め、Webアプリでよくある「Twitterアカウントでログイン」の機能において、アクセストークンを入手する方法です。概要としては、リクエストトークンをTwitterから発行してもらい、それをユーザーにリダイレクトページで認証してもらった後、Twitterに再度依頼してリクエストトークンをもとにアクセストークンと取得します。こちらのページ「OAuthプロトコルの中身をざっくり解説してみるよ」が詳しくて分かりやすいです。Twitter公式ドキュメントはこちらです。

dev.twitter.com

不特定多数のユーザ権限でAPIリクエストを行う必要のある場合は「Sign in with Twitter」の手順で、ユーザに認証してもらったリクエストトークンをもとにアクセストークンを取得すればよいです。しかしながら、いわゆるTwitterBotを作成する場合などは、ユーザーが一つに特定されるため、リクエストトークンを認証してもらうのではなく直接Twitterのサイトにそのユーザでログインし、アクセストークンを発行するという対応が可能です。具体的な発行手順はこちらのドキュメントをご参照ください。

アクセストークンおよびその秘密鍵の利用例

(元ページ https://dev.twitter.com/docs/auth/oauth/single-user-with-examples)

上述のいずれかの方法で入手したアクセストークンを利用してAPIアクセスを行う、具体的なrubyスクリプトをご紹介します。

インストール

事前にoauthのGEMパッケージをインストールしておいてください

$ gem install oauth

サンプルスクリプト

TwitterAPIv1.1群のうち、アカウントのHOMEのタイムラインを取得するAPIと、ツイートするAPIを、それぞれGETとPOSTの例として使用してみます。
他のAPIについても使用方法は同様です。具体的には公式ドキュメントをご覧ください。

#!/usr/bin/ruby
# -*- coding: utf-8 -*-
#
require 'oauth'
require 'json'

# Exchange your oauth_token and oauth_token_secret for an AccessToken instance.
def prepare_access_token(oauth_token, oauth_token_secret)
  consumer = OAuth::Consumer.new("oauth_consumer_key", "oauth_consumer_key_secret",
    { :site => "https://api.twitter.com",
      :scheme => :header })

  # now create the access token object from passed values
  token_hash = { :oauth_token => oauth_token,
                 :oauth_token_secret => oauth_token_secret }

  access_token = OAuth::AccessToken.from_hash(consumer, token_hash)
  return access_token
end

# Exchange our oauth_token and oauth_token secret for the AccessToken instance.
access_token = prepare_access_token("access_token", "access_token_secret")


# GET statuses/home_timeline
#  https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline
response = access_token.request(:get, "https://api.twitter.com/1.1/statuses/home_timeline.json?count=2")
result = JSON.parse(response.body)
p result


# POST statuses/update
#  https://dev.twitter.com/docs/api/1.1/post/statuses/update
access_token.request(:post, "https://api.twitter.com/1.1/statuses/update.json", status: '日本語テスト')

参考情報: TwitterGem

先程はOAuthの仕組みを理解するためにoauthのGEMパッケージを利用してみましたが、実際にTwitterボットを開発する際には、oauthのGEMパッケージをラップして使いやすくしたTwitterGemパッケージを使用するのがよいです。

$ gem install twitter

ドキュメントは少ないですが、APIへのHTTP POSTおよびGETの実行部分についてソースコードを読んでみると分かりやすくまとまっていることが分かります。

これとTwitter公式のAPIドキュメントを併用すれば、ドキュメントなしでも十分に利用できます。

twitter-bot.rb

#!/usr/bin/ruby
# -*- coding: utf-8 -*-
#
require 'twitter'

client = Twitter::REST::Client.new do |config|
  config.consumer_key = "oauth_consumer_key"
  config.consumer_secret = "oauth_consumer_key_secret"
  config.access_token = "access_token"
  config.access_token_secret = "access_token_secret"
end

### ツイートを実行
# - ソースコード: https://github.com/sferik/twitter/blob/master/lib/twitter/rest/tweets.rb
# - ドキュメント: https://dev.twitter.com/docs/api/1.1/post/statuses/update
client.update("日本語")

### 画像付きでツイート
# - ソースコード: https://github.com/sferik/twitter/blob/master/lib/twitter/rest/tweets.rb
# - ドキュメント: https://dev.twitter.com/docs/api/1.1/post/statuses/update_with_media
client.update_with_media("日本語", File.new("/path/to/media.png"))

### 逐次サーバ側で更新されるAPI利用制限情報などを取得
# - ソースコード: https://github.com/sferik/twitter/blob/master/lib/twitter/rest/help.rb
# - ドキュメント: https://dev.twitter.com/docs/api/1.1/get/help/configuration
client.configuration.non_username_paths.each do |non_username|
  puts non_username
end

### 自分のタイムラインの情報を取得
# - ソースコード: https://github.com/sferik/twitter/blob/master/lib/twitter/rest/timelines.rb
# - ドキュメント: https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline
client.home_timeline(count: 2).each do |tl|
  puts tl.text
end

なお、環境によってはSSL通信を行う際に

/Users/hoge/.rbenv/versions/2.0.0-p195/lib/ruby/2.0.0/net/http.rb:918:in `connect':
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate
verify failed (Twitter::Error::ClientError)

といったエラーが発生します。rubyの参照できるディレクトリにルートCAの証明書が存在しないことが原因です。まず

$ ruby -ropenssl -e "p OpenSSL::X509::DEFAULT_CERT_FILE"
C:/Users/Luis/Code/luislavena/knap-build/var/knapsack/software/x86-windows/openssl/1.0.0l/ssl/cert.pem

によってrubyが参照している証明書の場所を調査し、そこに証明書ファイルを作成します。管理者権限で以下のような内容を実行してください。

$ mkdir -p C:\Users\Luis\Code\luislavena\knap-build\var\knapsack\software\x86-windows\openssl\1.0.0l\ssl
$ wget -O C:\Users\Luis\Code\luislavena\knap-build\var\knapsack\software\x86-windows\openssl\1.0.0l\ssl
    http://curl.haxx.se/ca/cacert.pem
関連ページ
    概要 こちらのページで開発環境の構築方法をまとめた Spring Boot における OAuth2 のサンプルコードをまとめます。こちらのページで和訳した Twitter API で利用されている OAuth 1.0A と区別します。こちらのページで簡単なサンプルをまとめた Spring Security プロジェクト配下の