Twitter の OAuth を試す in Scala

Written by @dr_taka_n at 2010/09/07 00:06:34 [, , ]

Twitter では Basic 認証が廃止され、OAuth への移行が完了している。

過去に用意していたちょっとしたツールで対応していないものがあったので、Basic 認証から OAuth に切り替えを行った時の OAuth に関するメモを残しておく。

OAuth の流れ

OAuth における主な登場人物は、Consumer、Provider、User の3者となる。

Twitter に OAuth を利用して API を使用するアプリを考えた時、それぞれの実体は、

  • Consumer (アプリ)
  • Provider (Twitter)
  • User (アプリの利用者)

となる。

OAuth を利用した API の呼び出しまでの大まかな流れは以下の通りとなる。

  1. Consumer 登録
    • アプリの作成者が、
      Twitter (Provider) に自身の作成するアプリの登録を行う。
      • 今回の主題からは外れるが、気になる点を。
        Twitter (Provider) から OAuth 利用の許可を得る行為となるが、現状では、Twitter 側で審査的なものは行っていない。 元々 OAuth の概念では、あらかじめ信頼関係を構築したサービス間で、ユーザの同意のもと、権限を委譲する、というものであったはず。 Twitter と Consumer 登録を行ったアプリ(もしくはサービス)の間では、現状信頼関係はない・・・
  2. リクエストトークンの取得
    • アプリ (Consumer)が、
      アプリの利用者に、認可を求めるページを提示するために必要なリクエストトークン情報を Twitter (Provider) から取得する
  3. 認可用 URL へのリダイレクトとユーザによる認可
    • アプリ (Consumer) が Twitter (Provider) の力を借りて、
      アプリの利用者(ユーザ)に、アプリ (Consumer) が利用者の代わりに Twitter (Provider) にアクセスを行うことの認可を求める。
  4. アクセストークンの取得
    • アプリ (Consumer)が、
      アプリの利用者の認可の結果を受け、Twitter (Provider) からアクセストークンを取得する。
  5. API の呼び出し
    • アプリ (Consumer)が、
      アクセストークンを使って、Twitter (Provider) の API を利用する。

1 はアプリを作成する際の最初の1回のみの作業となる。登録のページは以下のページとなる。

このメモでは登録に関することは記述しないので、事前に上記サイトで Consumer 登録を行っており、この後の OAuth の利用で必要となる情報、

  • Consumer key
  • Consumer secret

を取得済みということを前提とする。

ちなみに、このメモで使用しているアプリの Consumer 登録の情報は以下の通り。

Consumer Setteings Consumer Setteings

上記のサイトの情報にあるように、OAuth を利用する際に意識しておく URL は3つあり、それぞれ以下の URL となる。

  • Request token URL
    • http://twitter.com/oauth/request_token
    • リクエストトークンの取得に利用 (上記の 2.)
  • Access token URL
    • http://twitter.com/oauth/access_token
    • アクセストークンの取得に利用 (上記の 4.)
  • Authorize URL
    • http://twitter.com/oauth/authorize
    • ユーザに認可を求める際に利用 (上記の 3.)

Scala を使って Twitter の OAuth を利用する

まず、Scala で Web と会話するための選択肢としては、

  • Java の標準ライブラリ HttpURLConnection を利用する
  • Apache が提供する HttpComponents を利用する
  • HTTP を利用したサービスの実装に便利な Dispatch → About を利用する。
    内部的には HttpCoomponets を使用している。

