技術的なやつ

技術的なやつ

0.2 OAuth認証(PINコード)

計算機科学実験及び演習4で、C#を用いたTwitter REST APIを利用するライブラリ制作を行った。
OAuth認証についてはライブラリを用いて良いということだったが、Twitter用にOAuth認証するライブラリは大体タイムライン取得やつぶやきも出来るようになってて、あまり意味が無いと感じたので、Google先生が提供しているOAuthBaseを利用して、割と一から認証処理を書いた。
おかげで、OAuth認証が何をやっているのかが分かったので、メモ書き程度の記事にしてみようと思う。
なお、今回扱うOAuth認証はPINコードを用いるもので、バージョンは1.0である。

OAuth1.0(PINコード)の流れ(見た目)

ブラウザアプリの場合は必要ないので、あまり見かけることはないが、数字を入力させる認証方法である。
具体的には、Twitterでは以下の様な流れになる。

  1. ブラウザ立ち上げ
  2. Twitterにログイン
  3. アプリと連携させるか選択
  4. PINコード(7桁の数字)を表示する
  5. アプリ内にPINコードを入力
  6. 認証完了

これが内部で何を行っているのかを探る。

OAuth1.0(PINコード)の流れ(中身)

まず、OAuth認証で重要なsignatureについて述べる。

signature

signatureはBase64形式のハッシュ値である。サーバとクライアントでこの値が一致していれば認証が通る。
signatureは、基礎値となるsignature_base文字列と、鍵となるkey文字列をHMAC-SHA1でハッシュ化したものをさらにBase64に変換した文字列となっている。

signature_base

基礎値となる文字列は、以下の情報を基に生成される。

  • URL(パラメータ含む)
  • consumer_key
  • access_token
  • timestamp
  • nonce

consumer_keyはアプリケーションが持つ鍵の一つである。access_tokenはユーザが各自持つ鍵の一つである。nonceはランダム文字列である。

key

keyは、以下の情報を基に生成される。

  • consumer_secret
  • access_token_secret

これらを繋げてハッシュ化したものが鍵となる。

TwitterにおけるOAuth認証の流れ

request_token

ユーザは、アプリケーションの持つconsumer_keyおよびconsumer_secretしか情報を持っていない。よって、まずはaccess_tokenおよびaccess_token_secretを取得する必要がある。
そこで、access_tokenおよびaccess_token_secretを空の文字列としたsignatureをTwitter側に送信し、Twitterが生成したaccess_tokenおよびaccess_token_secretを受け取る。
signatureの受け渡しでは、同時に基礎文字列の材料も全てパラメータで受け渡す。つまり、パラメータさえ見ればsignature_baseは簡単に求められる。しかし、鍵の基となる情報は送受信しないため(Twitterとユーザが個人で持っている)、安全性が保証されるわけである。
この段階は、「そのアプリケーションに、渡したaccess_tokenおよびaccess_token_secretを持つ認証待ちユーザがいる」という意味を持つ。

TwitterログインとPINコード入力

ここで、ユーザにはTwitterにログインしてもらう。ログイン後、ユーザがアプリ連携を認めると、7桁のPINコードが表示される。アプリケーションは、このPINコードを受け取る。

access_token

先ほど受け取ったaccess_tokenおよびaccess_token_secretは、request_tokenおよびrequest_token_secretと呼ぶ。これらのリクエストトークンを用いて再びsignatureを求める。このsignatureと、先ほど受け取ったPINコードを、再びTwitterに送信し、Twitterから新しいaccess_tokenおよびaccess_token_secretを受け取る。これがAPIを叩くときのOAuth認証に使われるトークンとなる。
この段階は、「Twitterでログインされた、確かなユーザが認証された」という意味を持つ。

APIを叩く

APIを叩く際は、signature_baseの生成に必要な情報と、signatureをTwitterに送信する。
先ほどと同様、signature_baseはパラメータから簡単に生成できるが、signature生成のための鍵はお互い送受信してないデータを用いて生成するため、安全性が保証されるわけである。

雑感

要するに、

  • signature(signature_baseとkeyを使ったハッシュ)を照合させて認証する
  • signature_baseは固定文字列とタイムスタンプとランダム文字列を用いて生成される
  • keyはサーバ・クライアントがお互いローカルに保持する2つの文字列を用いて生成される
  • 2つの鍵は、アプリケーションの鍵とユーザの鍵
  • この2段階認証によって特定のアプリ上の特定のユーザが認証できる

というわけであるが、access_token_secretは最初の一回はサーバ側からクライアント側に送信される必要があるわけで、少し微妙な認証方式だと思う。

Rubybot作ってた時は、意味もわからずconsumer_key・consumer_secret・access_token・access_token_secretを入力していたが、今回の実験でその利用法が分かって良かった。

全然関係ない話になるが、RSA暗号はこの「鍵配送問題」を解決した画期的な暗号である。次回の記事で解説しようと思う。