twicliのOAuth対応

4/11にOAuth認証に対応したtwicliを公開しました。API使用回数が150→350回に増えるほか、セキュリティも改善します。何より6月頃?にBASIC認証はobsoleteになって使えなくなる予定ですので、移行が必要です。


OAuth版のtwicliは、http://www.geocities.jp/twicli/ から「twicli起動(OAuth)」をクリックすれば利用できます。ブックマークレットとして登録して選択してもOKです。


なお、本体のアドレスを http://twicli.neocat.jp/twicli.html に変更しました。(設定や認証情報を保存するlocalStorageがドメイン毎にしかアクセスコントロールできないため。)この影響で以前のBASIC認証版の設定が引き継がれません。お手数ですが、手動で引き継いで下さい。


OAuth版もBASIC認証版と同様に、JavaScript only、Twitterとブラウザ間で直接通信し、ASPサーバ等は経由しない構成を維持しています。
以下では、OAuth対応のために行ったテクニカルな内容を書いてみます。

OAuthのものすごくおおざっぱな説明

OAuth認証APIを呼び出す際の仕組みをものすごくおおざっぱに説明してみます。


まず鍵となる文字列のペア(token, secretと言います)がアカウント/クライアントごとに発行されます*1
クライアントはアクセス時に、リクエストの内容にこの文字列をくっつけてハッシュ値を計算し、それをリクエストとともに送ります。たとえば、token/secretをaaaaa/bbbbbとすると、http://api.example.com/api.json に data=123 を送るときには、

http://api.example.com/api.json?data=123&oauth_secret=bbbbb&oauth_token=aaaaa

という文字列のSHA1ハッシュ値を計算します(引数の順序の影響を受けないよう辞書順でソートします)。例えばこれが f0fd9a になったとすると、secretのかわりにこのハッシュ値を署名としてつけて、

http://api.example.com/api.json?data=123&oauth_signature=f0fd9a&oauth_token=aaaaa

というURLにアクセスします。この署名はsecretを知らないと生成できず、また署名からsecretを逆算することも(ハッシュの一方向性により)できないため、認証に使えるというような雰囲気です。


これだけだとアクセス先URLを盗み見て真似すれば他者もアクセスできてしまうので、実際には同じURLは一度しか使えないようにする工夫*2や、クライアント自身の認証があったりしてもっと複雑です。詳しい仕様は http://oauth.net/core/1.0a/ を見て下さい。


(間違いがあるかも。ご指摘お待ちしてます。)


twicliでは、ハッシュ値の計算等をJavaScriptで行っています。これはPaul Johnston氏のsha1.jsを、John Kristian氏のoauth.jsを経由して利用させて頂いています。これらのコードは http://oauth.googlecode.com/svn/code/javascript/ から入手できます。ライセンスはそれぞれ BSDライセンスApacheライセンスです。

token/secretの取得

twicliの初回起動時には、OAuth認証用のtoken/secretを取得するための認証が求められます。現在twicliは2種類の方法でOAuthを行うことができます。


1つはWebブラウザ上で動くJavaScriptのみで認証情報を取得する方法で、ブラウザ⇔Twitterで直接通信して認証します。ただし、JavaScriptのセキュリティ制約上(XSS防止のため)、Twitterから送られてきた認証情報は、インラインフレームとして表示はできてもJavaScriptからアクセスできないため、ユーザにコピー&ペーストしてもらう操作が2回*3必要になります。

なおこの方法は、上記の oauth.js に付属のexampleを改良したものになっています。


ユーザがコピー&ペーストをする手間を省くために、twicliホスティングしているサーバ上でOAuth認証を行ってその結果をクライアントに引き継ぐ方法も用意しています、が、本当はセキュリティ的にはあまりよろしくないです*4

Twitter APIのGET/POST

基本的に今まで通り、GETはJSONP(scriptタグの動的生成)、POSTはインラインフレームを作ってそこをtargetに指定してフォームをsubmitするという方法をとっています。

なお、GET時はTwitter APIの仕様にある「suppress_response_code」を使って、エラーがあっても"200 OK"を返してもらうようにし、JavaScriptでエラーハンドリングできるようにしています(といってもalertが出るだけですが)。

BASIC認証の時は、これを指定すると"403 Forbidden"すら返らないために、ブラウザがBASIC認証情報を送信しようとしないという問題のせいで、エラーをJavaScriptに持ち込むことすらできていませんでした…(汗


BASIC認証と比べると、かなりブラウザの仕様から切り離されたので、たまに要望を頂くマルチアカウント対応とかもできるはずです。がどういうUIにしたものやら…(´゜ω゜`?)

その他の変更点

ついでにtwicli.htmlからcssJavaScriptを分離したり、画像やmp3ファイルをディレクトリに分けるなど、少し整理しました。
twicliは公開当初は(cssJavaScriptを含めて)100行くらいのHTMLファイル1つだけだったのですが、随分と成長 肥大化したものです。。


あと外部スクリプトをロードする際に確認を出すようにしました(プラグインからもOAuthの認証情報にアクセスできてしまうなど、セキュリティ上の懸念があるためです)。ただ外部のプラグインがダメというわけではなく、いろいろ作って頂くのは相変わらず大歓迎ですので誤解なきよう。本体と一緒においてくれとかもwelcomeです。


なおソースは今まで通りCodeReposgithubにあります。ライセンスはMITライセンスです。

*1:クライアントごとの鍵なので、全サービスに共通になってしまうパスワードと違って、クライアント単位にアクセス範囲を限定できるメリットがあります

*2:単調増加するタイムスタンプを含めなければならない。

*3:それぞれ、OAuth認証を求めるリクエスト・トークン取得時と、承認の結果得られるアクセス・トークンの取得時。

*4:サーバの都合でその際の通信がSSLぢゃないとか……。