などがあるようだ。
(scala.io.Source#fromURL はあまりに限定的で。。)

Twitter 用のライブラリもあるようだが、まだ Scala、及び、OAuth に慣れていない状況なので、できれば素の状態で試してみたい。HttpURLConnection を使ってやってみようかと思ったが、少々面倒臭いなぁ・・・。。というところで、HttpURLConnection をラップした非常にシンプルだが、使い勝手も良さそうなライブラリ scalaj’s scalaj-http at master - GitHub を気に入ったので、これを使ってみることにした。 OAuth の実装も既に行われている。
ソースも非常にコンパクトになっているので、OAuth の実装、関数型言語の特性も持つ Scala での関数値の使いどころなど、参考になるところが多い。

2. リクエストトークンの取得

scalaj-http をインポートし、リクエストトークンの取得に必要なアプリ(Consumer)側の情報 (Consumer key と Consumer secret) を準備しておく。

scala> import scalaj.http.{Http, Token}
import scalaj.http.{Http, Token}

scala> val consumer = Token("consumerKey", "consumerSecret")
consumer: scalaj.http.Token = Token(consumerKey,consumerSecret)

Twitter (Provider) にリクエストトークンの取得を要求し、リクエストトークンを取得する。
要求する URL は、先に記述していた Request token URL となる。

scala> val token = Http("http://twitter.com/oauth/request_token").param("oauth_callback", "").oauth(consumer).asToken
token: scalaj.http.Token = Token(oauthToken,oauthTokenSecret)

取得できたリクエストトークンを確認する。

scala> token.key
res20: String = oauthToken

上記の oauthToken (実際の値は要求毎に異なる) がリクエストトークンにあたる。

アプリの利用者(User)に認可を依頼するページの URI は、先に記述していた Authorize URL に、このリクエストトークンをクエリ文字列として付加した URI となる。

なお、上記の token インスタンスの中には、oauth_token_secret (token.secret) も含まれており、これは、アクセストークンを発行してもらう際に使用される。

3. 認可用 URL へのリダイレクトとユーザによる認可

ブラウザを起動し、以下の URI にアクセスする。

http://twitter.com/oauth/authorize?oauth_token=oauthToken

Twitter にログインしていなければ、Twitter へログインするための入力フィールドと、アプリが Twitter へのアクセスを行うことに対する認可を行う画面が表示される。 「疎通試験用テストアプリ」が Twitter へのデータにアクセスする旨、データを更新する旨の説明があり、それに対して許可するかどうかの判断を求めた画面が表示される。

OAuth Authorize No Login

既に Twitter にログイン済みの場合は、Twitter のログイン用の入力フィールドのない以下の画面が表示される。
(ログインしてない画面と言語が異っているのは、自身、Twitter では言語を英語で使っているため。)

OAuth Get Access Token

「許可する」、もしくは、「Allow」をクリックすると、画面に何かしらの7桁の数字が表示される。

OAuth Get Access Tokne Digest

この数字は oauth_verifier というもので、アプリ(Consumer) が Twitter (Provider)にアクセスするためのアクセストークンを取得するために必要な要素となるので、控えておく。

4. アクセストークンの取得

アクセストークンを取得するための情報が集ったので、実際にアクセストークンを取得する。先程の画面に表示された数値が 9999999 だとした場合、以下のような呼び出しとなる。

scala> val accessToken = Http("http://twitter.com/oauth/access_token").oauth(consumer, token, "9999999").asToken
accessToken: scalaj.http.Token = Token(xxx,xxx)

これで、Twitter (Provider) の API をアプリ(Consumer)が呼び出すのに必要なアクセストークンが手に入ったことになる。

5. API の呼び出し

では、Twitter からフォロワーを取得(Twitter API Wiki / Twitter REST API Method: statuses followers)してみる。

API の呼び出しに必要な情報は、Consumer の情報(consumer)と、先程入手したアクセストークン(accessToken)となる。

scala> Http("http://api.twitter.com/1/statuses/followers.xml").oauth(consumer, accessToken).asString
res23: java.lang.String = 
<?xml version="1.0" encoding="UTF-8"?>
<users type="array">
<user>
  <id>99999</id>
  <name>OOOOO</name>
  <screen_name>aaaaa</screen_name>
  <location>xxxx</location>
  <description>xxxx...

OKだ。

OAuth を利用したアプリを利用する利用者としての留意点

今回、OAuth を試してみて思ったのだが、確かに、利用者にとっても、アプリ提供者にとっても便利でうまい仕組みではあるが、OAuth の流れの Consumer 登録のところでちょっと触れたように、Twitter とアプリの間での信頼関係は構築されていない、という点には、利用者は意識をしておくべきだと思う。

利用者がアプリに Twitter へのアクセス権限の委譲を認可した場合、アプリ側では認可された機能で何でもできてしまう。 アプリ提供者がアプリの機能提供は仮の姿で、実は、情報搾取が目的であった場合、利用者は何も気づかずに、見られることは無いと思っている DM の内容を抜かれていたりすることもあるかもしれない。

参考にしたサイト

blog comments powered by Disqus