なか日記

一度きりの人生、楽しく生きよう。

ASP.NET Identity:Twitter認証時の情報でツイートする方法

この前、Twitter認証する方法を紹介しましたが、今回はその時の情報からTwitter APIを使ってツイートしてみたいと思います。

Access tokenとAccess token secretを取得する

前回のTwitterアプリケーション登録時に発行されているAPI keyとAPI secretはもちろん必要ですが、これに加えてユーザ毎に払い出されるAccess tokenとAccess token secretが必要です。

Access tokenとAccess token secretは次の様なコードで取得することができます。

Startup.Auth.csの修正

認証時にTwitterからAccess tokenとAccess token secretが通知されますが、標準で用意されていたコードでは参照できません。以下のように認証が完了した際に一時的に保存してあげる必要があります。

//app.UseTwitterAuthentication(
//   consumerKey: "{API key の値}",
//   consumerSecret: "{API secret の値}");
var options = new TwitterAuthenticationOptions();
options.ConsumerKey = "{API key の値}";
options.ConsumerSecret = "{API secret の値}";
options.Provider = new TwitterAuthenticationProvider()
{
    OnAuthenticated = async (context) =>
    {
        context.Identity.AddClaim(new Claim("ExternalAccessToken", context.AccessToken));
        context.Identity.AddClaim(new Claim("ExternalAccessTokenSecret", context.AccessTokenSecret));
    }
};
app.UseTwitterAuthentication(options);

AccountController.csの修正

Access tokenとAccess token secretを一時的に保存しましたが、一連の認証動作が終わると捨てられてしまいます。その為、初回ログイン(ユーザ登録)時に以下のように永続化を行います。

public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
{
    if (User.Identity.IsAuthenticated)
    {
        return RedirectToAction("Index", "Manage");
    }

    if (ModelState.IsValid)
    {
        // 外部ログイン プロバイダーからユーザーに関する情報を取得します
        var info = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (info == null)
        {
            return View("ExternalLoginFailure");
        }
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        var result = await UserManager.CreateAsync(user);
        if (result.Succeeded)
        {
            result = await UserManager.AddLoginAsync(user.Id, info.Login);
            if (result.Succeeded)
            {
                // ユーザ情報の登録が完了してから、AccessTokenとAccessTokenSecretを永続化する
                var claimsIdentity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
                var claims = claimsIdentity.Claims;
                foreach (var claim in claims)
                {
                    if ((claim.Type == "ExternalAccessToken") || (claim.Type == "ExternalAccessTokenSecret"))
                        await UserManager.AddClaimAsync(user.Id, claim);
                }
                // ここまで

                await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                return RedirectToLocal(returnUrl);
            }
        }
        AddErrors(result);
    }

    ViewBag.ReturnUrl = returnUrl;
    return View(model);
}

動作確認してみる

Twitterからログインして、メールアドレスを入力、ユーザ登録が完了すると AspNetUserClaims テーブルに Access token と Access token secret が保存されていると思います。

f:id:nakaji999:20140912023340p:plain

後はこれを使ってツイートすれば良いだけですね。

Twitterアプリケーションの設定変更

https://apps.twitter.com/ から、該当アプリケーションの Permission を「Read and Write」にしておく必要があります。

f:id:nakaji999:20140912023935p:plain

ツイートしてみる

CoreTweetのインストール

ツイートするためのライブラリはいつもの様に CoreTweet を使用しますので、 パッケージマネージャのコンソールから以下のコマンドでインストールを行います。

PM> Install-Package CoreTweet

ツイートする処理を書く

AspNetUserClaims テーブルに格納している Access token と Access token secret を使ってツイートします。

var usermgr = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var claims = await usermgr.GetClaimsAsync(User.Identity.GetUserId());

string accessToken = "", accessTokenSecret = "";

var firstOrDefault = claims.FirstOrDefault(x => x.Type == "ExternalAccessToken");
if (firstOrDefault != null) // TokenとTokenSecretはペアで登録されるのでnullチェックは片方のみ行う
{
    accessToken = firstOrDefault.Value;
    accessTokenSecret = claims.FirstOrDefault(x => x.Type == "ExternalAccessTokenSecret").Value;
}

var token = Tokens.Create("{API key の値}", "{API secret の値}", accessToken, accessTokenSecret);
token.Statuses.Update(status => "テスト");

参考

今回の方法は松崎 剛さんのブログを参考にさせて頂きました。細かい話についてはこちらを見て頂くのがいいと思います。