TwitterAPIを使ってOAuth2.0のフロー(Client Credentials)を確認した。
先日、以下のエントリーにて、4つあるOAuth2.0の認可フロー(Grant Type)からAuthorization Codeの流れを確認しました。
今回は、TwitterAPIにOAuth2.0でツイートの検索ができるよう認可してもらい、実際に検索結果のjsonが返ってくるところまでやっていきたいと思います。
Client Credentialsの流れは動画で確認できます。
参考
OAuth2.0(Client Credentials)について
Twitterの認可・仕様などについて
やること・ゴール
- 前回同様、Rubyで簡易的な実装で流れを掴んで行きたいと思います。
- 上記にも書きましたが、TwitterAPIにOAuth2.0でツイートの検索ができるよう認可してもらい、実際に検索結果のjsonが返ってくるところまでやっていきたいと思います。
Client Credentialsについて
Client Credentialsは他の認証フロー3つとは、少し異なります。
- ユーザ
- リソースを保持するサービス・認可をするサービス
- 第三者(リソースを保持するサービスのリソースを使いたい)
上記3人の登場人物がいたとすると、Client Credentials以外の認証フロー(Authorization Code, Implicit, Resource owner password credentials)は、 第三者がリソースへのアクセスの認可をしてもらうためのものです。 それに対して、Client Credentialsは認可を必要としていないリソースへアクセスする場合に使用します。
具体的にどういうこと?というと、 例えば、今回実装するTwitterAPIでは、 ‘Application-only authentication’ という認可のタイプ、以下の操作をすることが許可されます。 (TwitterAPIでは、この認可タイプ以外は、OAuth2.0に対応していないようです。)
- ツイートの検索
- ユーザのツイートの取得
- ユーザー情報を取得
- 任意のアカウントの友人やフォロワーの取得
など
反対にアクセスできないものは、
- ツイートの投稿
- ダイレクトメッセージの送信
など
つまり、ユーザ認可が必要のない公開されている内容のみ使用したい場合に使います。
恐らくアクセス数の制御のためだと思われます。
大まかな流れ
Client Credentials の説明を上記で行った通り、今回TwitterAPIでは、 ‘Application-only authentication’ の認可をもらいます。
流れとしては以下です。公式ページの流れに沿って実装していきます。
Application-only authentication — Twitter Developers
- consumer_keyとconsumer_secretを取得する
- consumer_keyとconsumer_secretをBase64でエンコードし、bearer_tokenを取得する
- bearer_tokenを使って、特定のアカウントのツイート一覧を表示する
consumer_keyとconsumer_secretを取得する
Twitter Developersにログインし、 consumer_keyとconsumer_secretをもらいます。 手順は検索すると多くの記事がでてくるので割愛します。
consumer_keyとconsumer_secretをBase64でエンコードし、bearer_tokenを取得する
ここは公式ページの Step 1: Encode consumer key and secret
, Step 2: Obtain a bearer token
に該当します。
以下のコードにあるように、consumer_key, consumer_secretをURIエンコードし、 :
で結合後、Base64エンコーディングし、リクエストを送信します。
# -*- coding: utf-8 -*- require 'uri' require 'net/http' require 'openssl' require 'base64' consumer_key = URI.encode({ consumer_key }) consumer_secret = URI.encode({ consumer_secret }) credential = Base64.strict_encode64(consumer_key + ':' + consumer_secret) uri = URI.parse('https://api.twitter.com/oauth2/token') https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true request_body_params = 'grant_type=client_credentials' request_header = { 'Authorization': "Basic #{credential}", 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 'Content-Length': request_body_params.length.to_s, 'Accept-Encoding': 'gzip' } request = Net::HTTP::Post.new(uri.request_uri, request_header) request.body = request_body_params response = https.request(request) puts response.code puts response.body
成功するとステータスコード200で以下のレスポンスが返ってきます。
access_token
が bearer_token
です。
{ "token_type":"bearer", "access_token": { ここにアクセストークンが表示されます。 } }
bearer_tokenを使って、特定のアカウントのツイート一覧を表示する
ここは公式ページの Step 3: Authenticate API requests with the bearer token
に該当します。
ひとまず、公式のサンプル通りに実装していきます。
# -*- coding: utf-8 -*- require 'uri' require 'net/http' access_token = { access_token } uri = URI.parse('https://api.twitter.com/1.1/statuses/user_timeline.json') https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true request_header = { 'Authorization': "Bearer #{access_token}", 'Accept-Encoding': 'gzip' } request_params = { count: '100', screen_name: 'twitterapi' } uri.query = URI.encode_www_form(request_params) request = Net::HTTP::Get.new(uri.request_uri, request_header) response = https.request(request) puts response.code puts response.body
成功するとステータスコード200でそれっぽいレスポンスがjsonで返ってきます。
せっかくなので、自分のツイートの検索してみます。 パラメータの仕様はこちらで確認しました。
GET search/tweets — Twitter Developers
# -*- coding: utf-8 -*- require 'uri' require 'net/http' access_token = { access_token } uri = URI.parse('https://api.twitter.com/1.1/search/tweets.json') https = Net::HTTP.new(uri.host, uri.port) https.use_ssl = true request_header = { 'Authorization': "Bearer #{access_token}", 'Accept-Encoding': 'gzip' } request_params = { q: '腹痛に耐えながらnginxをビルドし直し自サービスをhttp2化した。', lang: 'ja', result_type: 'mixed', count: '1' } uri.query = URI.encode_www_form(request_params) request = Net::HTTP::Get.new(uri.request_uri, request_header) response = https.request(request) puts response.code puts response.body
結果のjsonはちゃんと見ていませんが screen_name
に自分のアカウントが表示されていたので良さそうな気がします。