Gauche で OAuth
Twitter が OAuth という認証手続きを採用したそうだ。 現在の Basic 認証は近く廃止予定だそうで、 Twitter 関連ソフトは OAuth 対応を余儀なくされている。 OAuth についてとりあげているブログ記事もちらほらと見掛ける。
流行に乗ろうというわけでもないが、 Gauche で OAuth 認証 (コンシューマ側) のコードを書いてみた。 oauth_token とかを取得するあたりまでだけだが、署名の部分だけ使いまわせばあとは特に面倒なこともないだろう。
コンシューマキーやコンシューマ秘密鍵は (当然だが) 各自で取得して欲しい。
(use rfc.http) (use rfc.sha) (use rfc.hmac) (use rfc.base64) (use www.cgi) (use math.mt-random) (use gauche.uvector) (define consumer-key "ここにコンシューマキー") (define consumer-secret "ここにコンシューマ秘密鍵") (define (uri-encode-string str) (call-with-string-io str (lambda(in out) (while (read-char in) (compose not eof-object?) => ch (if (char-set-contains? #[a-zA-Z0-9.~_-] ch) (write-char ch out) (format out "%~2,'0X" (char->integer ch))))))) (define (time-stamp) (number->string (sys-time))) (define (random-string) (let ((random-source (make <mersenne-twister> :seed (sys-time))) (v (make-u32vector 10))) (mt-random-fill-u32vector! random-source v) (digest-hexify (sha1-digest-string (x->string v))))) (define (query-compose query) (string-join (map (cut string-join <> "=") query) "&")) (define (signature method uri info :optional (token-secret "")) (let* ((query-string (query-compose info)) (signature-basic-string (string-append method "&" (uri-encode-string uri) "&" (uri-encode-string query-string)))) (uri-encode-string (base64-encode-string (hmac-digest-string signature-basic-string :key #`",|consumer-secret|&,|token-secret|" :hasher <sha1>))))) (define query `(("oauth_consumer_key" ,consumer-key) ("oauth_nonce" ,(random-string)) ("oauth_signature_method" "HMAC-SHA1") ("oauth_timestamp" ,(time-stamp)) ("oauth_version" "1.0"))) (write (let1 s (signature "POST" "http://twitter.com/oauth/request_token" query) (receive (status header body) (http-post "twitter.com" "/oauth/request_token" (query-compose `(,@query ("oauth_signature" ,s)))) (cgi-parse-parameters :query-string body))))
特に注意が必要なのは Gauche の uri-encode-string をそのまま使っては駄目だということだ。 Gauche の uri-encode-string はエンコード結果の16進数を小文字で出力するが、 OAuth はこのとき大文字であることを期待する。
URI について定めている RFC3986 では大文字でも小文字でもかまわないことになっているので、他の言語 (ライブラリ) でもそういうものがあるかもしれない。 これにハマってずいぶんと時間を浪費してしまった。
Document ID: 9b2264f132bc89fb999faf671784d6c1