TwitterのOAuthバグを攻略
Twitter の API がクソであることは、数年前から既知の事実でしたが、まさか OAuth の仕様すら無視しているとは思ってもいませんでした。というのが 1 月あたりの話ですが、比較できるコードが書けたのでブログに書きます。
人類史上最悪のコミット
まずはこちらをご覧ください。
このコミットは
Twitter検索でエラーが出るのはCoreTweetが悪いのか否か
— JZ5 (@jz5) January 28, 2015
— JZ5 (@jz5) January 28, 2015
を受けて生まれた産物ですが、かなり強引なことをしました。ええ、それはもう、ね?@ch3cooh Could not authenticate you ってなるやろ?
— JZ5 (@jz5) January 28, 2015
何が起こっていたのか
最初は誰もが
.NET 4.5 から Uri クラスが :
を何故かアンエスケープしてしまう仕様になったせいで、 Twitter サーバーがエスケープされてないからエラーにしてる。
そう思っていました。ですが、現実はそんなに甘くなかった。実際には
Twitter サーバーは URI のクエリ部分や、リクエストボディをアンエスケープ→再エスケープせず、そのまま OAuth のシグネチャ作成に使用するため、クライアントでは :
はエスケープされた状態でシグネチャ作成をしているが Twitter サーバーでは :
のままシグネチャを作成するからエラーになる。
という大変悲惨なことになっていました。
というわけで
azyobuzin による OAuth 実装最新作です。
var handler = new TwitterOAuthHttpMessageHandler(new HttpClientHandler()) { ConsumerKey = "", ConsumerSecret = "", OAuthToken = "", OAuthTokenSecret = "" }; var client = new HttpClient(handler); // 「from:azyobuzin ねむい」で検索 var res = await client.GetAsync("https://api.twitter.com/1.1/search/tweets.json?q=from:azyobuzin%20%E3%81%AD%E3%82%80%E3%81%84");
この例では、 TwitterOAuthHttpMessageHandler
では動きますが、 OAuthHttpMessageHandler
では 401 が返って来ます。
まとめ
Twitter はクソ。でも今から仕様変えられたらそれはそれで困る(きっと中の人も気づいてるけどそうしてるんじゃないかな…)。
追記: DotNetOpenAuth は OAuthHttpMessageHandler 側の実装です。