かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Twitterにログインするまでの道のり(OAuthなんて嫌いだ!)

いい時代になりました。 id:neueccさんの、AsyncOAuthを使えば簡単にTwitterの認証を突破できる…。が!!Twitter初心者なんで使い方がよくわからなかったのでメモっておきます。

アプリの登録

  • Twitterの開発者向けサイトでログインします。
  • 右上の自分のアイコンからMy applicationsを選びます。
  • 各種項目を埋めていきます
    • Name: 名前
    • Description: 概要
    • Website: まぁアプリのページとか
    • Callback URL: 自分のドメインのサイトのURLでも入れておいて。適当でも動くっぽいけど…。
    • 最後の規約を読んで、OKならチェックを入れて Create your Twitter application

Callback URLは、後でアプリで使うので控えておきましょう。

キーの取得

  • アプリの登録が出来たらアプリのページにいくので、API Keysのタブを選びます。
  • API key(俗にConsumerKey)とAPI secret(俗にConsumerKeySecret)を控えておきます

アプリで認証を通す

Windowsストアアプリを新規作成したら迷わず、NuGetでAsyncOAuthを入れます。そして、App.xaml.csのOnLaunchedメソッドの先頭に以下のコードを書きます。

// Windows Store App(めんどうくせえええええ)
AsyncOAuth.OAuthUtility.ComputeHash = (key, buffer) =>
{
    var crypt = Windows.Security.Cryptography.Core.MacAlgorithmProvider.OpenAlgorithm("HMAC_SHA1");
    var keyBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(key);
    var cryptKey = crypt.CreateKey(keyBuffer);

    var dataBuffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(buffer);
    var signBuffer = Windows.Security.Cryptography.Core.CryptographicEngine.Sign(cryptKey, dataBuffer);

    byte[] value;
    Windows.Security.Cryptography.CryptographicBuffer.CopyToByteArray(signBuffer, out value);
    return value;
};

コメントの気持ち大事なので忘れないようにコピペしましょう。

後のコードはこんな感じ。認証してTwitterAPIに触れるHttpClientがとれるまでのコードをべたっと書きました。

// コピペしたキー(もう消してるから使えないけど)
var consumerKey = "2UHG3NsP6dKvAOHVP5xOvsizj";
var consumerKeySecret = "y94OwzrXRfhYKRGiCyGhlGWcbqMI64mcck8ptXVtZB8QnR9KVm";

// コールバックURL(アプリ登録したときに入力したやつ)
var callbackUrl = "http://okazuki.hogehoge.fuga"; // ちゃんとしたURLを指定しましょう

// 認証に使う一連のAPIのURL
var requestTokenUrl =  "https://api.twitter.com/oauth/request_token";
var authorizeUrl = "https://api.twitter.com/oauth/authorize";
var accessTokenUrl = "https://api.twitter.com/oauth/access_token";

// AsyncOAuthにお願いしてパラメータを作ってもらう
var param = OAuthUtility.BuildBasicParameters(
    consumerKey,
    consumerKeySecret,
    requestTokenUrl,
    HttpMethod.Post);

// 認証のめんどくさいことをしてくれる人を作る
var authrizer = new OAuthAuthorizer(consumerKey, consumerKeySecret);

// リクエストトークンというものを貰う
var tokenResponse = await authrizer.GetRequestToken(requestTokenUrl);
var requestToken = tokenResponse.Token;

// 認証画面のURLを貰う
var pinRequestUrl = authrizer.BuildAuthorizeUrl(authorizeUrl, requestToken);

// WebAuthenticationBrokerを使って認証画面を出す
var result = await WebAuthenticationBroker.AuthenticateAsync(
    WebAuthenticationOptions.None,
    new Uri(pinRequestUrl),
    new Uri(callbackUrl));

// 結果からHttpのパラメータを抜き取る
var query = result.ResponseData.Split('?')[1];
var parameters = new Dictionary<string, string>();
foreach (var token in query.Split('&'))
{
    var keyValue = token.Split('=');
    parameters[keyValue[0]] = WebUtility.UrlDecode(keyValue[1]);
}

// アクセストークンを取得する
var accessToken = await authrizer.GetAccessToken(accessTokenUrl, requestToken, parameters["oauth_verifier"]);

// APIにアクセスするためのHttpClientを取得する
var client = OAuthUtility.CreateOAuthClient(
    consumerKey,
    consumerKeySecret,
    accessToken.Token);

この後に例えばこんなコードを書くとHomeタイムラインがとってこれます。

var res = await client.GetAsync("https://api.twitter.com/1.1/statuses/home_timeline.json");
Debug.WriteLine(await res.Content.ReadAsStringAsync());